React + MotionFilter

Segmented Control

Eine Reihe von Optionen, bei der eine farbige Pille zu der gleitet, die du auswählst.

Einstellungen

3

Code

import { useId, useState } from "react";
import { motion } from "framer-motion";

const sizeMap = {
  sm: { pad: "px-3 py-1.5", text: "text-xs" },
  md: { pad: "px-4 py-2", text: "text-sm" },
  lg: { pad: "px-5 py-2.5", text: "text-base" },
} as const;

interface SegmentedControlProps {
  accent?: string;
  size?: keyof typeof sizeMap;
  options?: string[];
  value?: string;
  onChange?: (value: string) => void;
}

export default function SegmentedControl({
  accent = "#0071e3",
  size = "md",
  options = ["Design", "Code", "Audio"],
  value,
  onChange,
}: SegmentedControlProps) {
  const [internal, setInternal] = useState(options[0] ?? "");
  const layoutId = useId();
  const active = value ?? internal;
  const current = options.includes(active) ? active : options[0];
  const s = sizeMap[size];

  const select = (o: string) => {
    if (value === undefined) setInternal(o);
    onChange?.(o);
  };

  return (
    <div className="flex rounded-full bg-black/5 p-1 dark:bg-white/10">
      {options.map((o) => (
        <button
          key={o}
          type="button"
          aria-pressed={current === o}
          onClick={() => select(o)}
          className={`relative rounded-full font-medium ${s.pad} ${s.text}`}
        >
          {current === o && (
            <motion.span
              layoutId={layoutId}
              className="absolute inset-0 rounded-full"
              style={{ backgroundColor: accent }}
              transition={{ type: "spring", stiffness: 380, damping: 30 }}
            />
          )}
          <span
            className="relative z-10"
            style={{ color: current === o ? "#ffffff" : undefined }}
          >
            {o}
          </span>
        </button>
      ))}
    </div>
  );
}

Prompt für KI

Füg ihn in ChatGPT, Claude oder Cursor ein und der Baustein wird mit diesen Einstellungen an dein Projekt angepasst, auch ohne React.

Mehr aus Filter

Wofür du ihn nutzen kannst

Ein Segmented Control ist zum Umschalten von Ansichten da, nicht zum Filtern: „Monatlich / Jährlich“ auf einer Preisseite, „Liste / Karte“ bei einer Wohnungssuche oder „Tag / Woche / Monat“ im Kalender. Weil die Pille gleitet statt zu springen, sieht man, was sich geändert hat. Greif zu diesem Segmented Control, wenn es zwei bis vier Optionen gibt.

Ab fünf Optionen wird es eng, vor allem auf dem Handy. Kürz die Liste oder nimm Tabs. Wähl eine Akzentfarbe mit genug Kontrast zu Weiß, denn das ausgewählte Label wird weiß.