{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toggle-group",
  "title": "Toggle-group",
  "description": "A toggle-group component.",
  "dependencies": [
    "class-variance-authority"
  ],
  "registryDependencies": [
    "@cubby-ui/separator",
    "@cubby-ui/toggle"
  ],
  "files": [
    {
      "path": "registry/default/toggle-group/toggle-group.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { ToggleGroup as BaseToggleGroup } from \"@base-ui/react/toggle-group\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Separator } from \"@/registry/default/separator/separator\";\nimport {\n  isIconOnly,\n  Toggle,\n  type ToggleProps,\n} from \"@/registry/default/toggle/toggle\";\n\n// A shell, as in Button Group, whose items latch. Insets are item borders,\n// 2px facing the shell's edge and 1px facing a neighbour; `of` counts items\n// only, so separators don't move the ends. Plate corners are the shell's\n// minus the 2px edge border.\nconst toggleGroupVariants = cva(\n  [\n    \"relative isolate flex w-fit items-stretch rounded-(--toggle-group-radius) data-[orientation=vertical]:flex-col\",\n    // Never narrower than its items; overflow is the container's to handle.\n    \"min-w-max\",\n    \"[--toggle-group-item-radius:max(0px,calc(var(--toggle-group-radius)-2px))]\",\n    // Small corners between neighbors, so pressed runs read as one control\n    \"[--toggle-group-inner-radius:min(3px,var(--toggle-group-item-radius))]\",\n    // Hover 8%, press 10%: black overlays (white in dark), not a cool-cast label\n    // tint. `pressedStyle` sets the pressed fill; override its variables to recolor.\n    \"[--toggle-group-highlight:var(--surface-active)] [--toggle-group-press:var(--surface-selected)]\",\n    // A row is the ladder height and items stretch to fill it.\n    \"data-[orientation=horizontal]:h-(--toggle-group-h) data-[orientation=horizontal]:[&>[data-slot=toggle-group-item]]:aspect-square\",\n    \"data-[orientation=horizontal]:[&>[data-slot=toggle-group-item]]:border-y-2 data-[orientation=horizontal]:[&>:nth-child(1_of_[data-slot=toggle-group-item])]:border-s-2 data-[orientation=horizontal]:[&>:nth-last-child(1_of_[data-slot=toggle-group-item])]:border-e-2\",\n    // A column is at least the ladder width; every item gets the row's\n    // paint height.\n    \"data-[orientation=vertical]:[&>[data-slot=toggle-group-item]]:box-content data-[orientation=vertical]:[&>[data-slot=toggle-group-item]]:h-[calc(var(--toggle-group-h)-4px)] data-[orientation=vertical]:[&>[data-slot=toggle-group-item]]:min-w-[calc(var(--toggle-group-h)-4px)]\",\n    \"data-[orientation=vertical]:[&>[data-slot=toggle-group-item]]:border-x-2 data-[orientation=vertical]:[&>:nth-child(1_of_[data-slot=toggle-group-item])]:border-t-2 data-[orientation=vertical]:[&>:nth-last-child(1_of_[data-slot=toggle-group-item])]:border-b-2\",\n    // A square hit area over the whole box, corners included, so hover\n    // never drops between items. Beside a separator it reaches the line.\n    \"[&>[data-slot=toggle-group-item]]:after:absolute [&>[data-slot=toggle-group-item]]:after:content-[''] [&>[data-slot=toggle-group-item]]:after:-inset-x-px [&>[data-slot=toggle-group-item]]:after:-inset-y-0.5 data-[orientation=vertical]:[&>[data-slot=toggle-group-item]]:after:-inset-x-0.5 data-[orientation=vertical]:[&>[data-slot=toggle-group-item]]:after:-inset-y-px\",\n    \"data-[orientation=horizontal]:[&>[data-slot=toggle-group-item]:has(+[data-slot=toggle-group-separator])]:after:-end-[5px] data-[orientation=horizontal]:[&>[data-slot=toggle-group-separator]+[data-slot=toggle-group-item]]:after:-start-[5px] data-[orientation=vertical]:[&>[data-slot=toggle-group-item]:has(+[data-slot=toggle-group-separator])]:after:-bottom-[5px] data-[orientation=vertical]:[&>[data-slot=toggle-group-separator]+[data-slot=toggle-group-item]]:after:-top-[5px]\",\n    // Icon-only items: the paint is square, whatever each side's border.\n    \"[&>[data-slot=toggle-group-item][data-icon-only]]:box-content [&>[data-slot=toggle-group-item][data-icon-only]]:aspect-square data-[orientation=vertical]:[&>[data-slot=toggle-group-item][data-icon-only]]:h-auto\",\n    \"data-disabled:opacity-60 data-disabled:[&>*]:opacity-100\",\n  ],\n  {\n    variants: {\n      // How pressed items look. Solid (the default) is the emphasis grey shared\n      // with Tabs and checkboxes; subtle is a quiet 12% overlay, like Toolbar.\n      pressedStyle: {\n        solid:\n          \"[--toggle-group-selected-bg:var(--emphasis)] [--toggle-group-selected-fg:var(--emphasis-foreground)]\",\n        subtle:\n          \"[--toggle-group-selected-bg:oklch(0_0_0/12%)] dark:[--toggle-group-selected-bg:oklch(1_0_0/12%)] [--toggle-group-selected-fg:var(--foreground)]\",\n      },\n      variant: {\n        outline: \"bg-(--outline) outline outline-(--outline-border)\",\n        soft: \"bg-secondary\",\n        ghost: \"\",\n      },\n      // Button's height ladder (one step taller below sm); corners step with it.\n      size: {\n        sm: \"[--toggle-group-h:--spacing(9)] sm:not-pointer-coarse:[--toggle-group-h:--spacing(8)] [--toggle-group-radius:calc(var(--radius)-2px)]\",\n        default:\n          \"[--toggle-group-h:--spacing(10)] sm:not-pointer-coarse:[--toggle-group-h:--spacing(9)] [--toggle-group-radius:var(--radius)]\",\n        lg: \"[--toggle-group-h:--spacing(11)] sm:not-pointer-coarse:[--toggle-group-h:--spacing(10)] [--toggle-group-radius:calc(var(--radius)+2px)]\",\n      },\n    },\n    defaultVariants: {\n      variant: \"soft\",\n      size: \"default\",\n      pressedStyle: \"solid\",\n    },\n  },\n);\n\ntype ToggleGroupSize = NonNullable<\n  VariantProps<typeof toggleGroupVariants>[\"size\"]\n>;\n\ntype ToggleGroupContextValue = {\n  size: ToggleGroupSize;\n  orientation: \"horizontal\" | \"vertical\";\n  pressedStyle: \"solid\" | \"subtle\";\n};\n\nconst ToggleGroupContext = React.createContext<ToggleGroupContextValue>({\n  size: \"default\",\n  orientation: \"horizontal\",\n  pressedStyle: \"solid\",\n});\n\nexport type ToggleGroupProps = BaseToggleGroup.Props &\n  VariantProps<typeof toggleGroupVariants>;\n\nfunction ToggleGroup({\n  className,\n  variant,\n  size,\n  pressedStyle,\n  orientation = \"horizontal\",\n  children,\n  ...props\n}: ToggleGroupProps) {\n  const resolvedSize = size ?? \"default\";\n  const resolvedPressedStyle = pressedStyle ?? \"solid\";\n  const context = React.useMemo(\n    () => ({\n      size: resolvedSize,\n      orientation,\n      pressedStyle: resolvedPressedStyle,\n    }),\n    [resolvedSize, orientation, resolvedPressedStyle],\n  );\n\n  return (\n    <BaseToggleGroup\n      data-slot=\"toggle-group\"\n      data-variant={variant ?? \"soft\"}\n      data-size={resolvedSize}\n      data-pressed-style={resolvedPressedStyle}\n      orientation={orientation}\n      className={cn(\n        toggleGroupVariants({ variant, size, pressedStyle }),\n        className,\n      )}\n      {...props}\n    >\n      <ToggleGroupContext.Provider value={context}>\n        {children}\n      </ToggleGroupContext.Provider>\n    </BaseToggleGroup>\n  );\n}\n\nconst itemClasses = cn(\n  \"h-auto min-w-auto self-stretch border border-transparent text-sm sm:not-pointer-coarse:h-auto sm:not-pointer-coarse:min-w-auto\",\n  // Icon-only items drop their padding, so they're square.\n  \"data-icon-only:px-0\",\n  // Box corners are the plate's + 2px; the focus ring sits on the plate.\n  \"rounded-[calc(var(--toggle-group-item-radius)+2px)] before:rounded-(--toggle-group-item-radius) focus-visible:outline-transparent focus-visible:before:outline-2 focus-visible:before:-outline-offset-2 focus-visible:before:outline-ring focus-visible:z-10\",\n  \"[--tgl-bg-hover:var(--toggle-group-highlight)] [--tgl-bg-active:var(--toggle-group-press)] [--tgl-bg-selected:var(--toggle-group-selected-bg)]\",\n  // Label color\n  \"text-muted-foreground data-pressed:text-(--toggle-group-selected-fg) hover:not-data-pressed:text-foreground\",\n  // Instant hover, so a sweep never shows two items half-lit. The press\n  // tint and pressed fill still fade (Toggle's 100ms).\n  \"[transition-duration:100ms,100ms,100ms,100ms,0ms] before:[transition-duration:0ms,100ms,100ms] active:before:[transition-duration:100ms] data-pressed:before:[transition-duration:100ms]\",\n  // Forced colors drop the fill, so a pressed item gets a Highlight border.\n  \"forced-colors:data-pressed:border-[Highlight]\",\n);\n\n// Corners that face another item are small, so a run of pressed items reads\n// as one control. Corners at the shell or a separator stay concentric.\nconst joinedClasses = {\n  horizontal: cn(\n    \"[[data-slot=toggle-group-item]+&]:rounded-s-[calc(var(--toggle-group-inner-radius)+1px)] [[data-slot=toggle-group-item]+&]:before:rounded-s-(--toggle-group-inner-radius)\",\n    \"has-[+[data-slot=toggle-group-item]]:rounded-e-[calc(var(--toggle-group-inner-radius)+1px)] has-[+[data-slot=toggle-group-item]]:before:rounded-e-(--toggle-group-inner-radius)\",\n  ),\n  vertical: cn(\n    \"[[data-slot=toggle-group-item]+&]:rounded-t-[calc(var(--toggle-group-inner-radius)+1px)] [[data-slot=toggle-group-item]+&]:before:rounded-t-(--toggle-group-inner-radius)\",\n    \"has-[+[data-slot=toggle-group-item]]:rounded-b-[calc(var(--toggle-group-inner-radius)+1px)] has-[+[data-slot=toggle-group-item]]:before:rounded-b-(--toggle-group-inner-radius)\",\n  ),\n};\n\n// The group sets the pressed look, so items take no `pressedStyle` of their own.\nexport type ToggleGroupItemProps = Omit<\n  ToggleProps,\n  \"variant\" | \"size\" | \"pressedStyle\"\n>;\n\n/** A `Toggle` sized and styled by its `ToggleGroup`. */\nfunction ToggleGroupItem({\n  className,\n  children,\n  ...props\n}: ToggleGroupItemProps) {\n  const { size, orientation, pressedStyle } = React.use(ToggleGroupContext);\n  const iconOnly = isIconOnly(\n    children,\n    props[\"aria-label\"] || props[\"aria-labelledby\"],\n  );\n\n  return (\n    <Toggle\n      data-slot=\"toggle-group-item\"\n      variant=\"ghost\"\n      size={size}\n      data-pressed-style={pressedStyle}\n      data-icon-only={iconOnly || undefined}\n      className={cn(itemClasses, joinedClasses[orientation], className)}\n      {...props}\n    >\n      {children}\n    </Toggle>\n  );\n}\n\nexport type ToggleGroupSeparatorProps = React.ComponentProps<typeof Separator>;\n\nfunction ToggleGroupSeparator({\n  className,\n  orientation,\n  ...props\n}: ToggleGroupSeparatorProps) {\n  const group = React.use(ToggleGroupContext);\n  const resolved =\n    orientation ??\n    (group.orientation === \"vertical\" ? \"horizontal\" : \"vertical\");\n\n  return (\n    <Separator\n      data-slot=\"toggle-group-separator\"\n      orientation={resolved}\n      className={cn(\n        // Air and line are all borders, so both sides snap alike.\n        \"pointer-events-none flex shrink-0 self-stretch border-transparent bg-transparent data-[orientation=horizontal]:h-auto data-[orientation=horizontal]:w-auto data-[orientation=horizontal]:flex-col data-[orientation=vertical]:w-auto\",\n        \"before:border-transparent before:content-[''] after:border-transparent after:content-['']\",\n        \"data-[orientation=vertical]:after:border-s-border data-[orientation=vertical]:border-e-[3px] data-[orientation=vertical]:before:border-s-[3px] data-[orientation=vertical]:after:h-5 data-[orientation=vertical]:after:self-center data-[orientation=vertical]:after:rounded-full data-[orientation=vertical]:after:border-s-[1.5px]\",\n        \"data-[orientation=horizontal]:after:border-t-border data-[orientation=horizontal]:border-b-[3px] data-[orientation=horizontal]:before:border-t-[3px] data-[orientation=horizontal]:after:w-5 data-[orientation=horizontal]:after:self-center data-[orientation=horizontal]:after:rounded-full data-[orientation=horizontal]:after:border-t-[1.5px]\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nexport {\n  ToggleGroup,\n  ToggleGroupItem,\n  ToggleGroupSeparator,\n  toggleGroupVariants,\n};\n",
      "type": "registry:ui",
      "target": "components/ui/cubby-ui/toggle-group.tsx"
    }
  ],
  "type": "registry:ui"
}