{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"switch-clean","type":"registry:ui","title":"Switch (Clean)","description":"On or off for things that apply right away – label and second line, at the start or across a settings row, a thumb that stretches as you press it","dependencies":[],"files":[{"path":"registry/switch-clean/switch-clean.tsx","type":"registry:ui","content":"\"use client\";\n\nimport { useId, type ComponentPropsWithRef, type ReactNode } from \"react\";\n\n/*\n * Switch – a single self-contained file, clean style.\n * On or off for something that takes effect right away: a real checkbox with role=\"switch\", a label and a quiet\n * second line, the switch at the start or at the end of the row (settings rows put it on the right). The thumb\n * slides and stretches while it's pressed. Focus shows a ring only from the keyboard.\n * The styles are injected below, so no extra files are needed.\n */\n\nexport type SwitchProps = Omit<ComponentPropsWithRef<\"input\">, \"type\" | \"size\" | \"role\"> & {\n  /** Shown next to the switch; clicking it toggles */\n  label?: ReactNode;\n  /** A quiet second line under the label */\n  description?: ReactNode;\n  /** start: the switch before the text · end: after it, across the row – the settings look */\n  placement?: \"start\" | \"end\";\n  /** sm 16 · md 20 high */\n  size?: \"sm\" | \"md\";\n};\n\nexport function Switch({ label, description, placement = \"start\", size = \"md\", className, id, disabled, ref, \"aria-describedby\": describedBy, ...rest }: SwitchProps) {\n  const autoId = useId();\n  const inputId = id ?? `${autoId}-input`;\n  const descId = `${autoId}-desc`;\n\n  return (\n    <div\n      className={[\"ui-swc\", className].filter(Boolean).join(\" \")}\n      data-placement={placement === \"end\" ? \"end\" : \"start\"}\n      data-size={size === \"sm\" ? \"sm\" : \"md\"}\n      data-disabled={disabled || undefined}\n    >\n      {/* React 19 hoists this into <head> once, no matter how many switches render */}\n      <style href=\"ui-switch-clean\" precedence=\"default\">\n        {css}\n      </style>\n      <label className=\"ui-swc__row\" htmlFor={inputId}>\n        <span className=\"ui-swc__control\">\n          <input\n            {...rest}\n            ref={ref}\n            id={inputId}\n            type=\"checkbox\"\n            role=\"switch\"\n            className=\"ui-swc__input\"\n            disabled={disabled}\n            aria-describedby={[describedBy, description ? descId : null].filter(Boolean).join(\" \") || undefined}\n          />\n          <span className=\"ui-swc__track\" aria-hidden=\"true\">\n            <span className=\"ui-swc__thumb\" />\n          </span>\n        </span>\n        {(label != null || description != null) && (\n          <span className=\"ui-swc__text\">\n            {label != null && <span className=\"ui-swc__label\">{label}</span>}\n            {description != null && (\n              <span className=\"ui-swc__desc\" id={descId}>\n                {description}\n              </span>\n            )}\n          </span>\n        )}\n      </label>\n    </div>\n  );\n}\n\nconst css = /* css */ `\n/* Colors and motion as variables – override them on .ui-swc (see Theming in the docs) */\n.ui-swc {\n  --ui-swc-ink: var(--aui-ink, rgba(0, 0, 0, 0.88));\n  --ui-swc-subtle: var(--aui-muted, rgba(0, 0, 0, 0.45));\n  --ui-swc-off: rgba(0, 0, 0, 0.12);\n  --ui-swc-off-hover: rgba(0, 0, 0, 0.18);\n  --ui-swc-on: var(--aui-primary, rgba(0, 0, 0, 0.88));\n  --ui-swc-on-hover: rgba(0, 0, 0, 0.78);\n  --ui-swc-thumb: #ffffff;\n  --ui-swc-thumb-shadow: 0 1px 2px rgba(0, 0, 0, 0.18), 0 0 0 0.5px rgba(0, 0, 0, 0.04);\n  --ui-swc-focus: var(--aui-focus, rgba(0, 96, 226, 0.7));\n  --ui-swc-ease: cubic-bezier(0.22, 1, 0.36, 1);\n\n  /* The track: --w × --h, the thumb --h minus 4px */\n  --w: 32px;\n  --h: 20px;\n\n  min-width: 0;\n  font-family: var(--aui-font, \"Inter\", \"InterVariable\", ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif);\n  font-size: 13px;\n  line-height: 20px;\n  color: var(--ui-swc-ink);\n  -webkit-font-smoothing: antialiased;\n}\n.ui-swc[data-size=\"sm\"] { --w: 26px; --h: 16px; }\n\n.ui-swc__row { display: flex; align-items: flex-start; gap: 10px; min-width: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }\n/* At the end: the text first, the switch on the far right */\n.ui-swc[data-placement=\"end\"] .ui-swc__row { flex-direction: row-reverse; justify-content: space-between; gap: 16px; }\n.ui-swc[data-disabled] .ui-swc__row { cursor: not-allowed; opacity: 0.5; }\n\n/* The switch sits on the first line of the label, centered on it */\n.ui-swc__control { position: relative; display: grid; flex: none; place-items: center; height: max(var(--h), 20px); }\n.ui-swc__input { position: absolute; inset: -6px; width: calc(100% + 12px); height: calc(100% + 12px); margin: 0; opacity: 0; cursor: inherit; }\n.ui-swc__track {\n  position: relative;\n  display: block;\n  width: var(--w);\n  height: var(--h);\n  border-radius: 999px;\n  background: var(--ui-swc-off);\n  pointer-events: none;\n  transition: background-color 200ms ease;\n}\n.ui-swc__thumb {\n  position: absolute;\n  top: 2px;\n  left: 2px;\n  width: calc(var(--h) - 4px);\n  height: calc(var(--h) - 4px);\n  border-radius: 999px;\n  background: var(--ui-swc-thumb);\n  box-shadow: var(--ui-swc-thumb-shadow);\n  transition: transform 260ms var(--ui-swc-ease), width 160ms var(--ui-swc-ease);\n}\n.ui-swc__row:hover .ui-swc__input:not(:disabled):not(:checked) + .ui-swc__track { background: var(--ui-swc-off-hover); }\n.ui-swc__input:checked + .ui-swc__track { background: var(--ui-swc-on); }\n.ui-swc__row:hover .ui-swc__input:not(:disabled):checked + .ui-swc__track { background: var(--ui-swc-on-hover); }\n.ui-swc__input:checked + .ui-swc__track .ui-swc__thumb { transform: translateX(calc(var(--w) - var(--h))); }\n/* Pressed: the thumb stretches toward where it's going */\n.ui-swc__input:active:not(:disabled) + .ui-swc__track .ui-swc__thumb { width: calc(var(--h) + 1px); }\n.ui-swc__input:active:not(:disabled):checked + .ui-swc__track .ui-swc__thumb { transform: translateX(calc(var(--w) - var(--h) - 5px)); }\n.ui-swc__input:focus-visible + .ui-swc__track { outline: 2px solid var(--ui-swc-focus); outline-offset: 2px; }\n\n.ui-swc__text { display: grid; flex: 1; min-width: 0; }\n.ui-swc__label { color: var(--ui-swc-ink); overflow-wrap: anywhere; }\n.ui-swc__desc { font-size: 12px; line-height: 16px; color: var(--ui-swc-subtle); overflow-wrap: anywhere; }\n\n/* Touch screens: a bigger switch and 15px text */\n@media (pointer: coarse) {\n  .ui-swc { --w: 40px; --h: 24px; font-size: 15px; line-height: 22px; }\n  .ui-swc[data-size=\"sm\"] { --w: 34px; --h: 20px; }\n  .ui-swc__control { height: max(var(--h), 22px); }\n}\n\n@media (prefers-reduced-motion: reduce) {\n  .ui-swc__track, .ui-swc__thumb { transition-duration: 1ms; }\n}\n\n/* Dark mode: follows a .dark class or data-theme=\"dark\" on any ancestor, e.g. <html> */\n:where(.dark, [data-theme=\"dark\"]) .ui-swc {\n  --ui-swc-ink: var(--aui-ink, rgba(255, 255, 255, 0.9));\n  --ui-swc-subtle: var(--aui-muted, rgba(255, 255, 255, 0.46));\n  --ui-swc-off: rgba(255, 255, 255, 0.16);\n  --ui-swc-off-hover: rgba(255, 255, 255, 0.22);\n  --ui-swc-on: var(--aui-primary, rgba(255, 255, 255, 0.9));\n  --ui-swc-on-hover: rgba(255, 255, 255, 0.8);\n  --ui-swc-thumb: #ffffff;\n  --ui-swc-focus: var(--aui-focus, rgba(77, 141, 255, 0.8));\n}\n:where(.dark, [data-theme=\"dark\"]) .ui-swc__input:checked + .ui-swc__track .ui-swc__thumb { background: #161618; box-shadow: none; }\n`;\n"}]}