torch-glare 2.5.5 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -338
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -317
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -383
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -84
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -63
- package/apps/lib/components/DataViews/states.tsx +0 -38
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -420
- package/apps/lib/components/DropdownMenu.tsx +0 -540
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -73
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -163
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -91
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -47
- package/apps/lib/components/FormBuilder/types.ts +0 -311
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -128
- package/apps/lib/components/FormRenderer/detail.tsx +0 -207
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -297
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -15
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -339
- package/apps/lib/components/FormRenderer/types.ts +0 -78
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -147
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -253
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -610
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -58
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -214
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1201
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -712
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1495
- package/docs/components/data-views/migration.md +0 -79
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -276
- package/docs/components/form-renderer.md +0 -326
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -477
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -54
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1500
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -704
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,770 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Switch
|
|
3
|
-
version: 2.4.5
|
|
4
|
-
status: stable
|
|
5
|
-
category: components/forms
|
|
6
|
-
tags: [form, switch, toggle, radix-ui, accessible, controlled]
|
|
7
|
-
last-reviewed: 2024-11-05
|
|
8
|
-
bundle-size: 1.6kb
|
|
9
|
-
dependencies:
|
|
10
|
-
- "@radix-ui/react-switch": "^1.0.0"
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
# Switch
|
|
14
|
-
|
|
15
|
-
> A fully accessible toggle switch component built on Radix UI primitives. Perfect for boolean settings, feature toggles, and on/off states with smooth animations and keyboard support.
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
18
|
-
|
|
19
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
20
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
npx torch-glare@latest init
|
|
24
|
-
npx torch-glare@latest add Switch
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
`add` also copies any components, hooks, and utilities that `Switch` depends on.
|
|
28
|
-
|
|
29
|
-
## Import
|
|
30
|
-
|
|
31
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
32
|
-
|
|
33
|
-
```tsx
|
|
34
|
-
import { Switch } from "@/components/Switch";
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Quick Examples
|
|
38
|
-
|
|
39
|
-
### Basic Usage
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
import { Switch } from '@/components/Switch'
|
|
43
|
-
|
|
44
|
-
function Example() {
|
|
45
|
-
const [enabled, setEnabled] = useState(false)
|
|
46
|
-
|
|
47
|
-
return (
|
|
48
|
-
<Switch
|
|
49
|
-
checked={enabled}
|
|
50
|
-
onCheckedChange={setEnabled}
|
|
51
|
-
/>
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### With Label
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
function LabeledSwitch() {
|
|
60
|
-
const [notifications, setNotifications] = useState(true)
|
|
61
|
-
|
|
62
|
-
return (
|
|
63
|
-
<div className="flex items-center space-x-3">
|
|
64
|
-
<Switch
|
|
65
|
-
id="notifications"
|
|
66
|
-
checked={notifications}
|
|
67
|
-
onCheckedChange={setNotifications}
|
|
68
|
-
/>
|
|
69
|
-
<label
|
|
70
|
-
htmlFor="notifications"
|
|
71
|
-
className="text-sm font-medium cursor-pointer"
|
|
72
|
-
>
|
|
73
|
-
Enable notifications
|
|
74
|
-
</label>
|
|
75
|
-
</div>
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
### Settings Panel
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
function SettingsPanel() {
|
|
84
|
-
const [settings, setSettings] = useState({
|
|
85
|
-
darkMode: false,
|
|
86
|
-
autoSave: true,
|
|
87
|
-
notifications: true,
|
|
88
|
-
analytics: false
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
const updateSetting = (key: string, value: boolean) => {
|
|
92
|
-
setSettings(prev => ({ ...prev, [key]: value }))
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<div className="space-y-4">
|
|
97
|
-
<div className="flex items-center justify-between">
|
|
98
|
-
<label htmlFor="dark-mode" className="flex flex-col">
|
|
99
|
-
<span className="text-sm font-medium">Dark Mode</span>
|
|
100
|
-
<span className="text-xs text-gray-500">Use dark theme</span>
|
|
101
|
-
</label>
|
|
102
|
-
<Switch
|
|
103
|
-
id="dark-mode"
|
|
104
|
-
checked={settings.darkMode}
|
|
105
|
-
onCheckedChange={(checked) => updateSetting('darkMode', checked)}
|
|
106
|
-
/>
|
|
107
|
-
</div>
|
|
108
|
-
|
|
109
|
-
<div className="flex items-center justify-between">
|
|
110
|
-
<label htmlFor="auto-save" className="flex flex-col">
|
|
111
|
-
<span className="text-sm font-medium">Auto-Save</span>
|
|
112
|
-
<span className="text-xs text-gray-500">Save changes automatically</span>
|
|
113
|
-
</label>
|
|
114
|
-
<Switch
|
|
115
|
-
id="auto-save"
|
|
116
|
-
checked={settings.autoSave}
|
|
117
|
-
onCheckedChange={(checked) => updateSetting('autoSave', checked)}
|
|
118
|
-
/>
|
|
119
|
-
</div>
|
|
120
|
-
|
|
121
|
-
<div className="flex items-center justify-between">
|
|
122
|
-
<label htmlFor="notifications" className="flex flex-col">
|
|
123
|
-
<span className="text-sm font-medium">Notifications</span>
|
|
124
|
-
<span className="text-xs text-gray-500">Receive push notifications</span>
|
|
125
|
-
</label>
|
|
126
|
-
<Switch
|
|
127
|
-
id="notifications"
|
|
128
|
-
checked={settings.notifications}
|
|
129
|
-
onCheckedChange={(checked) => updateSetting('notifications', checked)}
|
|
130
|
-
/>
|
|
131
|
-
</div>
|
|
132
|
-
|
|
133
|
-
<div className="flex items-center justify-between">
|
|
134
|
-
<label htmlFor="analytics" className="flex flex-col">
|
|
135
|
-
<span className="text-sm font-medium">Analytics</span>
|
|
136
|
-
<span className="text-xs text-gray-500">Help improve our service</span>
|
|
137
|
-
</label>
|
|
138
|
-
<Switch
|
|
139
|
-
id="analytics"
|
|
140
|
-
checked={settings.analytics}
|
|
141
|
-
onCheckedChange={(checked) => updateSetting('analytics', checked)}
|
|
142
|
-
/>
|
|
143
|
-
</div>
|
|
144
|
-
</div>
|
|
145
|
-
)
|
|
146
|
-
}
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
### Feature Flags
|
|
150
|
-
|
|
151
|
-
```typescript
|
|
152
|
-
function FeatureFlags() {
|
|
153
|
-
const [features, setFeatures] = useState({
|
|
154
|
-
betaFeatures: false,
|
|
155
|
-
experimentalUI: false,
|
|
156
|
-
debugMode: false
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
const toggleFeature = (feature: keyof typeof features) => {
|
|
160
|
-
setFeatures(prev => ({
|
|
161
|
-
...prev,
|
|
162
|
-
[feature]: !prev[feature]
|
|
163
|
-
}))
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
return (
|
|
167
|
-
<div className="p-4 border rounded">
|
|
168
|
-
<h3 className="font-semibold mb-4">Developer Features</h3>
|
|
169
|
-
|
|
170
|
-
<div className="space-y-3">
|
|
171
|
-
<div className="flex items-center justify-between p-2 hover:bg-gray-50 rounded">
|
|
172
|
-
<div>
|
|
173
|
-
<p className="font-medium">Beta Features</p>
|
|
174
|
-
<p className="text-xs text-gray-500">Enable experimental features</p>
|
|
175
|
-
</div>
|
|
176
|
-
<Switch
|
|
177
|
-
checked={features.betaFeatures}
|
|
178
|
-
onCheckedChange={() => toggleFeature('betaFeatures')}
|
|
179
|
-
/>
|
|
180
|
-
</div>
|
|
181
|
-
|
|
182
|
-
<div className="flex items-center justify-between p-2 hover:bg-gray-50 rounded">
|
|
183
|
-
<div>
|
|
184
|
-
<p className="font-medium">Experimental UI</p>
|
|
185
|
-
<p className="text-xs text-gray-500">Try the new interface</p>
|
|
186
|
-
</div>
|
|
187
|
-
<Switch
|
|
188
|
-
checked={features.experimentalUI}
|
|
189
|
-
onCheckedChange={() => toggleFeature('experimentalUI')}
|
|
190
|
-
/>
|
|
191
|
-
</div>
|
|
192
|
-
|
|
193
|
-
<div className="flex items-center justify-between p-2 hover:bg-gray-50 rounded">
|
|
194
|
-
<div>
|
|
195
|
-
<p className="font-medium">Debug Mode</p>
|
|
196
|
-
<p className="text-xs text-gray-500">Show debug information</p>
|
|
197
|
-
</div>
|
|
198
|
-
<Switch
|
|
199
|
-
checked={features.debugMode}
|
|
200
|
-
onCheckedChange={() => toggleFeature('debugMode')}
|
|
201
|
-
className={features.debugMode ? 'bg-red-500' : ''}
|
|
202
|
-
/>
|
|
203
|
-
</div>
|
|
204
|
-
</div>
|
|
205
|
-
</div>
|
|
206
|
-
)
|
|
207
|
-
}
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### Privacy Settings
|
|
211
|
-
|
|
212
|
-
```typescript
|
|
213
|
-
function PrivacySettings() {
|
|
214
|
-
const [privacy, setPrivacy] = useState({
|
|
215
|
-
shareData: false,
|
|
216
|
-
personalizedAds: false,
|
|
217
|
-
cookies: true,
|
|
218
|
-
tracking: false
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
return (
|
|
222
|
-
<div className="space-y-4">
|
|
223
|
-
<h3 className="text-lg font-semibold">Privacy Settings</h3>
|
|
224
|
-
|
|
225
|
-
{Object.entries(privacy).map(([key, value]) => (
|
|
226
|
-
<div
|
|
227
|
-
key={key}
|
|
228
|
-
className="flex items-center justify-between py-2 border-b"
|
|
229
|
-
>
|
|
230
|
-
<label htmlFor={key} className="flex-1">
|
|
231
|
-
<span className="block font-medium">
|
|
232
|
-
{key.replace(/([A-Z])/g, ' $1').trim()}
|
|
233
|
-
</span>
|
|
234
|
-
<span className="text-sm text-gray-500">
|
|
235
|
-
{getPrivacyDescription(key)}
|
|
236
|
-
</span>
|
|
237
|
-
</label>
|
|
238
|
-
<Switch
|
|
239
|
-
id={key}
|
|
240
|
-
checked={value}
|
|
241
|
-
onCheckedChange={(checked) =>
|
|
242
|
-
setPrivacy(prev => ({ ...prev, [key]: checked }))
|
|
243
|
-
}
|
|
244
|
-
/>
|
|
245
|
-
</div>
|
|
246
|
-
))}
|
|
247
|
-
</div>
|
|
248
|
-
)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function getPrivacyDescription(key: string) {
|
|
252
|
-
const descriptions: Record<string, string> = {
|
|
253
|
-
shareData: 'Share usage data to improve services',
|
|
254
|
-
personalizedAds: 'Show ads based on your interests',
|
|
255
|
-
cookies: 'Use cookies for better experience',
|
|
256
|
-
tracking: 'Allow activity tracking'
|
|
257
|
-
}
|
|
258
|
-
return descriptions[key] || ''
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
### Disabled State
|
|
263
|
-
|
|
264
|
-
```typescript
|
|
265
|
-
function DisabledSwitches() {
|
|
266
|
-
return (
|
|
267
|
-
<div className="space-y-3">
|
|
268
|
-
<div className="flex items-center gap-3">
|
|
269
|
-
<Switch disabled />
|
|
270
|
-
<span className="text-gray-500">Disabled Off</span>
|
|
271
|
-
</div>
|
|
272
|
-
|
|
273
|
-
<div className="flex items-center gap-3">
|
|
274
|
-
<Switch disabled checked />
|
|
275
|
-
<span className="text-gray-500">Disabled On</span>
|
|
276
|
-
</div>
|
|
277
|
-
</div>
|
|
278
|
-
)
|
|
279
|
-
}
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
### Form Integration
|
|
283
|
-
|
|
284
|
-
```typescript
|
|
285
|
-
function NotificationForm() {
|
|
286
|
-
const [formData, setFormData] = useState({
|
|
287
|
-
email: true,
|
|
288
|
-
push: false,
|
|
289
|
-
sms: false
|
|
290
|
-
})
|
|
291
|
-
|
|
292
|
-
const handleSubmit = (e: FormEvent) => {
|
|
293
|
-
e.preventDefault()
|
|
294
|
-
console.log('Notification preferences:', formData)
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
return (
|
|
298
|
-
<form onSubmit={handleSubmit} className="space-y-4">
|
|
299
|
-
<fieldset>
|
|
300
|
-
<legend className="text-lg font-semibold mb-3">
|
|
301
|
-
Notification Channels
|
|
302
|
-
</legend>
|
|
303
|
-
|
|
304
|
-
<div className="space-y-3">
|
|
305
|
-
<div className="flex items-center justify-between">
|
|
306
|
-
<label htmlFor="email-notif">Email Notifications</label>
|
|
307
|
-
<Switch
|
|
308
|
-
id="email-notif"
|
|
309
|
-
checked={formData.email}
|
|
310
|
-
onCheckedChange={(checked) =>
|
|
311
|
-
setFormData({ ...formData, email: checked })
|
|
312
|
-
}
|
|
313
|
-
/>
|
|
314
|
-
</div>
|
|
315
|
-
|
|
316
|
-
<div className="flex items-center justify-between">
|
|
317
|
-
<label htmlFor="push-notif">Push Notifications</label>
|
|
318
|
-
<Switch
|
|
319
|
-
id="push-notif"
|
|
320
|
-
checked={formData.push}
|
|
321
|
-
onCheckedChange={(checked) =>
|
|
322
|
-
setFormData({ ...formData, push: checked })
|
|
323
|
-
}
|
|
324
|
-
/>
|
|
325
|
-
</div>
|
|
326
|
-
|
|
327
|
-
<div className="flex items-center justify-between">
|
|
328
|
-
<label htmlFor="sms-notif">SMS Notifications</label>
|
|
329
|
-
<Switch
|
|
330
|
-
id="sms-notif"
|
|
331
|
-
checked={formData.sms}
|
|
332
|
-
onCheckedChange={(checked) =>
|
|
333
|
-
setFormData({ ...formData, sms: checked })
|
|
334
|
-
}
|
|
335
|
-
/>
|
|
336
|
-
</div>
|
|
337
|
-
</div>
|
|
338
|
-
</fieldset>
|
|
339
|
-
|
|
340
|
-
<button type="submit" className="px-4 py-2 bg-blue-500 text-white rounded">
|
|
341
|
-
Save Preferences
|
|
342
|
-
</button>
|
|
343
|
-
</form>
|
|
344
|
-
)
|
|
345
|
-
}
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
## API Reference
|
|
349
|
-
|
|
350
|
-
### Switch Props
|
|
351
|
-
|
|
352
|
-
| Prop | Type | Default | Description |
|
|
353
|
-
|------|------|---------|-------------|
|
|
354
|
-
| `checked` | `boolean` | - | Controlled checked state |
|
|
355
|
-
| `defaultChecked` | `boolean` | `false` | Uncontrolled default state |
|
|
356
|
-
| `onCheckedChange` | `(checked: boolean) => void` | - | Called when state changes |
|
|
357
|
-
| `disabled` | `boolean` | `false` | Disables the switch |
|
|
358
|
-
| `required` | `boolean` | `false` | Makes field required in forms |
|
|
359
|
-
| `name` | `string` | - | Form field name |
|
|
360
|
-
| `value` | `string` | `'on'` | Form submission value |
|
|
361
|
-
| `id` | `string` | - | HTML id for label association |
|
|
362
|
-
| `className` | `string` | - | Additional CSS classes |
|
|
363
|
-
|
|
364
|
-
### TypeScript
|
|
365
|
-
|
|
366
|
-
```typescript
|
|
367
|
-
import { SwitchProps } from '@radix-ui/react-switch'
|
|
368
|
-
|
|
369
|
-
interface CustomSwitchProps extends SwitchProps {
|
|
370
|
-
className?: string
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
export const Switch: React.ForwardRefExoticComponent<CustomSwitchProps>
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
## Common Patterns
|
|
377
|
-
|
|
378
|
-
### Conditional Content
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
function ConditionalSettings() {
|
|
382
|
-
const [advancedMode, setAdvancedMode] = useState(false)
|
|
383
|
-
|
|
384
|
-
return (
|
|
385
|
-
<div className="space-y-4">
|
|
386
|
-
<div className="flex items-center gap-3">
|
|
387
|
-
<Switch
|
|
388
|
-
id="advanced"
|
|
389
|
-
checked={advancedMode}
|
|
390
|
-
onCheckedChange={setAdvancedMode}
|
|
391
|
-
/>
|
|
392
|
-
<label htmlFor="advanced">Advanced Mode</label>
|
|
393
|
-
</div>
|
|
394
|
-
|
|
395
|
-
{advancedMode && (
|
|
396
|
-
<div className="p-4 border rounded bg-gray-50">
|
|
397
|
-
<h4 className="font-semibold mb-2">Advanced Settings</h4>
|
|
398
|
-
<div className="space-y-2">
|
|
399
|
-
<input placeholder="API Key" className="w-full p-2 border rounded" />
|
|
400
|
-
<input placeholder="Webhook URL" className="w-full p-2 border rounded" />
|
|
401
|
-
<select className="w-full p-2 border rounded">
|
|
402
|
-
<option>Debug Level: Info</option>
|
|
403
|
-
<option>Debug Level: Warning</option>
|
|
404
|
-
<option>Debug Level: Error</option>
|
|
405
|
-
</select>
|
|
406
|
-
</div>
|
|
407
|
-
</div>
|
|
408
|
-
)}
|
|
409
|
-
</div>
|
|
410
|
-
)
|
|
411
|
-
}
|
|
412
|
-
```
|
|
413
|
-
|
|
414
|
-
### Live Preview Toggle
|
|
415
|
-
|
|
416
|
-
```typescript
|
|
417
|
-
function LivePreviewToggle() {
|
|
418
|
-
const [livePreview, setLivePreview] = useState(true)
|
|
419
|
-
const [previewDelay, setPreviewDelay] = useState(500)
|
|
420
|
-
|
|
421
|
-
return (
|
|
422
|
-
<div className="space-y-3">
|
|
423
|
-
<div className="flex items-center justify-between">
|
|
424
|
-
<label htmlFor="live-preview">
|
|
425
|
-
Live Preview
|
|
426
|
-
{livePreview && (
|
|
427
|
-
<span className="ml-2 text-xs text-green-600">● Active</span>
|
|
428
|
-
)}
|
|
429
|
-
</label>
|
|
430
|
-
<Switch
|
|
431
|
-
id="live-preview"
|
|
432
|
-
checked={livePreview}
|
|
433
|
-
onCheckedChange={setLivePreview}
|
|
434
|
-
/>
|
|
435
|
-
</div>
|
|
436
|
-
|
|
437
|
-
{livePreview && (
|
|
438
|
-
<div className="ml-4">
|
|
439
|
-
<label className="text-sm text-gray-600">
|
|
440
|
-
Delay: {previewDelay}ms
|
|
441
|
-
<input
|
|
442
|
-
type="range"
|
|
443
|
-
min="0"
|
|
444
|
-
max="2000"
|
|
445
|
-
step="100"
|
|
446
|
-
value={previewDelay}
|
|
447
|
-
onChange={(e) => setPreviewDelay(Number(e.target.value))}
|
|
448
|
-
className="w-full"
|
|
449
|
-
/>
|
|
450
|
-
</label>
|
|
451
|
-
</div>
|
|
452
|
-
)}
|
|
453
|
-
</div>
|
|
454
|
-
)
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
### Sync Settings
|
|
459
|
-
|
|
460
|
-
```typescript
|
|
461
|
-
function SyncSettings() {
|
|
462
|
-
const [syncing, setSyncing] = useState(false)
|
|
463
|
-
const [autoSync, setAutoSync] = useState(false)
|
|
464
|
-
|
|
465
|
-
const handleSync = async (enabled: boolean) => {
|
|
466
|
-
setAutoSync(enabled)
|
|
467
|
-
if (enabled) {
|
|
468
|
-
setSyncing(true)
|
|
469
|
-
// Simulate sync
|
|
470
|
-
await new Promise(resolve => setTimeout(resolve, 2000))
|
|
471
|
-
setSyncing(false)
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
return (
|
|
476
|
-
<div className="flex items-center justify-between p-4 border rounded">
|
|
477
|
-
<div>
|
|
478
|
-
<p className="font-medium">Auto Sync</p>
|
|
479
|
-
<p className="text-sm text-gray-500">
|
|
480
|
-
{syncing ? 'Syncing...' : 'Sync data across devices'}
|
|
481
|
-
</p>
|
|
482
|
-
</div>
|
|
483
|
-
<Switch
|
|
484
|
-
checked={autoSync}
|
|
485
|
-
onCheckedChange={handleSync}
|
|
486
|
-
disabled={syncing}
|
|
487
|
-
/>
|
|
488
|
-
</div>
|
|
489
|
-
)
|
|
490
|
-
}
|
|
491
|
-
```
|
|
492
|
-
|
|
493
|
-
## Testing
|
|
494
|
-
|
|
495
|
-
### Unit Test Example
|
|
496
|
-
|
|
497
|
-
```typescript
|
|
498
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
499
|
-
import { Switch } from '@/components/Switch'
|
|
500
|
-
|
|
501
|
-
describe('Switch', () => {
|
|
502
|
-
it('toggles state on click', () => {
|
|
503
|
-
const handleChange = jest.fn()
|
|
504
|
-
render(
|
|
505
|
-
<Switch onCheckedChange={handleChange} />
|
|
506
|
-
)
|
|
507
|
-
|
|
508
|
-
const switchElement = screen.getByRole('switch')
|
|
509
|
-
fireEvent.click(switchElement)
|
|
510
|
-
|
|
511
|
-
expect(handleChange).toHaveBeenCalledWith(true)
|
|
512
|
-
})
|
|
513
|
-
|
|
514
|
-
it('respects disabled state', () => {
|
|
515
|
-
const handleChange = jest.fn()
|
|
516
|
-
render(
|
|
517
|
-
<Switch disabled onCheckedChange={handleChange} />
|
|
518
|
-
)
|
|
519
|
-
|
|
520
|
-
const switchElement = screen.getByRole('switch')
|
|
521
|
-
fireEvent.click(switchElement)
|
|
522
|
-
|
|
523
|
-
expect(handleChange).not.toHaveBeenCalled()
|
|
524
|
-
expect(switchElement).toBeDisabled()
|
|
525
|
-
})
|
|
526
|
-
|
|
527
|
-
it('shows correct checked state', () => {
|
|
528
|
-
const { rerender } = render(<Switch checked={false} />)
|
|
529
|
-
|
|
530
|
-
let switchElement = screen.getByRole('switch')
|
|
531
|
-
expect(switchElement).toHaveAttribute('data-state', 'unchecked')
|
|
532
|
-
|
|
533
|
-
rerender(<Switch checked={true} />)
|
|
534
|
-
switchElement = screen.getByRole('switch')
|
|
535
|
-
expect(switchElement).toHaveAttribute('data-state', 'checked')
|
|
536
|
-
})
|
|
537
|
-
})
|
|
538
|
-
```
|
|
539
|
-
|
|
540
|
-
### Accessibility Test
|
|
541
|
-
|
|
542
|
-
```typescript
|
|
543
|
-
import { axe } from '@axe-core/react'
|
|
544
|
-
|
|
545
|
-
test('Switch meets WCAG standards', async () => {
|
|
546
|
-
const { container } = render(
|
|
547
|
-
<div>
|
|
548
|
-
<label htmlFor="test-switch">Enable feature</label>
|
|
549
|
-
<Switch id="test-switch" />
|
|
550
|
-
</div>
|
|
551
|
-
)
|
|
552
|
-
|
|
553
|
-
const results = await axe(container)
|
|
554
|
-
expect(results).toHaveNoViolations()
|
|
555
|
-
})
|
|
556
|
-
```
|
|
557
|
-
|
|
558
|
-
## Accessibility
|
|
559
|
-
|
|
560
|
-
### Keyboard Support
|
|
561
|
-
|
|
562
|
-
- **Space**: Toggle switch when focused
|
|
563
|
-
- **Tab**: Move focus to/from switch
|
|
564
|
-
- **Enter**: Toggle switch (in some contexts)
|
|
565
|
-
|
|
566
|
-
### ARIA Attributes
|
|
567
|
-
|
|
568
|
-
Radix UI automatically provides:
|
|
569
|
-
|
|
570
|
-
```html
|
|
571
|
-
<!-- Unchecked state -->
|
|
572
|
-
<button
|
|
573
|
-
role="switch"
|
|
574
|
-
aria-checked="false"
|
|
575
|
-
data-state="unchecked"
|
|
576
|
-
/>
|
|
577
|
-
|
|
578
|
-
<!-- Checked state -->
|
|
579
|
-
<button
|
|
580
|
-
role="switch"
|
|
581
|
-
aria-checked="true"
|
|
582
|
-
data-state="checked"
|
|
583
|
-
/>
|
|
584
|
-
|
|
585
|
-
<!-- Disabled -->
|
|
586
|
-
<button
|
|
587
|
-
role="switch"
|
|
588
|
-
aria-checked="false"
|
|
589
|
-
disabled
|
|
590
|
-
/>
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
### Screen Reader Support
|
|
594
|
-
|
|
595
|
-
- Announces switch role
|
|
596
|
-
- Communicates on/off state
|
|
597
|
-
- Reads associated labels
|
|
598
|
-
- Announces state changes
|
|
599
|
-
|
|
600
|
-
### Label Association
|
|
601
|
-
|
|
602
|
-
```typescript
|
|
603
|
-
// Method 1: Using htmlFor/id
|
|
604
|
-
<label htmlFor="switch-id">Label</label>
|
|
605
|
-
<Switch id="switch-id" />
|
|
606
|
-
|
|
607
|
-
// Method 2: Wrapping
|
|
608
|
-
<label>
|
|
609
|
-
<Switch />
|
|
610
|
-
<span>Label</span>
|
|
611
|
-
</label>
|
|
612
|
-
|
|
613
|
-
// Method 3: aria-label
|
|
614
|
-
<Switch aria-label="Enable feature" />
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
## Styling
|
|
618
|
-
|
|
619
|
-
### Custom Styles
|
|
620
|
-
|
|
621
|
-
```typescript
|
|
622
|
-
// Custom colors
|
|
623
|
-
<Switch
|
|
624
|
-
className="data-[state=checked]:bg-green-500 data-[state=unchecked]:bg-gray-300"
|
|
625
|
-
/>
|
|
626
|
-
|
|
627
|
-
// Custom size
|
|
628
|
-
<Switch
|
|
629
|
-
className="w-16 h-8 [&>span]:w-7 [&>span]:h-7"
|
|
630
|
-
/>
|
|
631
|
-
```
|
|
632
|
-
|
|
633
|
-
### State-Based Styling
|
|
634
|
-
|
|
635
|
-
```css
|
|
636
|
-
/* Using data attributes */
|
|
637
|
-
.switch[data-state="checked"] {
|
|
638
|
-
background-color: var(--color-primary);
|
|
639
|
-
}
|
|
640
|
-
|
|
641
|
-
.switch[data-state="unchecked"] {
|
|
642
|
-
background-color: var(--color-secondary);
|
|
643
|
-
}
|
|
644
|
-
```
|
|
645
|
-
|
|
646
|
-
### Animation
|
|
647
|
-
|
|
648
|
-
The switch includes smooth transitions:
|
|
649
|
-
|
|
650
|
-
```css
|
|
651
|
-
/* Thumb animation */
|
|
652
|
-
.switch-thumb {
|
|
653
|
-
transition: transform 100ms;
|
|
654
|
-
transform: translateX(0);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
.switch[data-state="checked"] .switch-thumb {
|
|
658
|
-
transform: translateX(21px);
|
|
659
|
-
}
|
|
660
|
-
```
|
|
661
|
-
|
|
662
|
-
## Performance
|
|
663
|
-
|
|
664
|
-
| Metric | Value |
|
|
665
|
-
|--------|-------|
|
|
666
|
-
| Bundle size (gzip) | 1.6kb |
|
|
667
|
-
| First render | <4ms |
|
|
668
|
-
| Interaction | <1ms |
|
|
669
|
-
| Animation | 100ms |
|
|
670
|
-
| Tree-shakeable | ✅ |
|
|
671
|
-
|
|
672
|
-
### Optimization Tips
|
|
673
|
-
|
|
674
|
-
1. Use uncontrolled mode with `defaultChecked` when possible
|
|
675
|
-
2. Memoize change handlers with `useCallback`
|
|
676
|
-
3. Avoid inline functions in render
|
|
677
|
-
4. Group multiple switches in a single state object
|
|
678
|
-
|
|
679
|
-
## Migration
|
|
680
|
-
|
|
681
|
-
### From Checkbox
|
|
682
|
-
|
|
683
|
-
```diff
|
|
684
|
-
// From checkbox used as toggle
|
|
685
|
-
- <input
|
|
686
|
-
- type="checkbox"
|
|
687
|
-
- checked={enabled}
|
|
688
|
-
- onChange={(e) => setEnabled(e.target.checked)}
|
|
689
|
-
- />
|
|
690
|
-
|
|
691
|
-
// To Switch
|
|
692
|
-
+ <Switch
|
|
693
|
-
+ checked={enabled}
|
|
694
|
-
+ onCheckedChange={setEnabled}
|
|
695
|
-
+ />
|
|
696
|
-
```
|
|
697
|
-
|
|
698
|
-
### From Custom Toggle
|
|
699
|
-
|
|
700
|
-
```diff
|
|
701
|
-
// From custom implementation
|
|
702
|
-
- <button
|
|
703
|
-
- onClick={() => setEnabled(!enabled)}
|
|
704
|
-
- className={enabled ? 'bg-blue-500' : 'bg-gray-300'}
|
|
705
|
-
- >
|
|
706
|
-
- <span className={enabled ? 'translate-x-5' : ''} />
|
|
707
|
-
- </button>
|
|
708
|
-
|
|
709
|
-
// To Switch
|
|
710
|
-
+ <Switch
|
|
711
|
-
+ checked={enabled}
|
|
712
|
-
+ onCheckedChange={setEnabled}
|
|
713
|
-
+ />
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
## Troubleshooting
|
|
717
|
-
|
|
718
|
-
### Switch not toggling
|
|
719
|
-
|
|
720
|
-
**Solution:** Ensure proper controlled/uncontrolled usage
|
|
721
|
-
|
|
722
|
-
```typescript
|
|
723
|
-
// Controlled - requires both props
|
|
724
|
-
<Switch checked={value} onCheckedChange={setValue} />
|
|
725
|
-
|
|
726
|
-
// Uncontrolled - use defaultChecked
|
|
727
|
-
<Switch defaultChecked />
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
### Label not clickable
|
|
731
|
-
|
|
732
|
-
**Solution:** Properly associate label with switch
|
|
733
|
-
|
|
734
|
-
```typescript
|
|
735
|
-
// ✅ Correct
|
|
736
|
-
<label htmlFor="my-switch">Label</label>
|
|
737
|
-
<Switch id="my-switch" />
|
|
738
|
-
|
|
739
|
-
// ❌ Wrong - no association
|
|
740
|
-
<label>Label</label>
|
|
741
|
-
<Switch />
|
|
742
|
-
```
|
|
743
|
-
|
|
744
|
-
## Related Components
|
|
745
|
-
|
|
746
|
-
- [Toggle](/docs/components/toggle.md) - Toggle button component
|
|
747
|
-
- [Checkbox](/docs/components/checkbox.md) - For multiple selections
|
|
748
|
-
- [Radio](/docs/components/radio.md) - For single choice from options
|
|
749
|
-
|
|
750
|
-
## Browser Support
|
|
751
|
-
|
|
752
|
-
- Chrome 90+ ✅
|
|
753
|
-
- Firefox 88+ ✅
|
|
754
|
-
- Safari 14+ ✅
|
|
755
|
-
- Edge 90+ ✅
|
|
756
|
-
- Mobile browsers ✅
|
|
757
|
-
|
|
758
|
-
## Changelog
|
|
759
|
-
|
|
760
|
-
### v1.1.15
|
|
761
|
-
- Migrated to Radix UI Switch primitive
|
|
762
|
-
- Added smooth animations
|
|
763
|
-
- Improved accessibility
|
|
764
|
-
|
|
765
|
-
### v1.1.14
|
|
766
|
-
- Enhanced visual design
|
|
767
|
-
- Fixed focus styles
|
|
768
|
-
|
|
769
|
-
### v1.1.0
|
|
770
|
-
- Initial stable release
|