React + MotionFiltros

Control segmentado

Una fila de opciones en la que una píldora de color se desliza hasta la que eliges.

Ajustes

3

Código

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 = ["Diseño", "Código", "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 para IA

Pégalo en ChatGPT, Claude o Cursor y adaptará el bloque a tu proyecto con estos ajustes, aunque no uses React.

Más en Filtros

Dónde usarlo

El control segmentado sirve para cambiar de vista, no para filtrar: «Mensual / Anual» en una página de precios, «Lista / Mapa» en un buscador de pisos o «Día / Semana / Mes» en un calendario. Como la píldora se desliza en lugar de saltar, se entiende qué ha cambiado. Tira de este segmented control cuando haya entre dos y cuatro opciones.

Con más de cuatro opciones se queda apretado, sobre todo en el móvil, así que recorta la lista o pasa a pestañas. Elige un color de acento con buen contraste, porque el texto seleccionado se vuelve blanco.