{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "toggle", "type": "registry:ui", "title": "Toggle", "description": "Switch control with a label and optional description, for a single on/off setting.", "categories": [ "forms" ], "registryDependencies": [ "https://whiskeyjack.net/r/utils.json" ], "files": [ { "path": "components/ui/toggle.tsx", "type": "registry:ui", "target": "components/ui/toggle.tsx", "content": "import * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ToggleProps {\n /** Optional label rendered to the left of the switch. */\n label?: React.ReactNode;\n /** Optional helper text rendered below the label. */\n description?: React.ReactNode;\n checked: boolean;\n onChange: (checked: boolean) => void;\n disabled?: boolean;\n className?: string;\n /** Accessible label when no visible `label` is provided. */\n \"aria-label\"?: string;\n}\n\n/**\n * Switch-style boolean toggle. When `label` is provided, the whole row reads\n * as `[label] [switch]`; without a label, just the switch renders (use the\n * `aria-label` prop in that case for accessibility).\n */\nconst Toggle = React.forwardRef(\n ({ label, description, checked, onChange, disabled, className, ...rest }, ref) => {\n const handleToggle = () => {\n if (!disabled) onChange(!checked);\n };\n\n const switchEl = (\n \n \n \n );\n\n if (!label) return switchEl;\n\n return (\n \n \n {/*\n `text-sm` on secondary, matching every other labelled row: an Input's\n label, a Select's, and the label a caller puts beside a Slider or a\n SegmentedControl. This was `text-xs` on muted, which made a toggle's\n title the smallest and faintest text in a settings card while being\n the primary thing in its row -- visibly undersized as soon as one sat\n next to any other labelled control.\n\n The description keeps the smaller muted treatment, so the pair still\n reads as title-then-hint rather than two lines of equal weight.\n */}\n \n {label}\n \n {description && (\n \n {description}\n \n )}\n \n {switchEl}\n \n );\n },\n);\nToggle.displayName = \"Toggle\";\n\nexport { Toggle };\n" } ], "docs": "Presentational and controlled: you own the value and the change handler, so it drops straight into a settings list. The switch stays physical under RTL by convention, since it carries an on/off metaphor rather than a directional one.", "meta": { "group": "forms", "related": [ "toggle-group" ], "exports": [ "Toggle" ], "siteSlug": "toggles" } }