torch-glare 2.5.6 → 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 -403
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -325
- 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 -395
- 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 -88
- 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 -72
- package/apps/lib/components/DataViews/states.tsx +0 -73
- 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 -451
- package/apps/lib/components/DropdownMenu.tsx +0 -554
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -85
- 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 -168
- 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 -114
- 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 -67
- package/apps/lib/components/FormBuilder/types.ts +0 -316
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -250
- package/apps/lib/components/FormRenderer/detail.tsx +0 -256
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -358
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -17
- package/apps/lib/components/FormRenderer/notch-action.tsx +0 -64
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -393
- package/apps/lib/components/FormRenderer/types.ts +0 -115
- 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 -168
- 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 -255
- 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 -597
- 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 -61
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useHtmlDir.ts +0 -31
- 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 -300
- 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 -1217
- 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/scroller.ts +0 -26
- 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 -738
- 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 -1521
- package/docs/components/data-views/migration.md +0 -81
- 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 -284
- package/docs/components/form-renderer.md +0 -396
- 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 -483
- 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 -60
- 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 -1523
- 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 -726
- 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,709 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Select
|
|
3
|
-
version: 2.4.5
|
|
4
|
-
status: stable
|
|
5
|
-
category: components/forms
|
|
6
|
-
tags: [form, select, dropdown, accessible, radix-ui]
|
|
7
|
-
last-reviewed: 2024-11-05
|
|
8
|
-
bundle-size: 4.5kb
|
|
9
|
-
dependencies:
|
|
10
|
-
- "@radix-ui/react-select": "^2.0.0"
|
|
11
|
-
- "class-variance-authority": "^0.7.0"
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Select
|
|
15
|
-
|
|
16
|
-
> A fully accessible dropdown select component built on Radix UI primitives. Supports single selection, scrolling, custom triggers, and full keyboard navigation.
|
|
17
|
-
|
|
18
|
-
## Installation
|
|
19
|
-
|
|
20
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
21
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
npx torch-glare@latest init
|
|
25
|
-
npx torch-glare@latest add Select
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
`add` also copies any components, hooks, and utilities that `Select` depends on.
|
|
29
|
-
|
|
30
|
-
## Import
|
|
31
|
-
|
|
32
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
33
|
-
|
|
34
|
-
```tsx
|
|
35
|
-
import { Select } from "@/components/Select";
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
## Quick Examples
|
|
39
|
-
|
|
40
|
-
### Basic Usage
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
import {
|
|
44
|
-
Select,
|
|
45
|
-
SelectTrigger,
|
|
46
|
-
SelectContent,
|
|
47
|
-
SelectItem,
|
|
48
|
-
SelectValue
|
|
49
|
-
} from '@/components/Select'
|
|
50
|
-
|
|
51
|
-
function Example() {
|
|
52
|
-
const [value, setValue] = useState('')
|
|
53
|
-
|
|
54
|
-
return (
|
|
55
|
-
<Select value={value} onValueChange={setValue}>
|
|
56
|
-
<SelectTrigger className="w-[180px]">
|
|
57
|
-
<SelectValue placeholder="Select an option" />
|
|
58
|
-
</SelectTrigger>
|
|
59
|
-
<SelectContent>
|
|
60
|
-
<SelectItem value="option1">Option 1</SelectItem>
|
|
61
|
-
<SelectItem value="option2">Option 2</SelectItem>
|
|
62
|
-
<SelectItem value="option3">Option 3</SelectItem>
|
|
63
|
-
</SelectContent>
|
|
64
|
-
</Select>
|
|
65
|
-
)
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
### With Groups
|
|
70
|
-
|
|
71
|
-
```typescript
|
|
72
|
-
<Select>
|
|
73
|
-
<SelectTrigger className="w-[200px]">
|
|
74
|
-
<SelectValue placeholder="Select a fruit" />
|
|
75
|
-
</SelectTrigger>
|
|
76
|
-
<SelectContent>
|
|
77
|
-
<SelectGroup>
|
|
78
|
-
<SelectLabel>Fruits</SelectLabel>
|
|
79
|
-
<SelectItem value="apple">Apple</SelectItem>
|
|
80
|
-
<SelectItem value="banana">Banana</SelectItem>
|
|
81
|
-
<SelectItem value="orange">Orange</SelectItem>
|
|
82
|
-
</SelectGroup>
|
|
83
|
-
<SelectSeparator />
|
|
84
|
-
<SelectGroup>
|
|
85
|
-
<SelectLabel>Vegetables</SelectLabel>
|
|
86
|
-
<SelectItem value="carrot">Carrot</SelectItem>
|
|
87
|
-
<SelectItem value="potato">Potato</SelectItem>
|
|
88
|
-
<SelectItem value="tomato">Tomato</SelectItem>
|
|
89
|
-
</SelectGroup>
|
|
90
|
-
</SelectContent>
|
|
91
|
-
</Select>
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### Different Sizes
|
|
95
|
-
|
|
96
|
-
```typescript
|
|
97
|
-
// Small
|
|
98
|
-
<Select>
|
|
99
|
-
<SelectTrigger size="S" className="w-[150px]">
|
|
100
|
-
<SelectValue placeholder="Small" />
|
|
101
|
-
</SelectTrigger>
|
|
102
|
-
<SelectContent>
|
|
103
|
-
<SelectItem value="1">Item 1</SelectItem>
|
|
104
|
-
</SelectContent>
|
|
105
|
-
</Select>
|
|
106
|
-
|
|
107
|
-
// Medium (default)
|
|
108
|
-
<Select>
|
|
109
|
-
<SelectTrigger size="M" className="w-[180px]">
|
|
110
|
-
<SelectValue placeholder="Medium" />
|
|
111
|
-
</SelectTrigger>
|
|
112
|
-
<SelectContent>
|
|
113
|
-
<SelectItem value="1">Item 1</SelectItem>
|
|
114
|
-
</SelectContent>
|
|
115
|
-
</Select>
|
|
116
|
-
|
|
117
|
-
// Large
|
|
118
|
-
<Select>
|
|
119
|
-
<SelectTrigger size="L" className="w-[220px]">
|
|
120
|
-
<SelectValue placeholder="Large" />
|
|
121
|
-
</SelectTrigger>
|
|
122
|
-
<SelectContent>
|
|
123
|
-
<SelectItem value="1">Item 1</SelectItem>
|
|
124
|
-
</SelectContent>
|
|
125
|
-
</Select>
|
|
126
|
-
|
|
127
|
-
// Extra Large
|
|
128
|
-
<Select>
|
|
129
|
-
<SelectTrigger size="XL" className="w-[250px]">
|
|
130
|
-
<SelectValue placeholder="Extra Large" />
|
|
131
|
-
</SelectTrigger>
|
|
132
|
-
<SelectContent>
|
|
133
|
-
<SelectItem value="1">Item 1</SelectItem>
|
|
134
|
-
</SelectContent>
|
|
135
|
-
</Select>
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
### With Error State
|
|
139
|
-
|
|
140
|
-
```typescript
|
|
141
|
-
function SelectWithValidation() {
|
|
142
|
-
const [value, setValue] = useState('')
|
|
143
|
-
const [error, setError] = useState('')
|
|
144
|
-
|
|
145
|
-
const handleChange = (newValue: string) => {
|
|
146
|
-
setValue(newValue)
|
|
147
|
-
if (!newValue) {
|
|
148
|
-
setError('Please select an option')
|
|
149
|
-
} else {
|
|
150
|
-
setError('')
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
return (
|
|
155
|
-
<Select value={value} onValueChange={handleChange}>
|
|
156
|
-
<SelectTrigger
|
|
157
|
-
errors={error}
|
|
158
|
-
className="w-[200px]"
|
|
159
|
-
>
|
|
160
|
-
<SelectValue placeholder="Select required" />
|
|
161
|
-
</SelectTrigger>
|
|
162
|
-
<SelectContent>
|
|
163
|
-
<SelectItem value="option1">Option 1</SelectItem>
|
|
164
|
-
<SelectItem value="option2">Option 2</SelectItem>
|
|
165
|
-
</SelectContent>
|
|
166
|
-
</Select>
|
|
167
|
-
)
|
|
168
|
-
}
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
### With Custom Icon
|
|
172
|
-
|
|
173
|
-
```typescript
|
|
174
|
-
<Select>
|
|
175
|
-
<SelectTrigger icon="custom-icon-class" className="w-[200px]">
|
|
176
|
-
<SelectValue placeholder="Custom icon" />
|
|
177
|
-
</SelectTrigger>
|
|
178
|
-
<SelectContent>
|
|
179
|
-
<SelectItem value="1">Item 1</SelectItem>
|
|
180
|
-
<SelectItem value="2">Item 2</SelectItem>
|
|
181
|
-
</SelectContent>
|
|
182
|
-
</Select>
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Controlled vs Uncontrolled
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
// Controlled
|
|
189
|
-
function Controlled() {
|
|
190
|
-
const [value, setValue] = useState('apple')
|
|
191
|
-
|
|
192
|
-
return (
|
|
193
|
-
<Select value={value} onValueChange={setValue}>
|
|
194
|
-
<SelectTrigger>
|
|
195
|
-
<SelectValue />
|
|
196
|
-
</SelectTrigger>
|
|
197
|
-
<SelectContent>
|
|
198
|
-
<SelectItem value="apple">Apple</SelectItem>
|
|
199
|
-
<SelectItem value="orange">Orange</SelectItem>
|
|
200
|
-
</SelectContent>
|
|
201
|
-
</Select>
|
|
202
|
-
)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Uncontrolled with default value
|
|
206
|
-
function Uncontrolled() {
|
|
207
|
-
return (
|
|
208
|
-
<Select defaultValue="apple">
|
|
209
|
-
<SelectTrigger>
|
|
210
|
-
<SelectValue />
|
|
211
|
-
</SelectTrigger>
|
|
212
|
-
<SelectContent>
|
|
213
|
-
<SelectItem value="apple">Apple</SelectItem>
|
|
214
|
-
<SelectItem value="orange">Orange</SelectItem>
|
|
215
|
-
</SelectContent>
|
|
216
|
-
</Select>
|
|
217
|
-
)
|
|
218
|
-
}
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
## API Reference
|
|
222
|
-
|
|
223
|
-
### Select Props
|
|
224
|
-
|
|
225
|
-
| Prop | Type | Default | Description |
|
|
226
|
-
|------|------|---------|-------------|
|
|
227
|
-
| `value` | `string` | - | Controlled value |
|
|
228
|
-
| `defaultValue` | `string` | - | Default value for uncontrolled |
|
|
229
|
-
| `onValueChange` | `(value: string) => void` | - | Called when value changes |
|
|
230
|
-
| `open` | `boolean` | - | Controlled open state |
|
|
231
|
-
| `defaultOpen` | `boolean` | `false` | Default open state |
|
|
232
|
-
| `onOpenChange` | `(open: boolean) => void` | - | Called when open state changes |
|
|
233
|
-
| `disabled` | `boolean` | `false` | Disable the select |
|
|
234
|
-
| `required` | `boolean` | `false` | Make selection required |
|
|
235
|
-
| `name` | `string` | - | Name for form submission |
|
|
236
|
-
| `dir` | `'ltr' \| 'rtl'` | `'ltr'` | Text direction |
|
|
237
|
-
|
|
238
|
-
### SelectTrigger Props
|
|
239
|
-
|
|
240
|
-
| Prop | Type | Default | Description |
|
|
241
|
-
|------|------|---------|-------------|
|
|
242
|
-
| `size` | `'S' \| 'M' \| 'L' \| 'XL'` | `'M'` | Size of the trigger |
|
|
243
|
-
| `variant` | `'PresentationStyle' \| 'SystemStyle'` | `'PresentationStyle'` | Visual variant |
|
|
244
|
-
| `errors` | `string` | - | Marks the trigger invalid — any non-undefined value turns on the negative border |
|
|
245
|
-
| `theme` | `Themes` | - | Theme override |
|
|
246
|
-
| `icon` | `string` | - | Custom icon class |
|
|
247
|
-
| `className` | `string` | - | Additional CSS classes |
|
|
248
|
-
| `asChild` | `boolean` | `false` | Render as child element |
|
|
249
|
-
|
|
250
|
-
### SelectContent Props
|
|
251
|
-
|
|
252
|
-
| Prop | Type | Default | Description |
|
|
253
|
-
|------|------|---------|-------------|
|
|
254
|
-
| `variant` | `'PresentationStyle' \| 'SystemStyle'` | `'PresentationStyle'` | Visual variant |
|
|
255
|
-
| `position` | `'item-aligned' \| 'popper'` | `'popper'` | Positioning strategy |
|
|
256
|
-
| `side` | `'top' \| 'bottom'` | `'bottom'` | Preferred side |
|
|
257
|
-
| `align` | `'start' \| 'center' \| 'end'` | `'center'` | Alignment |
|
|
258
|
-
| `sideOffset` | `number` | `4` | Offset from trigger |
|
|
259
|
-
| `theme` | `Themes` | - | Theme override |
|
|
260
|
-
| `className` | `string` | - | Additional CSS classes |
|
|
261
|
-
|
|
262
|
-
### SelectItem Props
|
|
263
|
-
|
|
264
|
-
| Prop | Type | Default | Description |
|
|
265
|
-
|------|------|---------|-------------|
|
|
266
|
-
| `value` | `string` | - | Item value (required) |
|
|
267
|
-
| `variant` | `'Default' \| 'Warning' \| 'Negative' \| 'SystemStyle'` | `'Default'` | Visual variant |
|
|
268
|
-
| `size` | `'S' \| 'M'` | `'M'` | Item size |
|
|
269
|
-
| `active` | `boolean` | `false` | Renders the item in its selected/active style |
|
|
270
|
-
| `disabled` | `boolean` | `false` | Disable item |
|
|
271
|
-
| `className` | `string` | - | Additional CSS classes |
|
|
272
|
-
| `children` | `React.ReactNode` | - | Item content |
|
|
273
|
-
|
|
274
|
-
### TypeScript
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
import type { Themes } from '@/utils/types'
|
|
278
|
-
|
|
279
|
-
// Select component types
|
|
280
|
-
interface SelectProps {
|
|
281
|
-
value?: string
|
|
282
|
-
defaultValue?: string
|
|
283
|
-
onValueChange?: (value: string) => void
|
|
284
|
-
open?: boolean
|
|
285
|
-
defaultOpen?: boolean
|
|
286
|
-
onOpenChange?: (open: boolean) => void
|
|
287
|
-
disabled?: boolean
|
|
288
|
-
required?: boolean
|
|
289
|
-
name?: string
|
|
290
|
-
dir?: 'ltr' | 'rtl'
|
|
291
|
-
children: React.ReactNode
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// Trigger types
|
|
295
|
-
interface SelectTriggerProps {
|
|
296
|
-
size?: 'S' | 'M' | 'L' | 'XL'
|
|
297
|
-
variant?: 'PresentationStyle' | 'SystemStyle'
|
|
298
|
-
errors?: string
|
|
299
|
-
theme?: Themes
|
|
300
|
-
icon?: string
|
|
301
|
-
className?: string
|
|
302
|
-
asChild?: boolean
|
|
303
|
-
children?: React.ReactNode
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// Content types
|
|
307
|
-
interface SelectContentProps {
|
|
308
|
-
variant?: 'PresentationStyle' | 'SystemStyle'
|
|
309
|
-
position?: 'item-aligned' | 'popper'
|
|
310
|
-
side?: 'top' | 'bottom'
|
|
311
|
-
align?: 'start' | 'center' | 'end'
|
|
312
|
-
sideOffset?: number
|
|
313
|
-
theme?: Themes
|
|
314
|
-
className?: string
|
|
315
|
-
children: React.ReactNode
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
// Item types
|
|
319
|
-
interface SelectItemProps {
|
|
320
|
-
value: string
|
|
321
|
-
variant?: 'Default' | 'Warning' | 'Negative' | 'SystemStyle'
|
|
322
|
-
size?: 'S' | 'M'
|
|
323
|
-
active?: boolean
|
|
324
|
-
disabled?: boolean
|
|
325
|
-
className?: string
|
|
326
|
-
children: React.ReactNode
|
|
327
|
-
}
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
## Common Patterns
|
|
331
|
-
|
|
332
|
-
### Country Selector
|
|
333
|
-
|
|
334
|
-
```typescript
|
|
335
|
-
function CountrySelect() {
|
|
336
|
-
const countries = [
|
|
337
|
-
{ code: 'us', name: 'United States', flag: '🇺🇸' },
|
|
338
|
-
{ code: 'gb', name: 'United Kingdom', flag: '🇬🇧' },
|
|
339
|
-
{ code: 'ca', name: 'Canada', flag: '🇨🇦' },
|
|
340
|
-
{ code: 'au', name: 'Australia', flag: '🇦🇺' },
|
|
341
|
-
]
|
|
342
|
-
|
|
343
|
-
const [selected, setSelected] = useState('us')
|
|
344
|
-
|
|
345
|
-
return (
|
|
346
|
-
<Select value={selected} onValueChange={setSelected}>
|
|
347
|
-
<SelectTrigger className="w-[250px]">
|
|
348
|
-
<SelectValue>
|
|
349
|
-
{countries.find(c => c.code === selected)?.flag}{' '}
|
|
350
|
-
{countries.find(c => c.code === selected)?.name}
|
|
351
|
-
</SelectValue>
|
|
352
|
-
</SelectTrigger>
|
|
353
|
-
<SelectContent>
|
|
354
|
-
{countries.map(country => (
|
|
355
|
-
<SelectItem key={country.code} value={country.code}>
|
|
356
|
-
<span className="flex items-center gap-2">
|
|
357
|
-
<span>{country.flag}</span>
|
|
358
|
-
<span>{country.name}</span>
|
|
359
|
-
</span>
|
|
360
|
-
</SelectItem>
|
|
361
|
-
))}
|
|
362
|
-
</SelectContent>
|
|
363
|
-
</Select>
|
|
364
|
-
)
|
|
365
|
-
}
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
### Form Integration
|
|
369
|
-
|
|
370
|
-
```typescript
|
|
371
|
-
import { Form } from '@/components/Form'
|
|
372
|
-
import { Label } from '@/components/Label'
|
|
373
|
-
|
|
374
|
-
function FormSelect() {
|
|
375
|
-
const [formData, setFormData] = useState({
|
|
376
|
-
category: '',
|
|
377
|
-
priority: ''
|
|
378
|
-
})
|
|
379
|
-
|
|
380
|
-
const handleSubmit = (e: FormEvent) => {
|
|
381
|
-
e.preventDefault()
|
|
382
|
-
console.log('Form data:', formData)
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
return (
|
|
386
|
-
<Form onSubmit={handleSubmit}>
|
|
387
|
-
<div className="space-y-4">
|
|
388
|
-
<div>
|
|
389
|
-
<Label htmlFor="category">Category</Label>
|
|
390
|
-
<Select
|
|
391
|
-
value={formData.category}
|
|
392
|
-
onValueChange={(value) =>
|
|
393
|
-
setFormData(prev => ({ ...prev, category: value }))
|
|
394
|
-
}
|
|
395
|
-
>
|
|
396
|
-
<SelectTrigger id="category">
|
|
397
|
-
<SelectValue placeholder="Select category" />
|
|
398
|
-
</SelectTrigger>
|
|
399
|
-
<SelectContent>
|
|
400
|
-
<SelectItem value="bug">Bug</SelectItem>
|
|
401
|
-
<SelectItem value="feature">Feature</SelectItem>
|
|
402
|
-
<SelectItem value="docs">Documentation</SelectItem>
|
|
403
|
-
</SelectContent>
|
|
404
|
-
</Select>
|
|
405
|
-
</div>
|
|
406
|
-
|
|
407
|
-
<div>
|
|
408
|
-
<Label htmlFor="priority">Priority</Label>
|
|
409
|
-
<Select
|
|
410
|
-
value={formData.priority}
|
|
411
|
-
onValueChange={(value) =>
|
|
412
|
-
setFormData(prev => ({ ...prev, priority: value }))
|
|
413
|
-
}
|
|
414
|
-
>
|
|
415
|
-
<SelectTrigger id="priority">
|
|
416
|
-
<SelectValue placeholder="Select priority" />
|
|
417
|
-
</SelectTrigger>
|
|
418
|
-
<SelectContent>
|
|
419
|
-
<SelectItem value="low">Low</SelectItem>
|
|
420
|
-
<SelectItem value="medium">Medium</SelectItem>
|
|
421
|
-
<SelectItem value="high">High</SelectItem>
|
|
422
|
-
<SelectItem value="critical">Critical</SelectItem>
|
|
423
|
-
</SelectContent>
|
|
424
|
-
</Select>
|
|
425
|
-
</div>
|
|
426
|
-
|
|
427
|
-
<Button type="submit">Submit</Button>
|
|
428
|
-
</div>
|
|
429
|
-
</Form>
|
|
430
|
-
)
|
|
431
|
-
}
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
### Dynamic Options
|
|
435
|
-
|
|
436
|
-
```typescript
|
|
437
|
-
function DynamicSelect() {
|
|
438
|
-
const [options, setOptions] = useState<string[]>([])
|
|
439
|
-
const [loading, setLoading] = useState(true)
|
|
440
|
-
|
|
441
|
-
useEffect(() => {
|
|
442
|
-
// Simulate API call
|
|
443
|
-
setTimeout(() => {
|
|
444
|
-
setOptions(['Option 1', 'Option 2', 'Option 3'])
|
|
445
|
-
setLoading(false)
|
|
446
|
-
}, 1000)
|
|
447
|
-
}, [])
|
|
448
|
-
|
|
449
|
-
return (
|
|
450
|
-
<Select disabled={loading}>
|
|
451
|
-
<SelectTrigger>
|
|
452
|
-
<SelectValue placeholder={loading ? "Loading..." : "Select option"} />
|
|
453
|
-
</SelectTrigger>
|
|
454
|
-
<SelectContent>
|
|
455
|
-
{options.map(option => (
|
|
456
|
-
<SelectItem key={option} value={option}>
|
|
457
|
-
{option}
|
|
458
|
-
</SelectItem>
|
|
459
|
-
))}
|
|
460
|
-
</SelectContent>
|
|
461
|
-
</Select>
|
|
462
|
-
)
|
|
463
|
-
}
|
|
464
|
-
```
|
|
465
|
-
|
|
466
|
-
## Testing
|
|
467
|
-
|
|
468
|
-
### Unit Test Example
|
|
469
|
-
|
|
470
|
-
```typescript
|
|
471
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
472
|
-
import { Select, SelectTrigger, SelectContent, SelectItem, SelectValue } from '@/components/Select'
|
|
473
|
-
|
|
474
|
-
describe('Select', () => {
|
|
475
|
-
it('opens dropdown on trigger click', () => {
|
|
476
|
-
render(
|
|
477
|
-
<Select>
|
|
478
|
-
<SelectTrigger>
|
|
479
|
-
<SelectValue placeholder="Select" />
|
|
480
|
-
</SelectTrigger>
|
|
481
|
-
<SelectContent>
|
|
482
|
-
<SelectItem value="1">Item 1</SelectItem>
|
|
483
|
-
</SelectContent>
|
|
484
|
-
</Select>
|
|
485
|
-
)
|
|
486
|
-
|
|
487
|
-
const trigger = screen.getByRole('combobox')
|
|
488
|
-
fireEvent.click(trigger)
|
|
489
|
-
|
|
490
|
-
expect(screen.getByText('Item 1')).toBeInTheDocument()
|
|
491
|
-
})
|
|
492
|
-
|
|
493
|
-
it('selects item on click', () => {
|
|
494
|
-
const handleChange = jest.fn()
|
|
495
|
-
|
|
496
|
-
render(
|
|
497
|
-
<Select onValueChange={handleChange}>
|
|
498
|
-
<SelectTrigger>
|
|
499
|
-
<SelectValue placeholder="Select" />
|
|
500
|
-
</SelectTrigger>
|
|
501
|
-
<SelectContent>
|
|
502
|
-
<SelectItem value="test">Test Item</SelectItem>
|
|
503
|
-
</SelectContent>
|
|
504
|
-
</Select>
|
|
505
|
-
)
|
|
506
|
-
|
|
507
|
-
const trigger = screen.getByRole('combobox')
|
|
508
|
-
fireEvent.click(trigger)
|
|
509
|
-
|
|
510
|
-
const item = screen.getByText('Test Item')
|
|
511
|
-
fireEvent.click(item)
|
|
512
|
-
|
|
513
|
-
expect(handleChange).toHaveBeenCalledWith('test')
|
|
514
|
-
})
|
|
515
|
-
})
|
|
516
|
-
```
|
|
517
|
-
|
|
518
|
-
### Accessibility Test
|
|
519
|
-
|
|
520
|
-
```typescript
|
|
521
|
-
import { axe } from '@axe-core/react'
|
|
522
|
-
|
|
523
|
-
test('Select meets WCAG standards', async () => {
|
|
524
|
-
const { container } = render(
|
|
525
|
-
<div>
|
|
526
|
-
<label htmlFor="test-select">Choose option</label>
|
|
527
|
-
<Select>
|
|
528
|
-
<SelectTrigger id="test-select">
|
|
529
|
-
<SelectValue />
|
|
530
|
-
</SelectTrigger>
|
|
531
|
-
<SelectContent>
|
|
532
|
-
<SelectItem value="1">Option 1</SelectItem>
|
|
533
|
-
</SelectContent>
|
|
534
|
-
</Select>
|
|
535
|
-
</div>
|
|
536
|
-
)
|
|
537
|
-
|
|
538
|
-
const results = await axe(container)
|
|
539
|
-
expect(results).toHaveNoViolations()
|
|
540
|
-
})
|
|
541
|
-
```
|
|
542
|
-
|
|
543
|
-
## Known Limitations & Frontend Patterns
|
|
544
|
-
|
|
545
|
-
### `Select` does not stretch to fill its container by default
|
|
546
|
-
|
|
547
|
-
The shipped `SelectTrigger` base styles do not include `w-full`, so when placed inside a CSS grid or flex column the trigger collapses to the width of its placeholder/selected text. This breaks row alignment in forms whenever `Select` is mixed with `InputField` or other full-width controls.
|
|
548
|
-
|
|
549
|
-
**Always pass `className="w-full h-10"` on form-context `Select` usages**:
|
|
550
|
-
|
|
551
|
-
```tsx
|
|
552
|
-
<Select
|
|
553
|
-
className="w-full h-10"
|
|
554
|
-
value={type}
|
|
555
|
-
onValueChange={setType}
|
|
556
|
-
options={typeOptions}
|
|
557
|
-
placeholder="Select type"
|
|
558
|
-
/>
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
For inline / compact / table-cell usages where you genuinely want the trigger to be content-sized, omit `w-full` (or pass `w-auto`).
|
|
562
|
-
|
|
563
|
-
### Numeric/financial selects
|
|
564
|
-
|
|
565
|
-
When `Select` is the source of a number (account code, fiscal period), keep the displayed `label` formatted (e.g. `"JV-001 — Journal Voucher"`) but the `value` as the raw key (`"JV"`). Do **not** put numeric formatting in the `value` itself.
|
|
566
|
-
|
|
567
|
-
## Accessibility
|
|
568
|
-
|
|
569
|
-
### Keyboard Support
|
|
570
|
-
|
|
571
|
-
- **Space/Enter**: Open select menu when trigger focused
|
|
572
|
-
- **Arrow Down**: Open menu or move to next item
|
|
573
|
-
- **Arrow Up**: Move to previous item
|
|
574
|
-
- **Home**: Move to first item
|
|
575
|
-
- **End**: Move to last item
|
|
576
|
-
- **Escape**: Close menu
|
|
577
|
-
- **Tab**: Move focus away
|
|
578
|
-
|
|
579
|
-
### ARIA Attributes
|
|
580
|
-
|
|
581
|
-
The Select component automatically includes:
|
|
582
|
-
|
|
583
|
-
```typescript
|
|
584
|
-
// Trigger
|
|
585
|
-
<button
|
|
586
|
-
role="combobox"
|
|
587
|
-
aria-expanded={open}
|
|
588
|
-
aria-haspopup="listbox"
|
|
589
|
-
aria-controls="select-content"
|
|
590
|
-
/>
|
|
591
|
-
|
|
592
|
-
// Content
|
|
593
|
-
<div
|
|
594
|
-
role="listbox"
|
|
595
|
-
id="select-content"
|
|
596
|
-
/>
|
|
597
|
-
|
|
598
|
-
// Items
|
|
599
|
-
<div
|
|
600
|
-
role="option"
|
|
601
|
-
aria-selected={selected}
|
|
602
|
-
aria-disabled={disabled}
|
|
603
|
-
/>
|
|
604
|
-
```
|
|
605
|
-
|
|
606
|
-
### Screen Reader Support
|
|
607
|
-
|
|
608
|
-
- Announces selected value
|
|
609
|
-
- Reads item labels when navigating
|
|
610
|
-
- Announces number of options
|
|
611
|
-
- Indicates disabled items
|
|
612
|
-
|
|
613
|
-
## Styling
|
|
614
|
-
|
|
615
|
-
### Custom Styles
|
|
616
|
-
|
|
617
|
-
```typescript
|
|
618
|
-
<Select>
|
|
619
|
-
<SelectTrigger className="border-2 border-blue-500 focus:ring-blue-500">
|
|
620
|
-
<SelectValue />
|
|
621
|
-
</SelectTrigger>
|
|
622
|
-
<SelectContent className="bg-gray-50">
|
|
623
|
-
<SelectItem className="hover:bg-blue-100" value="1">
|
|
624
|
-
Styled Item
|
|
625
|
-
</SelectItem>
|
|
626
|
-
</SelectContent>
|
|
627
|
-
</Select>
|
|
628
|
-
```
|
|
629
|
-
|
|
630
|
-
### Theme Customization
|
|
631
|
-
|
|
632
|
-
```typescript
|
|
633
|
-
<Select>
|
|
634
|
-
<SelectTrigger theme="dark">
|
|
635
|
-
<SelectValue placeholder="Dark theme" />
|
|
636
|
-
</SelectTrigger>
|
|
637
|
-
<SelectContent theme="dark">
|
|
638
|
-
<SelectItem value="1">Dark Item</SelectItem>
|
|
639
|
-
</SelectContent>
|
|
640
|
-
</Select>
|
|
641
|
-
```
|
|
642
|
-
|
|
643
|
-
## Performance
|
|
644
|
-
|
|
645
|
-
| Metric | Value |
|
|
646
|
-
|--------|-------|
|
|
647
|
-
| Bundle size (gzip) | 4.5kb |
|
|
648
|
-
| First render | <12ms |
|
|
649
|
-
| Re-render | <5ms |
|
|
650
|
-
| Tree-shakeable | ✅ |
|
|
651
|
-
|
|
652
|
-
### Optimization Tips
|
|
653
|
-
|
|
654
|
-
1. Use `React.memo()` for parent components with many selects
|
|
655
|
-
2. Lazy load large option lists
|
|
656
|
-
3. Virtualize very long lists (100+ items)
|
|
657
|
-
4. Debounce search/filter operations
|
|
658
|
-
|
|
659
|
-
## Migration
|
|
660
|
-
|
|
661
|
-
### From v1.0.x
|
|
662
|
-
|
|
663
|
-
```diff
|
|
664
|
-
// Component structure changed
|
|
665
|
-
- <Select options={options} value={value} onChange={onChange} />
|
|
666
|
-
+ <Select value={value} onValueChange={onChange}>
|
|
667
|
-
+ <SelectTrigger>
|
|
668
|
-
+ <SelectValue />
|
|
669
|
-
+ </SelectTrigger>
|
|
670
|
-
+ <SelectContent>
|
|
671
|
-
+ {options.map(opt => (
|
|
672
|
-
+ <SelectItem key={opt.value} value={opt.value}>
|
|
673
|
-
+ {opt.label}
|
|
674
|
-
+ </SelectItem>
|
|
675
|
-
+ ))}
|
|
676
|
-
+ </SelectContent>
|
|
677
|
-
+ </Select>
|
|
678
|
-
```
|
|
679
|
-
|
|
680
|
-
## Related Components
|
|
681
|
-
|
|
682
|
-
- [SimpleSelect](/docs/components/simple-select.md) - Lightweight select
|
|
683
|
-
- [Input](/docs/components/input.md) - Text input
|
|
684
|
-
- [RadioGroup](/docs/components/radio.md) - Single selection alternative
|
|
685
|
-
- [Checkbox](/docs/components/checkbox.md) - Multiple selection
|
|
686
|
-
- [Form](/docs/components/form.md) - Form wrapper
|
|
687
|
-
|
|
688
|
-
## Browser Support
|
|
689
|
-
|
|
690
|
-
- Chrome 90+ ✅
|
|
691
|
-
- Firefox 88+ ✅
|
|
692
|
-
- Safari 14+ ✅
|
|
693
|
-
- Edge 90+ ✅
|
|
694
|
-
- Mobile browsers ✅
|
|
695
|
-
|
|
696
|
-
## Changelog
|
|
697
|
-
|
|
698
|
-
### v1.1.15
|
|
699
|
-
- Added Radix UI integration
|
|
700
|
-
- Improved accessibility
|
|
701
|
-
- Added size variants
|
|
702
|
-
|
|
703
|
-
### v1.1.14
|
|
704
|
-
- Added error state with tooltip
|
|
705
|
-
- Performance optimizations
|
|
706
|
-
- Fixed keyboard navigation
|
|
707
|
-
|
|
708
|
-
### v1.1.0
|
|
709
|
-
- Initial release
|