{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "continuous-tabs",
  "title": "Continuous tabs",
  "description": "Tabs where a pill slides to the one you pick, with arrow keys like a proper tab list.",
  "dependencies": [
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/manniche/continuous-tabs/continuous-tabs.tsx",
      "content": "// Based on Watermelon UI's “Continuous tabs” (MIT, © 2026 Watermelon Platform Contributors,\n// github.com/WatermelonCorp/watermelon-platform). Rewritten as an ARIA tablist with arrow keys.\nimport { LayoutGroup, MotionConfig, motion } from 'motion/react'\nimport { useId, useRef, useState, type KeyboardEvent } from 'react'\nimport { cn } from '@/lib/utils'\n\nexport type ContinuousTab = { id: string; label: string }\n\nexport type ContinuousTabsProps = {\n  tabs: ContinuousTab[]\n  /** Controlled active tab. */\n  value?: string\n  defaultValue?: string\n  onChange?: (id: string) => void\n  /** Read aloud for the whole row, e.g. \"Sections\". */\n  label?: string\n  className?: string\n}\n\n/** Tabs where a pill slides to the one you pick. Arrow keys, Home and End move between them. */\nexport function ContinuousTabs({ tabs, value, defaultValue, onChange, label, className }: ContinuousTabsProps) {\n  const [own, setOwn] = useState(defaultValue ?? tabs[0]?.id)\n  const active = value ?? own\n  const group = useId()\n  const refs = useRef<(HTMLButtonElement | null)[]>([])\n\n  const pick = (id: string) => {\n    setOwn(id)\n    onChange?.(id)\n  }\n\n  const onKey = (e: KeyboardEvent, i: number) => {\n    const n = tabs.length\n    const to = ({ ArrowRight: (i + 1) % n, ArrowLeft: (i - 1 + n) % n, Home: 0, End: n - 1 } as Record<string, number>)[e.key]\n    if (to === undefined) return\n    e.preventDefault()\n    refs.current[to]?.focus()\n    pick(tabs[to].id)\n  }\n\n  return (\n    <MotionConfig reducedMotion=\"user\">\n      <LayoutGroup id={group}>\n        <div role=\"tablist\" aria-label={label} className={cn('inline-flex max-w-full items-center gap-1 overflow-x-auto rounded-2xl border bg-card p-1.5 shadow-sm', className)}>\n          {tabs.map((tab, i) => {\n            const on = tab.id === active\n            return (\n              <button\n                key={tab.id}\n                ref={(el) => {\n                  refs.current[i] = el\n                }}\n                type=\"button\"\n                role=\"tab\"\n                aria-selected={on}\n                tabIndex={on ? 0 : -1}\n                onClick={() => pick(tab.id)}\n                onKeyDown={(e) => onKey(e, i)}\n                className=\"relative min-h-11 shrink-0 rounded-xl px-4 text-sm font-medium outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n              >\n                {on && (\n                  <motion.span\n                    layoutId=\"pill\"\n                    transition={{ type: 'spring', stiffness: 380, damping: 32 }}\n                    className=\"absolute inset-0 rounded-xl bg-foreground\"\n                  />\n                )}\n                <span className={cn('relative transition-colors duration-200', on ? 'text-background' : 'text-muted-foreground hover:text-foreground')}>\n                  {tab.label}\n                </span>\n              </button>\n            )\n          })}\n        </div>\n      </LayoutGroup>\n    </MotionConfig>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "meta": {
    "credit": "Adapted from Watermelon UI (MIT)."
  },
  "categories": [
    "navigation"
  ],
  "type": "registry:component"
}