{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "tabs",
  "title": "Tabs",
  "description": "Tabs on radix-ui with 3 variants (solid segmented, line underline, pill) and 2 sizes (sm, md). Variant and size flow from TabsList to every trigger via context. Exports Tabs, TabsList, TabsTrigger, TabsContent.",
  "dependencies": [
    "class-variance-authority@^0.7.1",
    "radix-ui@^1.6.1"
  ],
  "registryDependencies": [
    "@ai2/tokens",
    "@ai2/primitives"
  ],
  "files": [
    {
      "path": "registry/ai2/ui/tabs.tsx",
      "content": "\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport { Tabs as TabsPrimitive } from \"@/registry/ai2/ui/primitives\"\r\nimport { cva, type VariantProps } from \"class-variance-authority\"\r\n\r\nimport { cn } from \"@/lib/utils\"\r\n\r\nfunction Tabs({\r\n  className,\r\n  ...props\r\n}: React.ComponentProps<typeof TabsPrimitive.Root>) {\r\n  return (\r\n    <TabsPrimitive.Root\r\n      data-slot=\"tabs\"\r\n      className={cn(\"flex flex-col gap-2\", className)}\r\n      {...props}\r\n    />\r\n  )\r\n}\r\n\r\nconst tabsListVariants = cva(\"inline-flex w-fit items-center text-muted-foreground\", {\r\n  variants: {\r\n    variant: {\r\n      solid: \"justify-center gap-1 rounded-lg bg-surface-3 p-1\",\r\n      line: \"gap-4 border-b border-border\",\r\n      pill: \"justify-center gap-1\",\r\n    },\r\n    size: {\r\n      sm: \"h-8\",\r\n      md: \"h-9\",\r\n    },\r\n  },\r\n  defaultVariants: { variant: \"solid\", size: \"md\" },\r\n})\r\n\r\ntype TabsSize = \"sm\" | \"md\"\r\ntype TabsVariant = \"solid\" | \"line\" | \"pill\"\r\n\r\nconst TabsContext = React.createContext<{ variant: TabsVariant; size: TabsSize }>({\r\n  variant: \"solid\",\r\n  size: \"md\",\r\n})\r\n\r\ninterface TabsListProps\r\n  extends React.ComponentProps<typeof TabsPrimitive.List>,\r\n    VariantProps<typeof tabsListVariants> {}\r\n\r\n/* WCAG 1.4.4 (200% text): the tab strip is `w-fit`, so as text grew it widened\r\n   the PAGE - at 375px the body went to 429px and the whole page scrolled\r\n   horizontally. The fix is to move scrolling INSIDE the strip itself.\r\n\r\n   Why a wrapper div: putting `overflow-x-auto` on the list itself is not\r\n   enough. Per CSS, once one axis is `auto` the other cannot stay `visible`\r\n   and also becomes `auto`; the VERTICAL axis would be clipped too, and in the\r\n   `line` variant the trigger and the list share the same height (h-9), so the\r\n   focus ring (3px) would be cut off. The `-m-1 p-1` pair on the wrapper opens\r\n   4px on all four sides (the smallest step on the scale, enough for a 3px\r\n   ring) and leaves the outer measurements THE SAME - the negative margin\r\n   cancels the padding.\r\n\r\n   The scrollbar is hidden: if `overflow-x-auto` painted a visible bar the\r\n   strip height would change and the fixed h-8/h-9 layout would break. Keyboard\r\n   access is unaffected - Radix moves with arrow keys and scrolls the focused\r\n   tab into view; mouse and trackpad scrolling still work. */\r\nfunction TabsList({ className, variant, size, ...props }: TabsListProps) {\r\n  const v = variant ?? \"solid\"\r\n  const s = size ?? \"md\"\r\n  return (\r\n    <TabsContext.Provider value={{ variant: v, size: s }}>\r\n      <div\r\n        data-slot=\"tabs-list-viewport\"\r\n        className=\"-m-1 max-w-full overflow-x-auto p-1 [scrollbar-width:none] [&::-webkit-scrollbar]:hidden\"\r\n      >\r\n        <TabsPrimitive.List\r\n          data-slot=\"tabs-list\"\r\n          data-variant={v}\r\n          data-size={s}\r\n          className={cn(tabsListVariants({ variant, size, className }))}\r\n          {...props}\r\n        />\r\n      </div>\r\n    </TabsContext.Provider>\r\n  )\r\n}\r\n\r\nconst tabsTriggerVariants = cva(\r\n  \"inline-flex items-center justify-center gap-1.5 whitespace-nowrap font-medium outline-none transition-colors duration-(--motion-fast) focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:size-4 [&_svg]:shrink-0 [&_i]:shrink-0 [&_i]:text-base [&_i]:leading-none\",\r\n  {\r\n    variants: {\r\n      variant: {\r\n        solid:\r\n          \"rounded-md px-3 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm\",\r\n        line: \"-mb-px border-b-2 border-transparent px-1 data-[state=active]:border-brand data-[state=active]:text-foreground\",\r\n        pill: \"rounded-full px-3.5 data-[state=active]:bg-brand data-[state=active]:text-brand-foreground\",\r\n      },\r\n      size: {\r\n        sm: \"text-xs\",\r\n        md: \"text-sm\",\r\n      },\r\n    },\r\n    compoundVariants: [\r\n      { variant: \"solid\", size: \"sm\", class: \"h-6\" },\r\n      { variant: \"solid\", size: \"md\", class: \"h-7\" },\r\n      { variant: \"line\", size: \"sm\", class: \"h-8\" },\r\n      { variant: \"line\", size: \"md\", class: \"h-9\" },\r\n      { variant: \"pill\", size: \"sm\", class: \"h-6\" },\r\n      { variant: \"pill\", size: \"md\", class: \"h-7\" },\r\n    ],\r\n    defaultVariants: { variant: \"solid\", size: \"md\" },\r\n  }\r\n)\r\n\r\nfunction TabsTrigger({\r\n  className,\r\n  ...props\r\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\r\n  const { variant, size } = React.useContext(TabsContext)\r\n  return (\r\n    <TabsPrimitive.Trigger\r\n      data-slot=\"tabs-trigger\"\r\n      className={cn(tabsTriggerVariants({ variant, size, className }))}\r\n      {...props}\r\n    />\r\n  )\r\n}\r\n\r\nfunction TabsContent({\r\n  className,\r\n  ...props\r\n}: React.ComponentProps<typeof TabsPrimitive.Content>) {\r\n  return (\r\n    <TabsPrimitive.Content\r\n      data-slot=\"tabs-content\"\r\n      className={cn(\"flex-1 outline-none\", className)}\r\n      {...props}\r\n    />\r\n  )\r\n}\r\n\r\nexport { Tabs, TabsList, TabsTrigger, TabsContent, type TabsListProps }\r\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Set variant on TabsList; triggers inherit it via context. Use line for docs-style pages, pill for compact filters.",
  "categories": [
    "navigation",
    "disclosure"
  ],
  "type": "registry:ui"
}