{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toggle-group",
  "title": "Toggle Group",
  "description": "Segmented controls with a gliding chip, plus outline and ghost groups.",
  "dependencies": [
    "class-variance-authority",
    "radix-ui"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.cuelark.com/r/theme.json",
    "https://ui.cuelark.com/r/motion.json"
  ],
  "files": [
    {
      "path": "src/registry/cuelark/ui/toggle-group.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { ToggleGroup as ToggleGroupPrimitive } from \"radix-ui\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { gsap, motionScale, useMergedRef } from \"@/lib/motion\";\nimport { cn } from \"@/lib/utils\";\n\nconst groupVariants = cva(\"relative inline-flex w-fit items-center\", {\n  variants: {\n    variant: {\n      /** One raised chip glides to the pressed item (single selection). */\n      segmented: \"gap-0 rounded-lg bg-muted p-[3px] shadow-well\",\n      outline: \"gap-0 rounded-md border border-input shadow-control\",\n      ghost: \"gap-1\",\n    },\n    size: { sm: \"h-ctl-sm\", md: \"h-ctl-md\", lg: \"h-ctl-lg\" },\n  },\n  defaultVariants: { variant: \"segmented\", size: \"md\" },\n});\n\nconst itemVariants = cva(\n  \"relative z-10 inline-flex h-full items-center justify-center gap-1.5 text-sm font-medium whitespace-nowrap text-muted-foreground outline-none transition-colors duration-150 hover:text-foreground focus-visible:z-20 focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n  {\n    variants: {\n      variant: {\n        segmented: \"rounded-md [[data-slot=toggle-group]:not([data-ready])_&]:data-[state=on]:bg-card [[data-slot=toggle-group]:not([data-ready])_&]:data-[state=on]:shadow-control\",\n        outline: \"border-s border-input first:border-s-0 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground first:rounded-s-[calc(var(--radius)-3px)] last:rounded-e-[calc(var(--radius)-3px)]\",\n        ghost: \"rounded-md hover:bg-muted data-[state=on]:bg-accent data-[state=on]:text-accent-foreground\",\n      },\n      size: {\n        sm: \"px-2.5 text-[0.8125rem]\",\n        md: \"px-3\",\n        lg: \"px-3.5\",\n      },\n    },\n    defaultVariants: { variant: \"segmented\", size: \"md\" },\n  },\n);\n\ntype GroupContext = VariantProps<typeof itemVariants>;\nconst ToggleGroupContext = React.createContext<GroupContext>({ variant: \"segmented\", size: \"md\" });\n\nfunction ToggleGroup({\n  className,\n  variant = \"segmented\",\n  size = \"md\",\n  children,\n  ref,\n  ...props\n}: React.ComponentProps<typeof ToggleGroupPrimitive.Root> & VariantProps<typeof groupVariants>) {\n  const rootRef = React.useRef<HTMLDivElement>(null);\n  const chipRef = React.useRef<HTMLSpanElement>(null);\n  const mergedRef = useMergedRef(rootRef, ref);\n\n  // A segmented control always has a selection: pressing the active item again keeps it selected.\n  const single = props.type === \"single\" ? (props as Extract<typeof props, { type: \"single\" }>) : null;\n  const [kept, setKept] = React.useState(single?.defaultValue ?? \"\");\n  if (single && variant === \"segmented\") {\n    const { onValueChange, value } = single;\n    Object.assign(props, {\n      value: value ?? kept,\n      defaultValue: undefined,\n      onValueChange: (next: string) => {\n        if (!next) return;\n        setKept(next);\n        onValueChange?.(next);\n      },\n    });\n  }\n\n  React.useLayoutEffect(() => {\n    const root = rootRef.current;\n    const chip = chipRef.current;\n    if (variant !== \"segmented\" || !root || !chip) return;\n    let placed = false;\n    const place = (animate: boolean) => {\n      const on = root.querySelector<HTMLElement>(':scope > [data-slot=\"toggle-group-item\"][data-state=\"on\"]');\n      if (!on) return gsap.to(chip, { opacity: 0, duration: 0.15 });\n      const box = { left: on.offsetLeft, top: on.offsetTop, width: on.offsetWidth, height: on.offsetHeight, opacity: 1 };\n      if (!animate || !placed || !motionScale(root)) gsap.set(chip, box);\n      else gsap.to(chip, { ...box, duration: 0.4, ease: \"cue-snap\", overwrite: true });\n      placed = true;\n      root.dataset.ready = \"\";\n    };\n    place(false);\n    const mutations = new MutationObserver(() => place(true));\n    mutations.observe(root, { subtree: true, attributes: true, attributeFilter: [\"data-state\"] });\n    const resize = new ResizeObserver(() => place(false));\n    resize.observe(root);\n    return () => {\n      mutations.disconnect();\n      resize.disconnect();\n    };\n  }, [variant]);\n\n  return (\n    <ToggleGroupPrimitive.Root ref={mergedRef} data-slot=\"toggle-group\" data-variant={variant} className={cn(groupVariants({ variant, size }), className)} {...props}>\n      {variant === \"segmented\" && (\n        <span ref={chipRef} aria-hidden=\"true\" className=\"pointer-events-none absolute rounded-md border border-border/60 bg-card opacity-0 shadow-control\" />\n      )}\n      <ToggleGroupContext.Provider value={{ variant, size }}>{children}</ToggleGroupContext.Provider>\n    </ToggleGroupPrimitive.Root>\n  );\n}\n\nfunction ToggleGroupItem({ className, ...props }: React.ComponentProps<typeof ToggleGroupPrimitive.Item>) {\n  const { variant, size } = React.useContext(ToggleGroupContext);\n  return <ToggleGroupPrimitive.Item data-slot=\"toggle-group-item\" className={cn(itemVariants({ variant, size }), className)} {...props} />;\n}\n\nexport { ToggleGroup, ToggleGroupItem };\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Docs and examples: https://ui.cuelark.com/components/toggle-group",
  "categories": [
    "forms"
  ],
  "type": "registry:ui"
}