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
package/docs/components/label.md
DELETED
|
@@ -1,761 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Label
|
|
3
|
-
description: Flexible label component with support for primary, secondary, and required text with customizable layout directions
|
|
4
|
-
group: Labels & Text
|
|
5
|
-
keywords: [label, form, input, required, text, typography]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Label
|
|
9
|
-
|
|
10
|
-
> A flexible label component that supports primary, secondary, and required label text with customizable layout directions. Can be used standalone or wrapped around form inputs with polymorphic rendering support.
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx torch-glare@latest init
|
|
19
|
-
npx torch-glare@latest add Label
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
`add` also copies any components, hooks, and utilities that `Label` depends on.
|
|
23
|
-
|
|
24
|
-
## Import
|
|
25
|
-
|
|
26
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
-
|
|
28
|
-
```tsx
|
|
29
|
-
import { Label } from "@/components/Label";
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Quick Examples
|
|
33
|
-
|
|
34
|
-
### Basic Usage
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { Label } from "@/components/Label";
|
|
38
|
-
import { InputField } from "@/components/InputField";
|
|
39
|
-
|
|
40
|
-
function Example() {
|
|
41
|
-
return (
|
|
42
|
-
<Label label="Email Address">
|
|
43
|
-
<InputField type="email" />
|
|
44
|
-
</Label>
|
|
45
|
-
)
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
### With Required Indicator
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
import { Label } from "@/components/Label";
|
|
53
|
-
import { InputField } from "@/components/InputField";
|
|
54
|
-
|
|
55
|
-
function RequiredField() {
|
|
56
|
-
return (
|
|
57
|
-
<Label
|
|
58
|
-
label="Full Name"
|
|
59
|
-
requiredLabel="*Required"
|
|
60
|
-
>
|
|
61
|
-
<InputField required />
|
|
62
|
-
</Label>
|
|
63
|
-
)
|
|
64
|
-
}
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
### With Secondary Label
|
|
68
|
-
|
|
69
|
-
```typescript
|
|
70
|
-
import { Label } from "@/components/Label";
|
|
71
|
-
import { InputField } from "@/components/InputField";
|
|
72
|
-
|
|
73
|
-
function WithSecondary() {
|
|
74
|
-
return (
|
|
75
|
-
<Label
|
|
76
|
-
label="Password"
|
|
77
|
-
secondaryLabel="(At least 8 characters)"
|
|
78
|
-
>
|
|
79
|
-
<InputField type="password" />
|
|
80
|
-
</Label>
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
### All Labels Combined
|
|
86
|
-
|
|
87
|
-
```typescript
|
|
88
|
-
import { Label } from "@/components/Label";
|
|
89
|
-
import { InputField } from "@/components/InputField";
|
|
90
|
-
|
|
91
|
-
function AllLabels() {
|
|
92
|
-
return (
|
|
93
|
-
<Label
|
|
94
|
-
label="Company Name"
|
|
95
|
-
secondaryLabel="(Optional)"
|
|
96
|
-
requiredLabel="*"
|
|
97
|
-
>
|
|
98
|
-
<InputField />
|
|
99
|
-
</Label>
|
|
100
|
-
)
|
|
101
|
-
}
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
### Horizontal Layout
|
|
105
|
-
|
|
106
|
-
```typescript
|
|
107
|
-
import { Label } from "@/components/Label";
|
|
108
|
-
import { Switch } from "@/components/Switch";
|
|
109
|
-
|
|
110
|
-
function HorizontalLabel() {
|
|
111
|
-
return (
|
|
112
|
-
<Label
|
|
113
|
-
label="Enable Notifications"
|
|
114
|
-
childrenDirections="horizontal"
|
|
115
|
-
>
|
|
116
|
-
<Switch />
|
|
117
|
-
</Label>
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
### Vertical Label Direction
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
import { Label } from "@/components/Label";
|
|
126
|
-
import { InputField } from "@/components/InputField";
|
|
127
|
-
|
|
128
|
-
function VerticalLabels() {
|
|
129
|
-
return (
|
|
130
|
-
<Label
|
|
131
|
-
label="Description"
|
|
132
|
-
secondaryLabel="Max 500 characters"
|
|
133
|
-
labelDirections="vertical"
|
|
134
|
-
>
|
|
135
|
-
<textarea className="w-full border rounded p-2" />
|
|
136
|
-
</Label>
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Reversed Children
|
|
142
|
-
|
|
143
|
-
```typescript
|
|
144
|
-
import { Label } from "@/components/Label";
|
|
145
|
-
import { Checkbox } from "@/components/Checkbox";
|
|
146
|
-
|
|
147
|
-
function ReversedLayout() {
|
|
148
|
-
return (
|
|
149
|
-
<Label
|
|
150
|
-
label="I agree to the terms"
|
|
151
|
-
childrenDirections="horizontal"
|
|
152
|
-
reverseChildren
|
|
153
|
-
>
|
|
154
|
-
<Checkbox />
|
|
155
|
-
</Label>
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Different Sizes
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
import { Label } from "@/components/Label";
|
|
164
|
-
import { InputField } from "@/components/InputField";
|
|
165
|
-
|
|
166
|
-
function Sizes() {
|
|
167
|
-
return (
|
|
168
|
-
<div className="space-y-4">
|
|
169
|
-
<Label label="Small Label" size="S">
|
|
170
|
-
<InputField size="S" />
|
|
171
|
-
</Label>
|
|
172
|
-
|
|
173
|
-
<Label label="Medium Label" size="M">
|
|
174
|
-
<InputField size="M" />
|
|
175
|
-
</Label>
|
|
176
|
-
|
|
177
|
-
<Label label="Large Label" size="L">
|
|
178
|
-
<InputField size="M" />
|
|
179
|
-
</Label>
|
|
180
|
-
</div>
|
|
181
|
-
)
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
### Style Variants
|
|
186
|
-
|
|
187
|
-
```typescript
|
|
188
|
-
import { Label } from "@/components/Label";
|
|
189
|
-
import { InputField } from "@/components/InputField";
|
|
190
|
-
|
|
191
|
-
function Variants() {
|
|
192
|
-
return (
|
|
193
|
-
<div className="space-y-4">
|
|
194
|
-
<Label
|
|
195
|
-
label="Presentation Style"
|
|
196
|
-
variant="PresentationStyle"
|
|
197
|
-
>
|
|
198
|
-
<InputField />
|
|
199
|
-
</Label>
|
|
200
|
-
|
|
201
|
-
<Label
|
|
202
|
-
label="System Style"
|
|
203
|
-
variant="SystemStyle"
|
|
204
|
-
>
|
|
205
|
-
<InputField variant="SystemStyle" />
|
|
206
|
-
</Label>
|
|
207
|
-
</div>
|
|
208
|
-
)
|
|
209
|
-
}
|
|
210
|
-
```
|
|
211
|
-
|
|
212
|
-
### Polymorphic Rendering
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
import { Label } from "@/components/Label";
|
|
216
|
-
|
|
217
|
-
function PolymorphicLabel() {
|
|
218
|
-
return (
|
|
219
|
-
<div className="space-y-4">
|
|
220
|
-
{/* Render as label (default) */}
|
|
221
|
-
<Label label="Name" htmlFor="name-input">
|
|
222
|
-
<input id="name-input" />
|
|
223
|
-
</Label>
|
|
224
|
-
|
|
225
|
-
{/* Render as div */}
|
|
226
|
-
<Label as="div" label="Settings">
|
|
227
|
-
<div className="space-y-2">
|
|
228
|
-
<Switch />
|
|
229
|
-
<Switch />
|
|
230
|
-
</div>
|
|
231
|
-
</Label>
|
|
232
|
-
|
|
233
|
-
{/* Render as span */}
|
|
234
|
-
<Label as="span" label="Inline Label">
|
|
235
|
-
<input type="checkbox" />
|
|
236
|
-
</Label>
|
|
237
|
-
</div>
|
|
238
|
-
)
|
|
239
|
-
}
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Form Example
|
|
243
|
-
|
|
244
|
-
```typescript
|
|
245
|
-
import { Label } from "@/components/Label";
|
|
246
|
-
import { Button } from "@/components/Button";
|
|
247
|
-
import { InputField } from "@/components/InputField";
|
|
248
|
-
import { useState } from 'react'
|
|
249
|
-
|
|
250
|
-
function RegistrationForm() {
|
|
251
|
-
const [formData, setFormData] = useState({
|
|
252
|
-
name: '',
|
|
253
|
-
email: '',
|
|
254
|
-
password: '',
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
return (
|
|
258
|
-
<form className="space-y-4">
|
|
259
|
-
<Label
|
|
260
|
-
label="Full Name"
|
|
261
|
-
requiredLabel="*"
|
|
262
|
-
>
|
|
263
|
-
<InputField
|
|
264
|
-
value={formData.name}
|
|
265
|
-
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
266
|
-
required
|
|
267
|
-
/>
|
|
268
|
-
</Label>
|
|
269
|
-
|
|
270
|
-
<Label
|
|
271
|
-
label="Email"
|
|
272
|
-
secondaryLabel="(We'll never share your email)"
|
|
273
|
-
requiredLabel="*"
|
|
274
|
-
>
|
|
275
|
-
<InputField
|
|
276
|
-
type="email"
|
|
277
|
-
value={formData.email}
|
|
278
|
-
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
279
|
-
required
|
|
280
|
-
/>
|
|
281
|
-
</Label>
|
|
282
|
-
|
|
283
|
-
<Label
|
|
284
|
-
label="Password"
|
|
285
|
-
secondaryLabel="(At least 8 characters)"
|
|
286
|
-
requiredLabel="*"
|
|
287
|
-
labelDirections="vertical"
|
|
288
|
-
>
|
|
289
|
-
<InputField
|
|
290
|
-
type="password"
|
|
291
|
-
value={formData.password}
|
|
292
|
-
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
|
293
|
-
required
|
|
294
|
-
/>
|
|
295
|
-
</Label>
|
|
296
|
-
|
|
297
|
-
<Button type="submit">Create Account</Button>
|
|
298
|
-
</form>
|
|
299
|
-
)
|
|
300
|
-
}
|
|
301
|
-
```
|
|
302
|
-
|
|
303
|
-
## API Reference
|
|
304
|
-
|
|
305
|
-
### Label Props
|
|
306
|
-
|
|
307
|
-
Extends all standard HTML label attributes.
|
|
308
|
-
|
|
309
|
-
| Prop | Type | Default | Description |
|
|
310
|
-
|------|------|---------|-------------|
|
|
311
|
-
| `label` | `ReactNode` | - | Primary label text |
|
|
312
|
-
| `requiredLabel` | `ReactNode` | - | Required indicator (typically "*Required") |
|
|
313
|
-
| `secondaryLabel` | `ReactNode` | - | Secondary/helper text |
|
|
314
|
-
| `size` | `'S' \| 'M' \| 'L'` | `'M'` | Label text size |
|
|
315
|
-
| `variant` | `'SystemStyle' \| 'PresentationStyle'` | `'PresentationStyle'` | Style variant |
|
|
316
|
-
| `theme` | `'light' \| 'dark' \| 'default'` | - | Theme variant |
|
|
317
|
-
| `labelDirections` | `'vertical' \| 'horizontal'` | `'horizontal'` | Direction of label texts |
|
|
318
|
-
| `childrenDirections` | `'vertical' \| 'horizontal'` | `'vertical'` | Direction of label and children |
|
|
319
|
-
| `reverseChildren` | `boolean` | `false` | Reverse order of label and children |
|
|
320
|
-
| `as` | `React.ElementType` | `'label'` | Element type to render as |
|
|
321
|
-
| `className` | `string` | - | Additional CSS classes for container |
|
|
322
|
-
| `labelsClassName` | `string` | - | Additional CSS classes for labels |
|
|
323
|
-
| ...HTMLLabelElement | - | - | All label attributes |
|
|
324
|
-
|
|
325
|
-
### Size Typography
|
|
326
|
-
|
|
327
|
-
| Size | Main Label | Secondary Label | Required Label |
|
|
328
|
-
|------|------------|-----------------|----------------|
|
|
329
|
-
| `S` | body-small-regular | labels-small-regular | labels-small-medium |
|
|
330
|
-
| `M` | body-medium-regular | labels-medium-regular | labels-medium-medium |
|
|
331
|
-
| `L` | body-large-regular | body-small-regular | body-small-medium |
|
|
332
|
-
|
|
333
|
-
### Style Variants
|
|
334
|
-
|
|
335
|
-
| Variant | Text Color |
|
|
336
|
-
|---------|------------|
|
|
337
|
-
| `PresentationStyle` | content-presentation-global-primary |
|
|
338
|
-
| `SystemStyle` | #E5E5E5 (light gray) |
|
|
339
|
-
|
|
340
|
-
## TypeScript
|
|
341
|
-
|
|
342
|
-
### Full Type Definitions
|
|
343
|
-
|
|
344
|
-
```typescript
|
|
345
|
-
import { LabelHTMLAttributes, ReactNode } from 'react'
|
|
346
|
-
import { VariantProps } from 'class-variance-authority'
|
|
347
|
-
|
|
348
|
-
interface LabelProps
|
|
349
|
-
extends LabelHTMLAttributes<HTMLLabelElement>,
|
|
350
|
-
VariantProps<typeof labelComponentVariants> {
|
|
351
|
-
label?: ReactNode
|
|
352
|
-
requiredLabel?: ReactNode
|
|
353
|
-
secondaryLabel?: ReactNode
|
|
354
|
-
as?: React.ElementType
|
|
355
|
-
size?: 'S' | 'M' | 'L'
|
|
356
|
-
variant?: 'SystemStyle' | 'PresentationStyle'
|
|
357
|
-
theme?: 'light' | 'dark' | 'default'
|
|
358
|
-
labelsClassName?: string
|
|
359
|
-
labelDirections?: 'vertical' | 'horizontal'
|
|
360
|
-
childrenDirections?: 'vertical' | 'horizontal'
|
|
361
|
-
reverseChildren?: boolean
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
export const Label: React.ForwardRefExoticComponent<
|
|
365
|
-
LabelProps & React.RefAttributes<HTMLLabelElement>
|
|
366
|
-
>
|
|
367
|
-
```
|
|
368
|
-
|
|
369
|
-
### Usage with Types
|
|
370
|
-
|
|
371
|
-
```typescript
|
|
372
|
-
import { Label } from "@/components/Label";
|
|
373
|
-
import { useRef } from 'react'
|
|
374
|
-
|
|
375
|
-
function TypedExample() {
|
|
376
|
-
const labelRef = useRef<HTMLLabelElement>(null)
|
|
377
|
-
|
|
378
|
-
const handleClick = () => {
|
|
379
|
-
labelRef.current?.focus()
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
return (
|
|
383
|
-
<Label
|
|
384
|
-
ref={labelRef}
|
|
385
|
-
label="Typed Label"
|
|
386
|
-
size="M"
|
|
387
|
-
variant="PresentationStyle"
|
|
388
|
-
>
|
|
389
|
-
<input type="text" />
|
|
390
|
-
</Label>
|
|
391
|
-
)
|
|
392
|
-
}
|
|
393
|
-
```
|
|
394
|
-
|
|
395
|
-
## Common Patterns
|
|
396
|
-
|
|
397
|
-
### Responsive Layout
|
|
398
|
-
|
|
399
|
-
```typescript
|
|
400
|
-
import { Label } from "@/components/Label";
|
|
401
|
-
import { InputField } from "@/components/InputField";
|
|
402
|
-
import { useState, useEffect } from 'react'
|
|
403
|
-
|
|
404
|
-
function ResponsiveLabel() {
|
|
405
|
-
const [isMobile, setIsMobile] = useState(false)
|
|
406
|
-
|
|
407
|
-
useEffect(() => {
|
|
408
|
-
const checkMobile = () => setIsMobile(window.innerWidth < 768)
|
|
409
|
-
checkMobile()
|
|
410
|
-
window.addEventListener('resize', checkMobile)
|
|
411
|
-
return () => window.removeEventListener('resize', checkMobile)
|
|
412
|
-
}, [])
|
|
413
|
-
|
|
414
|
-
return (
|
|
415
|
-
<Label
|
|
416
|
-
label="Email"
|
|
417
|
-
secondaryLabel="Required for notifications"
|
|
418
|
-
childrenDirections={isMobile ? 'vertical' : 'horizontal'}
|
|
419
|
-
labelDirections={isMobile ? 'vertical' : 'horizontal'}
|
|
420
|
-
>
|
|
421
|
-
<InputField type="email" />
|
|
422
|
-
</Label>
|
|
423
|
-
)
|
|
424
|
-
}
|
|
425
|
-
```
|
|
426
|
-
|
|
427
|
-
### Dynamic Required State
|
|
428
|
-
|
|
429
|
-
```typescript
|
|
430
|
-
import { Label } from "@/components/Label";
|
|
431
|
-
import { Checkbox } from "@/components/Checkbox";
|
|
432
|
-
import { InputField } from "@/components/InputField";
|
|
433
|
-
import { useState } from 'react'
|
|
434
|
-
|
|
435
|
-
function DynamicRequired() {
|
|
436
|
-
const [makeOptional, setMakeOptional] = useState(false)
|
|
437
|
-
const [value, setValue] = useState('')
|
|
438
|
-
|
|
439
|
-
return (
|
|
440
|
-
<div className="space-y-4">
|
|
441
|
-
<Checkbox
|
|
442
|
-
checked={makeOptional}
|
|
443
|
-
onChange={setMakeOptional}
|
|
444
|
-
label="Make field optional"
|
|
445
|
-
/>
|
|
446
|
-
|
|
447
|
-
<Label
|
|
448
|
-
label="Company Name"
|
|
449
|
-
requiredLabel={!makeOptional ? '*Required' : undefined}
|
|
450
|
-
secondaryLabel={makeOptional ? '(Optional)' : undefined}
|
|
451
|
-
>
|
|
452
|
-
<InputField
|
|
453
|
-
value={value}
|
|
454
|
-
onChange={(e) => setValue(e.target.value)}
|
|
455
|
-
required={!makeOptional}
|
|
456
|
-
/>
|
|
457
|
-
</Label>
|
|
458
|
-
</div>
|
|
459
|
-
)
|
|
460
|
-
}
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
### Label Group Component
|
|
464
|
-
|
|
465
|
-
```typescript
|
|
466
|
-
import { Label } from "@/components/Label";
|
|
467
|
-
import { ReactNode } from 'react'
|
|
468
|
-
|
|
469
|
-
interface LabelGroupProps {
|
|
470
|
-
items: Array<{
|
|
471
|
-
label: string
|
|
472
|
-
secondaryLabel?: string
|
|
473
|
-
requiredLabel?: string
|
|
474
|
-
children: ReactNode
|
|
475
|
-
}>
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
function LabelGroup({ items }: LabelGroupProps) {
|
|
479
|
-
return (
|
|
480
|
-
<div className="space-y-4">
|
|
481
|
-
{items.map((item, index) => (
|
|
482
|
-
<Label
|
|
483
|
-
key={index}
|
|
484
|
-
label={item.label}
|
|
485
|
-
secondaryLabel={item.secondaryLabel}
|
|
486
|
-
requiredLabel={item.requiredLabel}
|
|
487
|
-
>
|
|
488
|
-
{item.children}
|
|
489
|
-
</Label>
|
|
490
|
-
))}
|
|
491
|
-
</div>
|
|
492
|
-
)
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
// Usage
|
|
496
|
-
function FormWithGroup() {
|
|
497
|
-
return (
|
|
498
|
-
<LabelGroup
|
|
499
|
-
items={[
|
|
500
|
-
{
|
|
501
|
-
label: 'Name',
|
|
502
|
-
requiredLabel: '*',
|
|
503
|
-
children: <InputField />,
|
|
504
|
-
},
|
|
505
|
-
{
|
|
506
|
-
label: 'Email',
|
|
507
|
-
secondaryLabel: '(Optional)',
|
|
508
|
-
children: <InputField type="email" />,
|
|
509
|
-
},
|
|
510
|
-
]}
|
|
511
|
-
/>
|
|
512
|
-
)
|
|
513
|
-
}
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
## Testing
|
|
517
|
-
|
|
518
|
-
### Unit Test Examples
|
|
519
|
-
|
|
520
|
-
```typescript
|
|
521
|
-
import { render, screen } from '@testing-library/react'
|
|
522
|
-
import { Label } from "@/components/Label";
|
|
523
|
-
|
|
524
|
-
describe('Label', () => {
|
|
525
|
-
it('renders label text', () => {
|
|
526
|
-
render(<Label label="Test Label" />)
|
|
527
|
-
|
|
528
|
-
expect(screen.getByText('Test Label')).toBeInTheDocument()
|
|
529
|
-
})
|
|
530
|
-
|
|
531
|
-
it('renders all label types', () => {
|
|
532
|
-
render(
|
|
533
|
-
<Label
|
|
534
|
-
label="Main"
|
|
535
|
-
secondaryLabel="Secondary"
|
|
536
|
-
requiredLabel="*Required"
|
|
537
|
-
/>
|
|
538
|
-
)
|
|
539
|
-
|
|
540
|
-
expect(screen.getByText('Main')).toBeInTheDocument()
|
|
541
|
-
expect(screen.getByText('Secondary')).toBeInTheDocument()
|
|
542
|
-
expect(screen.getByText('*Required')).toBeInTheDocument()
|
|
543
|
-
})
|
|
544
|
-
|
|
545
|
-
it('renders children', () => {
|
|
546
|
-
render(
|
|
547
|
-
<Label label="Label">
|
|
548
|
-
<input data-testid="input" />
|
|
549
|
-
</Label>
|
|
550
|
-
)
|
|
551
|
-
|
|
552
|
-
expect(screen.getByTestId('input')).toBeInTheDocument()
|
|
553
|
-
})
|
|
554
|
-
|
|
555
|
-
it('applies size classes correctly', () => {
|
|
556
|
-
const { container, rerender } = render(
|
|
557
|
-
<Label label="Small" size="S" />
|
|
558
|
-
)
|
|
559
|
-
|
|
560
|
-
expect(container.querySelector('.typography-body-small-regular')).toBeInTheDocument()
|
|
561
|
-
|
|
562
|
-
rerender(<Label label="Medium" size="M" />)
|
|
563
|
-
expect(container.querySelector('.typography-body-medium-regular')).toBeInTheDocument()
|
|
564
|
-
|
|
565
|
-
rerender(<Label label="Large" size="L" />)
|
|
566
|
-
expect(container.querySelector('.typography-body-large-regular')).toBeInTheDocument()
|
|
567
|
-
})
|
|
568
|
-
|
|
569
|
-
it('renders as different elements', () => {
|
|
570
|
-
const { container } = render(
|
|
571
|
-
<Label as="div" label="Div Label" />
|
|
572
|
-
)
|
|
573
|
-
|
|
574
|
-
expect(container.querySelector('div')).toBeInTheDocument()
|
|
575
|
-
expect(container.querySelector('label')).not.toBeInTheDocument()
|
|
576
|
-
})
|
|
577
|
-
|
|
578
|
-
it('applies custom className', () => {
|
|
579
|
-
const { container } = render(
|
|
580
|
-
<Label label="Test" className="custom-class" />
|
|
581
|
-
)
|
|
582
|
-
|
|
583
|
-
expect(container.querySelector('.custom-class')).toBeInTheDocument()
|
|
584
|
-
})
|
|
585
|
-
|
|
586
|
-
it('renders with vertical label direction', () => {
|
|
587
|
-
const { container } = render(
|
|
588
|
-
<Label
|
|
589
|
-
label="Main"
|
|
590
|
-
secondaryLabel="Secondary"
|
|
591
|
-
labelDirections="vertical"
|
|
592
|
-
/>
|
|
593
|
-
)
|
|
594
|
-
|
|
595
|
-
expect(container.querySelector('.flex-col')).toBeInTheDocument()
|
|
596
|
-
})
|
|
597
|
-
|
|
598
|
-
it('reverses children order', () => {
|
|
599
|
-
const { container } = render(
|
|
600
|
-
<Label
|
|
601
|
-
label="Label"
|
|
602
|
-
reverseChildren
|
|
603
|
-
childrenDirections="horizontal"
|
|
604
|
-
>
|
|
605
|
-
<span>Child</span>
|
|
606
|
-
</Label>
|
|
607
|
-
)
|
|
608
|
-
|
|
609
|
-
expect(container.querySelector('.flex-row-reverse')).toBeInTheDocument()
|
|
610
|
-
})
|
|
611
|
-
})
|
|
612
|
-
```
|
|
613
|
-
|
|
614
|
-
## Accessibility
|
|
615
|
-
|
|
616
|
-
- **Semantic HTML**: Uses proper `<label>` element by default
|
|
617
|
-
- **For Attribute**: Support for `htmlFor` to link with inputs
|
|
618
|
-
- **Keyboard Navigation**: Fully keyboard accessible
|
|
619
|
-
- **Screen Readers**: Labels announced correctly
|
|
620
|
-
- **Required Indicators**: Clear visual and semantic indication
|
|
621
|
-
- **Color Contrast**: Meets WCAG AA standards
|
|
622
|
-
|
|
623
|
-
### Accessibility Best Practices
|
|
624
|
-
|
|
625
|
-
```typescript
|
|
626
|
-
// Link label to input
|
|
627
|
-
<Label label="Email" htmlFor="email-input">
|
|
628
|
-
<InputField id="email-input" />
|
|
629
|
-
</Label>
|
|
630
|
-
|
|
631
|
-
// Provide context for required fields
|
|
632
|
-
<Label
|
|
633
|
-
label="Password"
|
|
634
|
-
requiredLabel="*"
|
|
635
|
-
aria-required="true"
|
|
636
|
-
>
|
|
637
|
-
<InputField type="password" required />
|
|
638
|
-
</Label>
|
|
639
|
-
|
|
640
|
-
// Use secondary label for hints
|
|
641
|
-
<Label
|
|
642
|
-
label="Phone"
|
|
643
|
-
secondaryLabel="Format: (555) 555-5555"
|
|
644
|
-
aria-describedby="phone-hint"
|
|
645
|
-
>
|
|
646
|
-
<InputField id="phone-input" />
|
|
647
|
-
</Label>
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
## Performance
|
|
651
|
-
|
|
652
|
-
| Metric | Value |
|
|
653
|
-
|--------|-------|
|
|
654
|
-
| Bundle size (minified) | ~3kb |
|
|
655
|
-
| Bundle size (gzipped) | ~1kb |
|
|
656
|
-
| Dependencies | class-variance-authority |
|
|
657
|
-
| Re-renders | Only on prop changes |
|
|
658
|
-
| Tree-shakeable | ✅ |
|
|
659
|
-
|
|
660
|
-
### Performance Tips
|
|
661
|
-
|
|
662
|
-
1. **Memoize complex labels**:
|
|
663
|
-
```typescript
|
|
664
|
-
const label = useMemo(() => `${firstName} ${lastName}`, [firstName, lastName])
|
|
665
|
-
<Label label={label} />
|
|
666
|
-
```
|
|
667
|
-
|
|
668
|
-
2. **Use appropriate size**: Don't over-size labels unnecessarily
|
|
669
|
-
|
|
670
|
-
3. **Avoid inline functions**: Define handlers outside render
|
|
671
|
-
```typescript
|
|
672
|
-
const handleClick = useCallback(() => { ... }, [])
|
|
673
|
-
<Label onClick={handleClick} />
|
|
674
|
-
```
|
|
675
|
-
|
|
676
|
-
## Styling
|
|
677
|
-
|
|
678
|
-
### Custom Styles
|
|
679
|
-
|
|
680
|
-
```typescript
|
|
681
|
-
// Custom label container
|
|
682
|
-
<Label
|
|
683
|
-
label="Styled Label"
|
|
684
|
-
className="bg-gray-100 p-4 rounded"
|
|
685
|
-
>
|
|
686
|
-
<InputField />
|
|
687
|
-
</Label>
|
|
688
|
-
|
|
689
|
-
// Custom label text styling
|
|
690
|
-
<Label
|
|
691
|
-
label="Custom Text"
|
|
692
|
-
labelsClassName="text-blue-600 font-bold"
|
|
693
|
-
>
|
|
694
|
-
<InputField />
|
|
695
|
-
</Label>
|
|
696
|
-
|
|
697
|
-
// Override size
|
|
698
|
-
<Label
|
|
699
|
-
label="Large Label"
|
|
700
|
-
size="L"
|
|
701
|
-
className="[&_p]:text-2xl"
|
|
702
|
-
>
|
|
703
|
-
<InputField />
|
|
704
|
-
</Label>
|
|
705
|
-
```
|
|
706
|
-
|
|
707
|
-
### Default Styling
|
|
708
|
-
|
|
709
|
-
- Container: Flex layout with 8px gap
|
|
710
|
-
- Primary Label: Theme-based color, size-dependent typography
|
|
711
|
-
- Secondary Label: Secondary color, smaller typography
|
|
712
|
-
- Required Label: Negative (red) color, medium weight
|
|
713
|
-
|
|
714
|
-
## Best Practices
|
|
715
|
-
|
|
716
|
-
1. **Always provide label text**: Essential for accessibility
|
|
717
|
-
```typescript
|
|
718
|
-
<Label label="Email">...</Label> // ✅
|
|
719
|
-
<Label>...</Label> // ❌
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
2. **Use consistent size**: Match label size with input size
|
|
723
|
-
```typescript
|
|
724
|
-
<Label label="Name" size="M">
|
|
725
|
-
<InputField size="M" />
|
|
726
|
-
</Label>
|
|
727
|
-
```
|
|
728
|
-
|
|
729
|
-
3. **Mark required fields clearly**: Use requiredLabel prop
|
|
730
|
-
```typescript
|
|
731
|
-
<Label label="Password" requiredLabel="*Required">
|
|
732
|
-
<InputField required />
|
|
733
|
-
</Label>
|
|
734
|
-
```
|
|
735
|
-
|
|
736
|
-
4. **Provide helpful hints**: Use secondaryLabel for context
|
|
737
|
-
```typescript
|
|
738
|
-
<Label label="Phone" secondaryLabel="(Include area code)">
|
|
739
|
-
<InputField type="tel" />
|
|
740
|
-
</Label>
|
|
741
|
-
```
|
|
742
|
-
|
|
743
|
-
5. **Use appropriate layout**: Choose direction based on context
|
|
744
|
-
- Vertical for forms
|
|
745
|
-
- Horizontal for toggles and checkboxes
|
|
746
|
-
|
|
747
|
-
6. **Link labels to inputs**: Use htmlFor when possible
|
|
748
|
-
```typescript
|
|
749
|
-
<Label label="Name" htmlFor="name-input">
|
|
750
|
-
<input id="name-input" />
|
|
751
|
-
</Label>
|
|
752
|
-
```
|
|
753
|
-
|
|
754
|
-
7. **Test keyboard navigation**: Ensure label clicking focuses input
|
|
755
|
-
|
|
756
|
-
## Related Components
|
|
757
|
-
|
|
758
|
-
- [LabelField](./label-field.md) - Combined Label + InputField
|
|
759
|
-
- [InnerLabelField](./inner-label-field.md) - Floating label inside input
|
|
760
|
-
- [InputField](./input-field.md) - Input field component
|
|
761
|
-
- [FieldHint](./field-hint.md) - Inline field hints and validation
|