{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"segmented-control","type":"registry:ui","title":"Segmented Control","description":"A compact single-choice control whose thumb slides to the selected option.","dependencies":["motion"],"registryDependencies":["https://ui.mekaigames.com/r/theme.json"],"files":[{"path":"components/ui/segmented-control.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { motion, useReducedMotion } from \"motion/react\";\nimport { useId, useState, type KeyboardEvent, type ReactNode } from \"react\";\n\nexport type SegmentOption = string | { value: string; label: ReactNode; disabled?: boolean };\n\ntype SegmentedControlProps = {\n  options: SegmentOption[];\n  /** Selected value, for controlled use. */\n  value?: string;\n  /** Selected value when uncontrolled. Defaults to the first option. */\n  defaultValue?: string;\n  onChange?: (value: string) => void;\n  size?: \"sm\" | \"md\" | \"lg\";\n  /** \"ink\" is a raised neutral thumb, \"accent\" fills it with the brand color. */\n  tone?: \"ink\" | \"accent\";\n  /** Accessible name of the group. */\n  label?: string;\n  className?: string;\n};\n\nconst SIZES = {\n  sm: \"h-7 px-3 text-xs\",\n  md: \"h-9 px-4 text-sm\",\n  lg: \"h-11 px-5 text-base\",\n};\n\n/** A compact single-choice control with a thumb that slides to the selected segment. */\nexport function SegmentedControl({\n  options,\n  value,\n  defaultValue,\n  onChange,\n  size = \"md\",\n  tone = \"ink\",\n  label = \"Options\",\n  className = \"\",\n}: SegmentedControlProps) {\n  const uid = useId();\n  const reduce = useReducedMotion();\n  const items = options.map((o) => (typeof o === \"string\" ? { value: o, label: o, disabled: false } : o));\n  const [internal, setInternal] = useState(defaultValue ?? items.find((i) => !i.disabled)?.value ?? \"\");\n  const selected = value ?? internal;\n  const hasSelection = items.some((i) => i.value === selected);\n\n  function choose(next: string) {\n    if (next === selected) return;\n    if (value === undefined) setInternal(next);\n    onChange?.(next);\n  }\n\n  function onKeyDown(e: KeyboardEvent<HTMLDivElement>) {\n    const enabled = items.filter((i) => !i.disabled);\n    if (enabled.length === 0) return;\n    const current = enabled.findIndex((i) => i.value === selected);\n    let next: (typeof items)[number] | undefined;\n    if (e.key === \"ArrowRight\" || e.key === \"ArrowDown\") next = enabled[(current + 1) % enabled.length];\n    else if (e.key === \"ArrowLeft\" || e.key === \"ArrowUp\") next = enabled[(current - 1 + enabled.length) % enabled.length];\n    else if (e.key === \"Home\") next = enabled[0];\n    else if (e.key === \"End\") next = enabled[enabled.length - 1];\n    if (!next) return;\n    e.preventDefault();\n    choose(next.value);\n    const index = items.indexOf(next);\n    e.currentTarget.querySelectorAll<HTMLButtonElement>('[role=\"radio\"]')[index]?.focus();\n  }\n\n  const thumb =\n    tone === \"accent\"\n      ? \"bg-ember shadow-[0_6px_18px_-8px_rgb(255_120_79/0.8)]\"\n      : \"bg-ink-600 shadow-[inset_0_1px_0_rgb(255_255_255/0.07),0_6px_16px_-6px_rgb(0_0_0/0.9)]\";\n  const activeText = tone === \"accent\" ? \"text-ink-950\" : \"text-bone\";\n\n  return (\n    <div\n      role=\"radiogroup\"\n      aria-label={label}\n      onKeyDown={onKeyDown}\n      className={`inline-grid auto-cols-fr grid-flow-col gap-1 rounded-xl border border-ink-600 bg-ink-900 p-1 ${className}`}\n    >\n      {items.map((item, i) => {\n        const checked = item.value === selected;\n        return (\n          <button\n            key={item.value}\n            type=\"button\"\n            role=\"radio\"\n            aria-checked={checked}\n            tabIndex={checked || (!hasSelection && i === 0) ? 0 : -1}\n            disabled={item.disabled}\n            onClick={() => choose(item.value)}\n            className={`relative whitespace-nowrap rounded-lg font-semibold transition-colors disabled:cursor-not-allowed disabled:opacity-40 ${SIZES[size]} ${\n              checked ? activeText : \"text-bone-dim hover:text-bone\"\n            }`}\n          >\n            {checked ? (\n              <motion.span\n                layoutId={`${uid}-thumb`}\n                aria-hidden=\"true\"\n                className={`absolute inset-0 rounded-lg ${thumb}`}\n                transition={reduce ? { duration: 0 } : { type: \"spring\", stiffness: 500, damping: 38 }}\n              />\n            ) : null}\n            <span className=\"relative\">{item.label}</span>\n          </button>\n        );\n      })}\n    </div>\n  );\n}\n"}]}