{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "segmented-control",
  "title": "Segmented Control",
  "description": "A single-select toggle with a sliding indicator.",
  "files": [
    {
      "path": "registry/tealmac/segmented-control.tsx",
      "content": "\"use client\"\n\nimport { useId, useRef, useState, type HTMLAttributes } from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface SegmentedControlProps extends Omit<\n  HTMLAttributes<HTMLDivElement>,\n  \"onChange\" | \"defaultValue\"\n> {\n  options: { label: string; value: string }[]\n  value?: string\n  defaultValue?: string\n  onChange?: (value: string) => void\n}\n\n/**\n * SegmentedControl is a compact single-select toggle. A pill indicator slides\n * to the active option (transform-only, so it animates cheaply). Built as a\n * radiogroup with arrow-key navigation for keyboard and screen-reader users.\n */\nexport function SegmentedControl({\n  options,\n  value,\n  defaultValue,\n  onChange,\n  className,\n  ...props\n}: SegmentedControlProps) {\n  const groupId = useId()\n  const groupRef = useRef<HTMLDivElement>(null)\n  const [internal, setInternal] = useState(defaultValue ?? options[0]?.value)\n  const current = value ?? internal\n  const activeIndex = Math.max(\n    0,\n    options.findIndex((o) => o.value === current)\n  )\n\n  const select = (next: string) => {\n    if (value === undefined) setInternal(next)\n    onChange?.(next)\n  }\n\n  const move = (dir: 1 | -1) => {\n    const next = (activeIndex + dir + options.length) % options.length\n    select(options[next].value)\n    // Roving tabindex: focus follows the selection, otherwise focus would be\n    // left on a radio that just dropped out of the tab order.\n    groupRef.current\n      ?.querySelectorAll<HTMLButtonElement>('[role=\"radio\"]')\n      [next]?.focus()\n  }\n\n  return (\n    // Focus lives on the radios (roving tabindex), not on the group itself.\n    // eslint-disable-next-line jsx-a11y/interactive-supports-focus\n    <div\n      ref={groupRef}\n      role=\"radiogroup\"\n      className={cn(\"bg-muted relative inline-flex rounded-lg p-1\", className)}\n      onKeyDown={(e) => {\n        if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") {\n          e.preventDefault()\n          move(1)\n        } else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") {\n          e.preventDefault()\n          move(-1)\n        }\n      }}\n      {...props}\n    >\n      {/* sliding indicator */}\n      <span\n        aria-hidden\n        className=\"bg-background absolute inset-y-1 rounded-md shadow-sm transition-transform duration-200 ease-out\"\n        style={{\n          width: `calc((100% - 0.5rem) / ${options.length})`,\n          transform: `translateX(${activeIndex * 100}%)`,\n        }}\n      />\n      {options.map((o) => {\n        const active = o.value === current\n        return (\n          <button\n            key={`${groupId}-${o.value}`}\n            type=\"button\"\n            role=\"radio\"\n            aria-checked={active}\n            tabIndex={active ? 0 : -1}\n            onClick={() => select(o.value)}\n            className={cn(\n              \"focus-visible:ring-ring relative z-10 flex-1 rounded-md px-4 py-1.5 text-sm font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none\",\n              active\n                ? \"text-foreground\"\n                : \"text-muted-foreground hover:text-foreground\"\n            )}\n          >\n            {o.label}\n          </button>\n        )\n      })}\n    </div>\n  )\n}\n\nexport default SegmentedControl\n",
      "type": "registry:ui"
    }
  ],
  "type": "registry:ui"
}