{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toggle",
  "type": "registry:ui",
  "title": "Toggle",
  "description": "A two-state button (pressed / not-pressed) and a grouped form thereof (mutually-exclusive or multi-select). Wraps @base-ui/react/toggle and @base-ui/react/toggle-group; we own the surface (size, variant, focus ring) and Base UI owns the pressed-state…",
  "author": "ofri-peretz <https://github.com/ofri-peretz>",
  "categories": [
    "form",
    "primitive"
  ],
  "dependencies": [
    "@base-ui/react",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "https://ds.interlace.tools/r/theme.json",
    "https://ds.interlace.tools/r/cn.json"
  ],
  "files": [
    {
      "path": "registry/interlace-ui/toggle.tsx",
      "target": "components/ui/toggle.tsx",
      "type": "registry:ui",
      "content": "'use client';\n\nimport * as React from 'react';\n\n// @interlace/toggle v1.0.0 — Interlace design system.\n// Docs, props and live preview: https://ds.interlace.tools/c/toggle\n// What changed since: https://ds.interlace.tools/c/toggle#history\n// Generated banner — keep it, the upgrade diff reads this version.\n\n/**\n * @interlace/ui — Toggle + ToggleGroup\n *\n * A two-state button (pressed / not-pressed) and a grouped form thereof\n * (mutually-exclusive or multi-select). Wraps @base-ui/react/toggle and\n * @base-ui/react/toggle-group; we own the surface (size, variant, focus\n * ring) and Base UI owns the pressed-state machinery + ARIA.\n *\n * ## Anatomy\n *\n *   Toggle                           (button — data-min-viewport=320)\n *     └─ children                    (icon / text)\n *\n *   ToggleGroup                      (div — data-min-viewport=320, role=group or radiogroup)\n *     ├─ ToggleGroupItem\n *     ├─ ToggleGroupItem\n *     └─ ToggleGroupItem\n *\n * ## MIN_VIEWPORT — 320\n *\n * Toggles must reach the WCAG 2.5.5 target-size floor (24×24 CSS px). The\n * `sm` size below renders at 32×32, the smallest in the size enum.\n *\n * | Rule | Concept                          | Where in this file                                          |\n * | ---- | -------------------------------- | ----------------------------------------------------------- |\n * | R4   | Extends Base UI part props       | wrappers extend `React.ComponentProps<typeof BaseToggle/etc>` |\n * | R6   | data-slot per part               | toggle / toggle-group / toggle-group-item                   |\n * | R7   | cva + cn + ...rest               | `cn(toggleVariants({size,variant}), className)` + `{...props}` |\n * | R8   | Enums for size / variant         | size = sm|md|lg; variant = default|outline                  |\n * | R12  | Reuse over wrap                  | Base UI owns pressed state + ARIA                           |\n * | R14  | Declares min viewport            | `data-min-viewport={String(MIN_VIEWPORT)}` + exported const |\n * | R19  | Tokens only                      | bg-muted, bg-accent, text-foreground — semantic tokens      |\n * | R25  | Client component                 | Required — Base UI Toggle ships client hooks                |\n * | R26  | A11y from upstream               | role=button + aria-pressed handled by Base UI               |\n */\n\nimport { Toggle as BaseToggle } from '@base-ui/react/toggle';\nimport { ToggleGroup as BaseToggleGroup } from '@base-ui/react/toggle-group';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\nimport { cn } from '@/lib/utils';\n\nexport const MIN_VIEWPORT = 320 as const;\n\nconst toggleVariants = cva(\n  cn(\n    'inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors',\n    'hover:bg-muted hover:text-muted-foreground',\n    'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n    'disabled:pointer-events-none disabled:opacity-50',\n    'data-[pressed]:bg-accent data-[pressed]:text-accent-foreground',\n  ),\n  {\n    variants: {\n      variant: {\n        default: 'bg-transparent',\n        outline: 'border-border bg-transparent border shadow-sm hover:bg-accent hover:text-accent-foreground',\n      },\n      size: {\n        sm: 'h-8 px-2',\n        md: 'h-9 px-3',\n        lg: 'h-10 px-4',\n      },\n    },\n    defaultVariants: {\n      variant: 'default',\n      size: 'md',\n    },\n  },\n);\n\ntype ToggleProps = React.ComponentProps<typeof BaseToggle> &\n  VariantProps<typeof toggleVariants>;\n\nconst Toggle = React.forwardRef<\n  React.ElementRef<typeof BaseToggle>,\n  ToggleProps\n>(({ className, variant, size, ...props }, ref) => (\n  <BaseToggle\n    ref={ref}\n    data-slot=\"toggle\"\n    data-min-viewport={String(MIN_VIEWPORT)}\n    className={cn(toggleVariants({ variant, size, className }))}\n    {...props}\n  />\n));\nToggle.displayName = 'Toggle';\n\nconst ToggleGroup = React.forwardRef<\n  React.ElementRef<typeof BaseToggleGroup>,\n  React.ComponentProps<typeof BaseToggleGroup>\n>(({ className, ...props }, ref) => (\n  <BaseToggleGroup\n    ref={ref}\n    data-slot=\"toggle-group\"\n    data-min-viewport={String(MIN_VIEWPORT)}\n    // Base UI renders the wrapper as `role=\"group\" aria-orientation=\"…\"`,\n    // but ARIA 1.2 says `group` does NOT allow `aria-orientation` (only\n    // toolbar / radiogroup / menu / tree / listbox / select / tablist /\n    // separator / slider / scrollbar do). Promote the role to `toolbar`\n    // so the orientation announcement is valid AND the surface still\n    // reads as a self-contained group of related controls.\n    role=\"toolbar\"\n    className={cn('inline-flex items-center', className)}\n    {...props}\n  />\n));\nToggleGroup.displayName = 'ToggleGroup';\n\n// ToggleGroup uses Toggle children — there is no separate \"Item\" primitive in\n// Base UI's toggle-group API. Consumers compose <ToggleGroup><Toggle .../></ToggleGroup>.\n\nexport { Toggle, ToggleGroup, toggleVariants };\nexport type { ToggleProps };\n"
    }
  ],
  "meta": {
    "tier": "primitive",
    "client": true,
    "minViewport": 320,
    "loading": false,
    "version": "1.0.0",
    "since": "1.0.0"
  },
  "docs": "## @interlace/toggle\n\nInstalled to `components/ui/toggle.tsx`.\n\n```tsx\nimport { /* … */ } from '@/components/ui/toggle';\n```\n\nProps, a11y contract, live preview and source: https://ds.interlace.tools/c/toggle\n\nRequires the `@interlace/theme` CSS baseline (installed automatically as a registry dependency)."
}
