{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "switch",
  "title": "Switch",
  "description": "A switch component.",
  "dependencies": [
    "class-variance-authority"
  ],
  "files": [
    {
      "path": "registry/default/switch/switch.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Switch as BaseSwitch } from \"@base-ui/react/switch\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\n\nimport { cn } from \"@/lib/utils\";\n\nimport \"./switch.css\";\n\nconst switchVariants = cva(\n  [\n    // Containing block for the thumb, which is pinned by left and right so its\n    // two edges can move on separate schedules. That is the stretch motion.\n    \"peer relative inline-block shrink-0 cursor-pointer\",\n    // Layout containment bounds the reflow that `stretch` causes. That motion\n    // animates the thumb's `left`/`right` every frame, and without this the\n    // engine has to satisfy itself each time that nothing outside the switch\n    // moved. The promise is already true — the root's width and height are\n    // explicit and the thumb is absolutely positioned — so this only tells it\n    // what it would otherwise re-derive. `default` reflows too, just not during\n    // the toggle: its reach is a width and its squash is a height, both on a\n    // fine pointer only. So it takes the same bound on the same terms.\n    //\n    // Layout only, deliberately. `paint` (and therefore `strict`) clips\n    // descendants to the box, which would cut the coarse-pointer tap target\n    // below back to the visual size and take the 24px WCAG target with it.\n    \"[contain:layout]\",\n    \"touch-manipulation [-webkit-tap-highlight-color:transparent]\",\n    // Track and thumb need separate radii: the track is 4px larger in both\n    // axes, so one shared value leaves its corners proportionally tighter.\n    // Only `squircle` sets --switch-corner-shape, so that fallback is real.\n    \"rounded-(--switch-track-radius) [corner-shape:var(--switch-corner-shape,round)]\",\n    // All geometry derives from --thumb-size, so overriding that one value\n    // still works. No var() fallbacks here: the prop types reject `null`, so\n    // cva cannot drop a defaultVariant and leave one unset.\n    \"[--thumb-h:var(--thumb-size)]\",\n    \"[--thumb-w:calc(var(--thumb-size)*var(--thumb-aspect))]\",\n    \"[--travel:calc(var(--thumb-w)*var(--travel-ratio))]\",\n    // Snapped to whole pixels, or the 2px inset lands mid-pixel and renders\n    // thicker on one side. The unrounded values above cover no round() support.\n    \"supports-[width:round(1px,1px)]:[--thumb-h:round(var(--thumb-size),1px)]\",\n    \"supports-[width:round(1px,1px)]:[--thumb-w:round(calc(var(--thumb-size)*var(--thumb-aspect)),1px)]\",\n    \"supports-[width:round(1px,1px)]:[--travel:round(calc(var(--thumb-w)*var(--travel-ratio)),1px)]\",\n    \"h-[calc(var(--thumb-h)+4px)]\",\n    \"w-[calc(var(--thumb-w)+var(--travel)+4px)]\",\n    // How far the thumb reaches into the empty half of the track. Whole pixels\n    // because a pointer can rest in either state. The matching flatten depth\n    // lives in the `squash` variant below, which is the one of the three a host\n    // turns off.\n    \"[--switch-hover-ext:round(calc(var(--thumb-h)*0.125),1px)]\",\n    \"[--switch-press-ext:round(calc(var(--thumb-h)*0.25),1px)]\",\n    // --switch-p is the whole toggle: every thumb declaration is a calc() of\n    // it, which is how one mechanism serves both motions.\n    \"[--switch-p:0] data-checked:[--switch-p:1]\",\n    // Hover and press write to separate variables and --switch-ext takes the\n    // larger. A press always happens while hovering, so both rules match at\n    // once, and whichever Tailwind ordered last would win. Press has to.\n    \"[--switch-hover-part:0px] [--switch-press-part:0px] [--switch-press:0px]\",\n    \"[--switch-ext:max(var(--switch-hover-part),var(--switch-press-part))]\",\n    // Gestures read from the control and from a `group/switch` ancestor, so a\n    // switch in a labelled row answers the row. Named, not bare: `group-hover:`\n    // compiles to a descendant selector, so an unnamed group would let any\n    // `.group` a consumer puts on a card drive every switch inside it. Menu\n    // indicators are inert, so data-highlighted stands in for hover.\n    // motion-safe rather than a motion-reduce reset: a reset carries fewer\n    // selectors than the rule it undoes and loses on specificity.\n    //\n    // Every one of these ends up in the thumb's WIDTH, via the negative\n    // margins, so each is a reflow per frame. A mouse can afford that; a phone\n    // cannot, and on touch a press lands at the same instant as the toggle, so\n    // the reach would relayout straight through the slide and undo the\n    // compositor path `default` sets up. Only the rules a finger can actually\n    // reach say so, though: Tailwind compiles `hover` and `group-hover` inside\n    // `@media (hover: hover)` already, so those two never match on a phone and\n    // a pointer-fine gate on them would be a second lock on the same door.\n    // `:active` has no such wrapper, and data-highlighted is set by Base UI\n    // rather than inferred by the browser, so nothing stands between it and a\n    // finger dragging down a menu. Those three carry the gate. Geometry only —\n    // the colour rules below are paint-only and need no gate at all, see there.\n    \"motion-safe:not-data-disabled:hover:[--switch-hover-part:var(--switch-hover-ext)]\",\n    \"motion-safe:not-data-disabled:group-hover/switch:[--switch-hover-part:var(--switch-hover-ext)]\",\n    \"motion-safe:pointer-fine:not-data-disabled:data-highlighted:[--switch-hover-part:var(--switch-hover-ext)]\",\n    \"motion-safe:pointer-fine:not-data-disabled:active:[--switch-press-part:var(--switch-press-ext)]\",\n    \"motion-safe:pointer-fine:not-data-disabled:group-active/switch:[--switch-press-part:var(--switch-press-ext)]\",\n    // Unchecked track. Values live here rather than in the theme so the\n    // component works the moment it is installed; set --switch-track /\n    // --switch-track-hover on any ancestor to retune. Translucent, so one\n    // colour works on any substrate and hover steps along the same overlay.\n    \"[--switch-track-bg:var(--switch-track,oklch(0_0_0/8%))]\",\n    \"[--switch-track-bg-hover:var(--switch-track-hover,oklch(0_0_0/12%))]\",\n    \"dark:[--switch-track-bg:var(--switch-track,oklch(1_0_0/20%))]\",\n    \"dark:[--switch-track-bg-hover:var(--switch-track-hover,oklch(1_0_0/24%))]\",\n    // Checked fill and thumb both read through an indirection: `color` supplies\n    // the preset, and --switch-fill / --switch-thumb from an ancestor or\n    // className win over it.\n    \"[--switch-fill-bg:var(--switch-fill,var(--switch-fill-preset))]\",\n    // The data-checked: qualifier sits on --switch-thumb-bg, never on\n    // --switch-thumb: qualifying the consumer-facing variable would raise its\n    // specificity and silently outrank a className override.\n    \"[--switch-thumb-bg:var(--switch-thumb,var(--color-white))]\",\n    \"data-checked:[--switch-thumb-bg:var(--switch-thumb,var(--switch-thumb-preset))]\",\n    // Hover derives from the resolved fill, so one rule covers every colour.\n    // An absolute lightness step, not a percentage of black: a percentage is\n    // proportional, so 8% moves --primary (L 0.6) by 0.048 but --neutral in\n    // light (L 0.22) by 0.018, at the JND. It also leaves `c` and `h` alone,\n    // where mixing black desaturates. Darkens in both themes deliberately, a\n    // lighter checked track reads as disabled, which is also why the\n    // --primary-hover / --neutral-hover tokens are unused: they lighten in one\n    // theme or the other.\n    \"[--switch-fill-hover:oklch(from_var(--switch-fill-bg)_calc(l-0.05)_c_h)]\",\n    \"data-unchecked:bg-(--switch-track-bg) data-checked:bg-(--switch-fill-bg)\",\n    // Ungated, unlike the geometry above, including the data-highlighted pair\n    // that is gated up there. These are paint-only: there is no reflow to keep\n    // off a phone, and a highlight that survives a frame longer than it should\n    // costs a repaint of one small box. The `:hover` half also never fires on a\n    // touch-only device to begin with, on Tailwind's `@media (hover: hover)`.\n    \"not-data-disabled:hover:data-unchecked:bg-(--switch-track-bg-hover)\",\n    \"not-data-disabled:group-hover/switch:data-unchecked:bg-(--switch-track-bg-hover)\",\n    \"not-data-disabled:data-highlighted:data-unchecked:bg-(--switch-track-bg-hover)\",\n    \"not-data-disabled:hover:data-checked:bg-(--switch-fill-hover)\",\n    \"not-data-disabled:group-hover/switch:data-checked:bg-(--switch-fill-hover)\",\n    \"not-data-disabled:data-highlighted:data-checked:bg-(--switch-fill-hover)\",\n    // One gentle curve for everything: the two edges split a single timeline,\n    // so a front-loaded curve would spend the trailing edge's budget on the\n    // leading one. Which properties ride that curve is a question of how the\n    // switch moves, so the lists themselves live on `motion` below.\n    \"ease-out-cubic\",\n    \"motion-reduce:transition-none\",\n    \"focus-visible:outline-ring/50 outline-0 outline-offset-0 outline-transparent outline-solid focus-visible:outline-2 focus-visible:outline-offset-2\",\n    // The border box is the painted box, so a mouse already has an exact\n    // target. Coarse pointers get 24px (WCAG 2.5.8), where reach matters and\n    // there is no hover to mismatch.\n    \"pointer-coarse:before:absolute pointer-coarse:before:inset-x-0 pointer-coarse:before:content-['']\",\n    \"pointer-coarse:before:inset-y-[calc((100%-24px)/2)]\",\n    \"data-disabled:cursor-not-allowed data-disabled:opacity-60\",\n  ],\n  {\n    variants: {\n      // Each colour pairs a fill with the foreground that sits on it, as Button\n      // pairs --btn-bg with text-*-foreground. Not decoration: --neutral is\n      // light in dark mode, where a white thumb would vanish into it. The base\n      // array applies these while checked only, since the unchecked track is a\n      // translucent overlay that a dark thumb disappears into.\n      color: {\n        primary:\n          \"[--switch-fill-preset:var(--primary)] [--switch-thumb-preset:var(--primary-foreground)]\",\n        neutral:\n          \"[--switch-fill-preset:var(--neutral)] [--switch-thumb-preset:var(--neutral-foreground)]\",\n      },\n      // Shape sets the thumb's silhouette, size sets its height. They are\n      // independent, so radii are fractions of --thumb-size rather than fixed\n      // pixels that would read too round at xs and too sharp at default.\n      shape: {\n        circle: [\n          \"[--switch-radius:9999px] [--switch-track-radius:9999px]\",\n          \"[--thumb-aspect:1] [--travel-ratio:0.8]\",\n        ].join(\" \"),\n        pill: [\n          \"[--switch-radius:9999px] [--switch-track-radius:9999px]\",\n          \"[--thumb-aspect:1.8] [--travel-ratio:0.45]\",\n        ].join(\" \"),\n        // A superellipse, not a rounded rect. corner-shape needs a radius near\n        // 50%, but that same radius without corner-shape support is just a\n        // circle, so the plain-radius fallback is smaller and degrades to a\n        // rounded square instead.\n        squircle: [\n          \"[--switch-radius:calc(var(--thumb-h)*0.3)]\",\n          \"[--switch-track-radius:calc((var(--thumb-h)+4px)*0.3)]\",\n          \"supports-[corner-shape:squircle]:[--switch-radius:calc(var(--thumb-h)*0.5)]\",\n          \"supports-[corner-shape:squircle]:[--switch-track-radius:calc((var(--thumb-h)+4px)*0.5)]\",\n          \"[--switch-corner-shape:squircle]\",\n          \"[--thumb-aspect:1] [--travel-ratio:0.8]\",\n        ].join(\" \"),\n      },\n      size: {\n        xs: \"[--thumb-size:--spacing(3.5)]\",\n        sm: \"[--thumb-size:--spacing(4)]\",\n        default: \"[--thumb-size:--spacing(5)]\",\n      },\n      // --switch-split is the fraction of the timeline each edge of the thumb\n      // gets. At 1 they move together and the width never changes, so the thumb\n      // slides. At 0.5 they run back to back and it spans the track mid-toggle.\n      motion: {\n        default: [\n          \"[--switch-split:1] [--switch-duration:160ms]\",\n          // --switch-p is the only entry a coarse pointer would ever move, and\n          // the only one this motion can do without: the toggle is a translate\n          // the thumb owns and times itself, and the sole thing left reading\n          // --switch-p here is a pair of margins that multiply it by a\n          // --switch-ext no finger sets. Listed for the pointers with a use for\n          // it, left out for the ones without, where it would interpolate a\n          // registered custom property, and recompute the thumb's style against\n          // it, every frame of a toggle the compositor is otherwise running by\n          // itself. --switch-ext and --switch-press stay in both lists because\n          // a property that does not change starts no transition and so costs\n          // nothing to name, and a coarse pointer that can still hover — a TV\n          // remote — does move --switch-ext. Colour runs at half the speed of\n          // anything else either way, so the track reads as filling ahead of\n          // the thumb.\n          \"transition-[background-color,--switch-ext,--switch-press]\",\n          \"duration-[80ms,160ms,160ms]\",\n          \"motion-safe:pointer-fine:transition-[background-color,--switch-p,--switch-ext,--switch-press]\",\n          \"motion-safe:pointer-fine:duration-[80ms,var(--switch-duration),160ms,160ms]\",\n          // Fine pointers only, for the same reason as the reach above: this\n          // drives the thumb's HEIGHT, and on touch it would be animating\n          // through the slide rather than before it.\n          \"motion-safe:pointer-fine:not-data-disabled:active:[--switch-press:var(--switch-press-squash)]\",\n          \"motion-safe:pointer-fine:not-data-disabled:group-active/switch:[--switch-press:var(--switch-press-squash)]\",\n        ].join(\" \"),\n        // No press squash: the stretch derives its own from how far it has\n        // spread. Longer than the slide because this timeline has to show the\n        // thumb both spread and gather inside it. --switch-press is absent from\n        // the list below for the same reason — nothing in this motion sets it.\n        // --switch-p is not gated the way `default` gates it: interpolating it\n        // IS the stretch, on every pointer there is.\n        stretch: [\n          \"[--switch-split:0.5] [--switch-duration:200ms]\",\n          \"transition-[background-color,--switch-p,--switch-ext]\",\n          \"duration-[80ms,var(--switch-duration),160ms]\",\n        ].join(\" \"),\n      },\n      // How far the thumb flattens, and the one knob that reaches both motions\n      // through different triggers: `default` applies it on :active (see the\n      // rules in that variant), `stretch` derives it from how far the thumb has\n      // spread, so there it flattens mid-travel with no press involved. Off\n      // means neither happens and the thumb holds a constant height.\n      //\n      // For hosts that own the press themselves — a menu row, where the\n      // indicator is inert and only squashes if the pointer happens to land on\n      // the graphic — and for anywhere the constant-height spread simply reads\n      // cleaner. Declared here rather than in the base list so `false` is not\n      // relying on twMerge to drop a competing base declaration.\n      squash: {\n        true: \"[--switch-press-squash:round(calc(var(--thumb-h)*0.25),1px)]\",\n        false: \"[--switch-press-squash:0px]\",\n      },\n    },\n    defaultVariants: {\n      color: \"primary\",\n      shape: \"circle\",\n      size: \"default\",\n      motion: \"default\",\n      squash: true,\n    },\n  },\n);\n\n/**\n * Thumb classes. Every declaration reads a custom property the root supplies,\n * so this is only correct as a direct child of an element carrying\n * `switchVariants`. Unexported for that reason.\n *\n * The two motions travel by different means, which is the whole reason this is\n * a variant rather than one class list. `stretch` moves the thumb's two edges\n * on separate schedules — no single transform expresses that, so it animates\n * `left`/`right` and pays for a layout pass per frame. `default` moves both\n * edges in lockstep at a constant width, which IS a translate, so it uses one\n * and the compositor runs it off the main thread. Routing `default` through the\n * layout path too (as this once did) meant the common case paid the rare case's\n * cost: interpolating a custom property on the main thread, then relayouting\n * and repainting the thumb every frame. Cheap on a desktop, visibly janky on a\n * phone, especially inside a Drawer that is already compositing hard.\n *\n * The compositor path is only clean where nothing else is moving, which means a\n * coarse pointer — the case that needed it. A desktop toggle almost always\n * fires mid-hover, so --switch-ext is retracting from the press across the same\n * frames and the width is not constant after all. Desktops could always afford\n * that; the point was never to spare them.\n */\nconst switchThumbVariants = cva(\n  [\n    // White unchecked in both themes: the thumb is the lit element against a\n    // recessed track, the way physical switches read.\n    \"pointer-events-none absolute top-0 block bg-(--switch-thumb-bg)\",\n    \"rounded-(--switch-radius) [corner-shape:var(--switch-corner-shape,round)]\",\n    // Progress of each edge along its own half of the timeline. Reversing\n    // --switch-p swaps which edge leads for free, so there is no per-direction\n    // code.\n    \"[--lead:min(1,var(--switch-p)/var(--switch-split))]\",\n    \"[--trail:max(0,(var(--switch-p)-(1-var(--switch-split)))/var(--switch-split))]\",\n    // Negative margins push one edge outward. Each carries its own edge's\n    // factor, so the reach retracts exactly as that edge lands on its inset,\n    // which is what stops the thumb overhanging the track. Both resolve to 0\n    // on coarse pointers, where the gestures that set --switch-ext never fire,\n    // so the used value never changes and the pair costs a phone nothing.\n    \"ml-[calc(-1*var(--switch-ext)*var(--trail))]\",\n    \"mr-[calc(-1*var(--switch-ext)*(1-var(--lead)))]\",\n    // Only the horizontal axis needs two edges. Vertically, an explicit height\n    // plus one offset keeps the inset a single number instead of two independent\n    // roundings at fractional DPRs. The offset must be a transform: as a margin\n    // it snaps separately from the height and the thumb reads as shaking.\n    \"w-auto h-[calc(var(--thumb-h)-var(--switch-press-total))]\",\n    // Whichever is larger; only one is ever non-zero, since --switch-split\n    // decides which motion is in play.\n    \"[--switch-press-total:max(var(--switch-press),calc(var(--switch-press-squash)*(var(--lead)-var(--trail))))]\",\n    \"[transform:translateY(calc(2px+var(--switch-press-total)/2))]\",\n    // Only 2px of track shows around the thumb, so anything heavier darkens the\n    // inset below it and the thumb reads as sitting low.\n    // In light mode the unchecked track is an 8% black overlay, so on a white\n    // dialog the thumb is white-on-near-white and this shadow is the only edge\n    // between them. It was thinned to 1px/0.10 in a registry refresh; restored,\n    // because the \"only 2px of track shows\" reasoning that motivated thinning it\n    // assumes a track you can actually see.\n    \"shadow-[0_1px_2px_0_oklch(0.18_0_0/0.15)]\",\n    \"motion-reduce:transition-none\",\n  ],\n  {\n    variants: {\n      motion: {\n        // Box pinned at the unchecked position; the toggle is a translate.\n        // Same start, end, duration and curve as the layout path it replaces —\n        // at --switch-split:1 the edges were already moving together, so the\n        // interpolated positions are identical.\n        //\n        // Keyed off the PARENT's state, not the thumb's: SwitchVisual renders a\n        // plain span with no state of its own, and the root carries it in both\n        // cases. Direct-child, not `in-data-checked`, which matches any\n        // ancestor — a Switch inside a checked menu row would inherit that\n        // row's state and sit at the wrong end.\n        default: [\n          \"left-[2px] right-[calc(2px+var(--travel))]\",\n          \"[translate:0_0] [[data-checked]>&]:[translate:var(--travel)_0]\",\n          // The thumb's colour is state-dependent and transition-* does not\n          // inherit, so it needs its own. Matched to the track's 80ms step so\n          // the two cross together rather than the thumb snapping.\n          \"transition-[background-color,translate] duration-[80ms,var(--switch-duration)] ease-out-cubic\",\n        ].join(\" \"),\n        stretch: [\n          \"left-[calc(2px+var(--travel)*var(--trail))]\",\n          \"right-[calc(2px+var(--travel)*(1-var(--lead)))]\",\n          \"transition-[background-color] duration-80 ease-out-cubic\",\n        ].join(\" \"),\n      },\n    },\n    defaultVariants: {\n      motion: \"default\",\n    },\n  },\n);\n\n/**\n * cva types an explicit `null` as valid and drops its defaultVariants when it\n * sees one, which would leave the geometry variables unset. Rejecting `null` at\n * the type level is what lets every `var()` above read a bare variable instead\n * of restating its default as a fallback.\n */\ntype SwitchVariants = {\n  [K in keyof VariantProps<typeof switchVariants>]?: NonNullable<\n    VariantProps<typeof switchVariants>[K]\n  >;\n};\n\ntype SwitchProps = React.ComponentProps<typeof BaseSwitch.Root> &\n  SwitchVariants;\n\nfunction Switch({\n  className,\n  color = \"primary\",\n  shape = \"circle\",\n  size = \"default\",\n  motion = \"default\",\n  squash = true,\n  ...props\n}: SwitchProps) {\n  return (\n    <BaseSwitch.Root\n      data-slot=\"switch\"\n      data-color={color}\n      data-shape={shape}\n      data-size={size}\n      data-motion={motion}\n      className={cn(\n        switchVariants({ color, shape, size, motion, squash }),\n        className,\n      )}\n      {...props}\n    >\n      <BaseSwitch.Thumb\n        data-slot=\"switch-thumb\"\n        className={switchThumbVariants({ motion })}\n      />\n    </BaseSwitch.Root>\n  );\n}\n\n/**\n * The switch's look without the control, for rows that already own the role and\n * the click target — a menu's checkbox item, say, where nesting a real Switch\n * would put a focusable control inside a `menuitemcheckbox`. Pass the row's\n * indicator as `render`:\n *\n * ```tsx\n * <SwitchVisual render={<Menu.CheckboxItemIndicator keepMounted />} />\n * ```\n *\n * Pass that element childless: track and thumb only work as a pair, and\n * children on it would replace the thumb and leave a dead track.\n *\n * `squash` defaults to `false` here, inverting the control's default. The\n * condition that makes this component the right choice — the row owns the press\n * — is the same condition that makes the flatten wrong: the indicator is inert,\n * so under `motion=\"default\"` it would squash only when the pointer happened to\n * land on the graphic rather than anywhere else in the row, and under\n * `motion=\"stretch\"` it would flatten mid-travel on a row nobody is pressing.\n * Pass `squash` to opt back in.\n */\n// mergeProps lets the rightmost object win, so a child reaches the thumb's slot\n// from either direction. Omitting `children` closes the direct-prop route; the\n// `render` route above is a convention the type cannot reach.\ntype SwitchVisualProps = Omit<useRender.ComponentProps<\"span\">, \"children\"> &\n  SwitchVariants;\n\nfunction SwitchVisual({\n  className,\n  color = \"primary\",\n  shape = \"circle\",\n  size = \"xs\",\n  motion = \"default\",\n  squash = false,\n  render,\n  ...props\n}: SwitchVisualProps) {\n  const defaultProps = {\n    \"data-slot\": \"switch-visual\",\n    className: cn(\n      switchVariants({ color, shape, size, motion, squash }),\n      // The row carries the state and the hit area; this is decoration.\n      \"pointer-events-none cursor-default\",\n      // The row already dims when disabled; don't compound the fade.\n      \"data-disabled:opacity-100\",\n      className,\n    ),\n    children: <span className={switchThumbVariants({ motion })} />,\n  };\n\n  return useRender({\n    defaultTagName: \"span\",\n    render,\n    props: mergeProps<\"span\">(defaultProps, props),\n  });\n}\n\nexport { Switch, SwitchVisual, switchVariants };\nexport type { SwitchProps, SwitchVisualProps };\n",
      "type": "registry:ui",
      "target": "components/ui/cubby-ui/switch/switch.tsx"
    },
    {
      "path": "registry/default/switch/switch.css",
      "content": "/* -------------------------------------------------------------------------------------------------\n * Switch motion.\n *\n * A custom property only animates once it is registered — an unregistered one\n * has no type, so there is nothing to interpolate and it steps. These three are\n * the only animated quantities on a Switch: the thumb's own declarations are\n * plain calc() of them, which is what lets one mechanism serve both the sliding\n * and the stretching motion. They inherit so the thumb can read what the root\n * animates.\n *\n * Ships as a file rather than through the registry's `css` field, which cannot\n * carry @property. Imported from switch.tsx, so anything that renders a Switch —\n * including the menu components' SwitchItem, which borrow switchVariants —\n * pulls it in without a separate install step.\n * -------------------------------------------------------------------------------------------------*/\n@property --switch-p {\n  syntax: \"<number>\";\n  inherits: true;\n  initial-value: 0;\n}\n\n@property --switch-ext {\n  syntax: \"<length>\";\n  inherits: true;\n  initial-value: 0px;\n}\n\n@property --switch-press {\n  syntax: \"<length>\";\n  inherits: true;\n  initial-value: 0px;\n}\n",
      "type": "registry:file",
      "target": "components/ui/cubby-ui/switch/switch.css"
    }
  ],
  "type": "registry:ui"
}