torch-glare 2.4.0 → 2.4.2
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 +8 -0
- package/apps/lib/components/ActionButton.tsx +7 -12
- package/apps/lib/components/ActionsGroup.tsx +4 -15
- package/apps/lib/components/AlertDialog.tsx +173 -191
- package/apps/lib/components/Avatar.tsx +13 -16
- package/apps/lib/components/Badge.tsx +1 -3
- package/apps/lib/components/BadgeField.tsx +76 -71
- package/apps/lib/components/Breadcrumb.tsx +49 -85
- package/apps/lib/components/Button.tsx +21 -20
- package/apps/lib/components/ButtonGroup.tsx +31 -41
- package/apps/lib/components/Calendar.tsx +51 -29
- package/apps/lib/components/Card.tsx +40 -24
- package/apps/lib/components/Checkbox.tsx +9 -16
- package/apps/lib/components/ColorPicker.tsx +441 -0
- package/apps/lib/components/ConclusionHeader.tsx +148 -0
- package/apps/lib/components/ContextMenu.tsx +97 -96
- package/apps/lib/components/CountBadge.tsx +4 -6
- package/apps/lib/components/DataTable.tsx +196 -216
- package/apps/lib/components/DataViews/DataViewRadio.tsx +1 -6
- package/apps/lib/components/DataViews/DataViewsConfigPanel.tsx +13 -47
- package/apps/lib/components/DataViews/DataViewsHeader.tsx +1 -3
- package/apps/lib/components/DataViews/DataViewsLayout.tsx +5 -12
- package/apps/lib/components/DataViews/FilterPanel.tsx +155 -149
- package/apps/lib/components/DataViews/HeaderSearch.tsx +1 -5
- package/apps/lib/components/DataViews/InboxView.tsx +22 -68
- package/apps/lib/components/DataViews/InboxViewCard.tsx +68 -77
- package/apps/lib/components/DataViews/KanbanView.tsx +8 -25
- package/apps/lib/components/DataViews/PanelControls.tsx +3 -13
- package/apps/lib/components/DataViews/SettingsPanel.tsx +83 -89
- package/apps/lib/components/DataViews/TableView.tsx +8 -28
- package/apps/lib/components/DataViews/TreeView.tsx +12 -40
- package/apps/lib/components/DataViews/badgeAdapter.ts +32 -28
- package/apps/lib/components/DataViews/fieldRenderers.tsx +106 -141
- package/apps/lib/components/DataViews/filters/DatePickerRangeFilter.tsx +30 -23
- package/apps/lib/components/DataViews/filters/DateRangePopover.tsx +39 -32
- package/apps/lib/components/DataViews/filters/PresetChips.tsx +15 -15
- package/apps/lib/components/DataViews/filters/RangeSliderWithInputs.tsx +69 -58
- package/apps/lib/components/DataViews/index.ts +26 -26
- package/apps/lib/components/DataViews/tree/TreeDrawer.tsx +12 -16
- package/apps/lib/components/DataViews/tree/TreeSidebar.tsx +28 -31
- package/apps/lib/components/DataViews/types.ts +104 -115
- package/apps/lib/components/DatePicker.tsx +200 -196
- package/apps/lib/components/Dialog.tsx +92 -105
- package/apps/lib/components/Divider.tsx +21 -24
- package/apps/lib/components/Drawer.tsx +124 -142
- package/apps/lib/components/DropdownMenu.tsx +131 -171
- package/apps/lib/components/FieldHint.tsx +4 -11
- package/apps/lib/components/Form.tsx +146 -155
- package/apps/lib/components/FormBuilder/DisplayField.tsx +40 -0
- package/apps/lib/components/FormBuilder/context.ts +71 -0
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +65 -0
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +76 -0
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +16 -0
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +34 -0
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +79 -0
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +174 -0
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +40 -0
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +139 -0
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +32 -0
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +82 -0
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +37 -0
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +101 -0
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +175 -0
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +72 -0
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +42 -0
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +312 -0
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +222 -0
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +49 -0
- package/apps/lib/components/FormBuilder/fields/countries.ts +303 -0
- package/apps/lib/components/FormBuilder/fields/index.ts +25 -0
- package/apps/lib/components/FormBuilder/form-builder.tsx +292 -0
- package/apps/lib/components/FormBuilder/header.tsx +105 -0
- package/apps/lib/components/FormBuilder/index.ts +37 -0
- package/apps/lib/components/FormBuilder/numberFormat.ts +16 -0
- package/apps/lib/components/FormBuilder/stepper.tsx +217 -0
- package/apps/lib/components/FormBuilder/submit.tsx +41 -0
- package/apps/lib/components/FormBuilder/types.ts +264 -0
- package/apps/lib/components/FormBuilder/viewFormat.tsx +137 -0
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +121 -0
- package/apps/lib/components/FormRenderer/form-renderer.tsx +113 -0
- package/apps/lib/components/FormRenderer/index.ts +9 -0
- package/apps/lib/components/FormRenderer/types.ts +79 -0
- package/apps/lib/components/FormStepper.tsx +9 -39
- package/apps/lib/components/FormSummary.tsx +282 -0
- package/apps/lib/components/HeaderBar.tsx +1 -9
- package/apps/lib/components/ImageAttachment.tsx +106 -93
- package/apps/lib/components/InnerLabelField.tsx +20 -16
- package/apps/lib/components/Input.tsx +171 -172
- package/apps/lib/components/InputField.tsx +44 -45
- package/apps/lib/components/InputOTP.tsx +68 -69
- package/apps/lib/components/Label.tsx +61 -58
- package/apps/lib/components/LabelField.tsx +4 -5
- package/apps/lib/components/LabeledCheckBox.tsx +8 -12
- package/apps/lib/components/LabeledRadio.tsx +7 -5
- package/apps/lib/components/LinkButton.tsx +2 -9
- package/apps/lib/components/LoginButton.tsx +4 -9
- package/apps/lib/components/PasswordLevel.tsx +5 -5
- package/apps/lib/components/Popover.tsx +15 -33
- package/apps/lib/components/ProfileMenu.tsx +67 -72
- package/apps/lib/components/Radio.tsx +1 -5
- package/apps/lib/components/RadioCard.tsx +11 -28
- package/apps/lib/components/ScrollArea.tsx +45 -43
- package/apps/lib/components/SearchField.tsx +49 -39
- package/apps/lib/components/SearchableSelect.tsx +16 -16
- package/apps/lib/components/SearchableTable.tsx +108 -118
- package/apps/lib/components/SearchableTree.tsx +469 -0
- package/apps/lib/components/SearchableTreeDialog.tsx +493 -0
- package/apps/lib/components/SectionBlock.tsx +19 -23
- package/apps/lib/components/Select.tsx +80 -186
- package/apps/lib/components/SimpleSelect.tsx +196 -187
- package/apps/lib/components/Skeleton.tsx +9 -12
- package/apps/lib/components/SlideDatePicker.tsx +215 -166
- package/apps/lib/components/SpinLoading.tsx +33 -49
- package/apps/lib/components/Stepper.tsx +13 -56
- package/apps/lib/components/Switch.tsx +8 -10
- package/apps/lib/components/TabFormItem.tsx +3 -12
- package/apps/lib/components/TabSwitch.tsx +7 -34
- package/apps/lib/components/Table.tsx +60 -75
- package/apps/lib/components/{ChartBlockTool.ts → TextEditor/ChartBlockTool.ts} +17 -52
- package/apps/lib/components/TextEditor/RichTextField.tsx +46 -0
- package/apps/lib/components/{TableDnDWrapper.ts → TextEditor/TableDnDWrapper.ts} +15 -48
- package/apps/lib/components/{TextEditor.tsx → TextEditor/TextEditor.tsx} +156 -113
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +429 -0
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +70 -0
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +50 -0
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +48 -0
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +98 -0
- package/apps/lib/{types → components/TextEditor}/editorjs.d.ts +19 -0
- package/apps/lib/components/TextEditor/index.ts +7 -0
- package/apps/lib/{utils → components/TextEditor}/markdownParser.ts +2 -7
- package/apps/lib/components/Textarea.tsx +9 -13
- package/apps/lib/components/Timeline.tsx +21 -41
- package/apps/lib/components/Toast.tsx +83 -83
- package/apps/lib/components/Toggle.tsx +112 -114
- package/apps/lib/components/ToggleButton.tsx +1 -1
- package/apps/lib/components/Tooltip.tsx +24 -19
- package/apps/lib/components/TransparentLabel.tsx +61 -62
- package/apps/lib/components/TreeDropDown.tsx +86 -52
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +15 -48
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +16 -21
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +9 -20
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +3 -3
- package/apps/lib/components/TreeFolder/icons.tsx +14 -17
- package/apps/lib/components/TreeFolder/index.ts +15 -8
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +47 -52
- package/apps/lib/components/TreeFolder/types.ts +32 -32
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +117 -123
- package/apps/lib/hooks/useActiveTreeItem.ts +52 -55
- package/apps/lib/hooks/useClickOutside.ts +21 -20
- package/apps/lib/hooks/useDataViewsState.ts +86 -80
- package/apps/lib/hooks/useIsMobile.ts +12 -12
- package/apps/lib/hooks/useResize.ts +54 -65
- package/apps/lib/hooks/useTagSelection.ts +201 -201
- package/apps/lib/layouts/CNLayout.tsx +181 -140
- package/apps/lib/layouts/DataViewCard.tsx +4 -18
- package/apps/lib/layouts/FieldSection.tsx +2 -6
- package/apps/lib/layouts/TreeSubLayout.tsx +24 -38
- package/apps/lib/providers/ThemeProvider.tsx +8 -23
- package/apps/lib/registry.json +997 -0
- package/apps/lib/tsconfig.json +9 -0
- package/apps/lib/tsconfig.tsbuildinfo +1 -0
- package/apps/lib/utils/cn.ts +1 -1
- package/apps/lib/utils/color.ts +175 -0
- package/apps/lib/utils/dataViews/columnUtils.ts +46 -44
- package/apps/lib/utils/dataViews/fieldUtils.ts +70 -71
- package/apps/lib/utils/dataViews/nestedDataUtils.tsx +129 -122
- package/apps/lib/utils/dataViews/pathUtils.ts +74 -67
- package/apps/lib/utils/dataViews/rangeUtils.ts +121 -112
- package/apps/lib/utils/dataViews/treeUtils.ts +204 -211
- package/apps/lib/utils/dateFormat.ts +64 -54
- package/apps/lib/utils/resize.ts +21 -25
- package/apps/lib/utils/types.ts +13 -13
- package/dist/bin/index.js +8 -2
- package/dist/bin/index.js.map +1 -1
- package/dist/src/shared/getAvailableFiles.d.ts.map +1 -1
- package/dist/src/shared/getAvailableFiles.js +6 -1
- package/dist/src/shared/getAvailableFiles.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +7 -0
- package/dist/src/shared/loadRegistry.d.ts.map +1 -0
- package/dist/src/shared/loadRegistry.js +31 -0
- package/dist/src/shared/loadRegistry.js.map +1 -0
- package/dist/src/shared/resolveInstallPlan.d.ts +12 -0
- package/dist/src/shared/resolveInstallPlan.d.ts.map +1 -0
- package/dist/src/shared/resolveInstallPlan.js +39 -0
- package/dist/src/shared/resolveInstallPlan.js.map +1 -0
- package/dist/src/types/main.d.ts +24 -0
- package/dist/src/types/main.d.ts.map +1 -1
- package/docs/README.md +10 -2
- package/docs/components/action-button.md +30 -24
- package/docs/components/actions-group.md +26 -20
- package/docs/components/alert-dialog.md +45 -45
- package/docs/components/avatar.md +6 -2
- package/docs/components/badge-field.md +6 -2
- package/docs/components/badge.md +7 -1
- package/docs/components/breadcrumb.md +15 -40
- package/docs/components/button-group.md +13 -10
- package/docs/components/button.md +58 -33
- package/docs/components/calendar.md +26 -19
- package/docs/components/card.md +23 -18
- package/docs/components/chart-block-tool.md +129 -0
- package/docs/components/checkbox.md +16 -8
- package/docs/components/cn-layout.md +7 -1
- package/docs/components/color-picker.md +101 -0
- package/docs/components/conclusion-header.md +80 -0
- package/docs/components/context-menu.md +18 -25
- package/docs/components/count-badge.md +7 -1
- package/docs/components/data-table.md +45 -33
- package/docs/components/data-views-config-panel.md +15 -11
- package/docs/components/data-views-layout.md +13 -16
- package/docs/components/date-picker.md +30 -23
- package/docs/components/dialog.md +43 -42
- package/docs/components/divider.md +10 -4
- package/docs/components/drawer.md +161 -135
- package/docs/components/dropdown-menu.md +25 -34
- package/docs/components/field-hint.md +37 -25
- package/docs/components/field-section.md +9 -3
- package/docs/components/form-builder.md +270 -0
- package/docs/components/form-renderer.md +228 -0
- package/docs/components/form-stepper.md +6 -0
- package/docs/components/form-summary.md +123 -0
- package/docs/components/form.md +17 -20
- package/docs/components/header-bar.md +6 -0
- package/docs/components/image-attachment.md +43 -45
- package/docs/components/inbox-view.md +16 -5
- package/docs/components/inner-label-field.md +34 -24
- package/docs/components/input-field.md +18 -10
- package/docs/components/input-otp.md +14 -11
- package/docs/components/input.md +22 -16
- package/docs/components/kanban-view.md +15 -5
- package/docs/components/label-field.md +32 -22
- package/docs/components/label.md +43 -32
- package/docs/components/labeled-check-box.md +16 -8
- package/docs/components/labeled-radio.md +18 -11
- package/docs/components/link-button.md +7 -1
- package/docs/components/login-button.md +8 -2
- package/docs/components/password-level.md +37 -24
- package/docs/components/popover.md +26 -23
- package/docs/components/profile-menu.md +38 -27
- package/docs/components/radio-card.md +16 -9
- package/docs/components/radio.md +16 -8
- package/docs/components/scroll-area.md +6 -2
- package/docs/components/search-field.md +14 -6
- package/docs/components/searchable-select.md +19 -14
- package/docs/components/searchable-table.md +18 -13
- package/docs/components/searchable-tree-dialog.md +190 -0
- package/docs/components/searchable-tree.md +200 -0
- package/docs/components/section-block.md +12 -4
- package/docs/components/select.md +23 -18
- package/docs/components/simple-select.md +14 -10
- package/docs/components/skeleton.md +43 -33
- package/docs/components/slide-date-picker.md +37 -29
- package/docs/components/spin-loading.md +32 -23
- package/docs/components/stepper.md +6 -0
- package/docs/components/switch.md +14 -6
- package/docs/components/tab-form-item.md +7 -1
- package/docs/components/tab-switch.md +13 -6
- package/docs/components/table-dnd-wrapper.md +107 -0
- package/docs/components/table-view.md +15 -5
- package/docs/components/table.md +28 -28
- package/docs/components/text-editor.md +37 -13
- package/docs/components/textarea.md +15 -7
- package/docs/components/timeline.md +6 -0
- package/docs/components/toast.md +35 -26
- package/docs/components/toggle-button.md +24 -21
- package/docs/components/toggle.md +23 -15
- package/docs/components/tooltip.md +42 -30
- package/docs/components/transparent-label.md +29 -20
- package/docs/components/tree-drop-down.md +31 -23
- package/docs/components/tree-sub-layout.md +6 -2
- package/docs/components/tree-view.md +16 -5
- package/docs/explanation/architecture.md +54 -0
- package/docs/explanation/design-system.md +52 -0
- package/docs/how-to/data-views-from-backend-response.md +6 -4
- package/docs/how-to/form-and-list-recipes.md +26 -19
- package/docs/how-to/forms-with-form-builder.md +408 -0
- package/docs/how-to/guides.md +177 -197
- package/docs/migration/changelog.md +38 -0
- package/docs/reference/cli.md +87 -0
- package/docs/reference/components.md +11 -12
- package/docs/reference/hooks.md +8 -8
- package/docs/reference/providers.md +22 -22
- package/docs/reference/tailwind-plugins.md +2 -2
- package/docs/reference/theme.md +85 -0
- package/docs/reference/types.md +4 -4
- package/docs/reference/utilities.md +19 -26
- package/docs/tutorials/building-first-form.md +170 -172
- package/docs/tutorials/component-composition.md +34 -50
- package/docs/tutorials/getting-started.md +2 -2
- package/docs/tutorials/theming-basics.md +13 -10
- package/package.json +31 -3
- package/dist/src/commands/block.d.ts +0 -5
- package/dist/src/commands/block.d.ts.map +0 -1
- package/dist/src/commands/block.js +0 -255
- package/dist/src/commands/block.js.map +0 -1
- package/dist/src/shared/configureFonts.d.ts +0 -6
- package/dist/src/shared/configureFonts.d.ts.map +0 -1
- package/dist/src/shared/configureFonts.js +0 -106
- package/dist/src/shared/configureFonts.js.map +0 -1
- package/dist/src/shared/configureGlobalCss.d.ts +0 -6
- package/dist/src/shared/configureGlobalCss.d.ts.map +0 -1
- package/dist/src/shared/configureGlobalCss.js +0 -154
- package/dist/src/shared/configureGlobalCss.js.map +0 -1
- package/dist/src/shared/configureTailwind.d.ts +0 -7
- package/dist/src/shared/configureTailwind.d.ts.map +0 -1
- package/dist/src/shared/configureTailwind.js +0 -163
- package/dist/src/shared/configureTailwind.js.map +0 -1
- package/dist/src/shared/detectFramework.d.ts +0 -23
- package/dist/src/shared/detectFramework.d.ts.map +0 -1
- package/dist/src/shared/detectFramework.js +0 -119
- package/dist/src/shared/detectFramework.js.map +0 -1
- package/dist/src/shared/installBaseUtils.d.ts +0 -5
- package/dist/src/shared/installBaseUtils.d.ts.map +0 -1
- package/dist/src/shared/installBaseUtils.js +0 -79
- package/dist/src/shared/installBaseUtils.js.map +0 -1
- package/dist/src/shared/resolveAliases.d.ts +0 -24
- package/dist/src/shared/resolveAliases.d.ts.map +0 -1
- package/dist/src/shared/resolveAliases.js +0 -98
- package/dist/src/shared/resolveAliases.js.map +0 -1
|
@@ -10,51 +10,41 @@ keywords: [drawer, sheet, side-panel, bottom-sheet, slide, vaul, form, create, e
|
|
|
10
10
|
> A gesture-based sliding panel built on [Vaul](https://vaul.emilkowal.ski/). It can slide up from the **bottom**, in from the **right**, or in from the **left**. It supports drag-to-dismiss, nested/stacked drawers with an iOS-style scale-back effect, an optional "notch" tab on the top edge, and a dark framed "tray" look. It is the recommended surface for create / edit forms, filter panels, side navigation, action sheets, and full-screen editors.
|
|
11
11
|
|
|
12
12
|
> [!IMPORTANT]
|
|
13
|
-
> The Drawer is **composed**, not configured. There is no single `direction` style switch on `DrawerContent`. You pick the anchor on the root `<Drawer direction="...">` and then pass layout classes (`wrapperClassName`, `className
|
|
13
|
+
> The Drawer is **composed**, not configured. There is no single `direction` style switch on `DrawerContent`. You pick the anchor on the root `<Drawer direction="...">` and then pass layout classes (`wrapperClassName`, `className`) plus a few flags (`framed`, `notch`, `notchSide`) to get the bottom / right / left look. The recipes below give you exact, copy-paste class strings for each direction.
|
|
14
|
+
|
|
15
|
+
> [!WARNING]
|
|
16
|
+
> **Changed in 3.0.** `DrawerContent` no longer paints the light content surface — wrap your
|
|
17
|
+
> content in a [`DrawerPanel`](#drawerpanel). This is what lets a drawer hold a form panel and
|
|
18
|
+
> a dark summary panel side by side, each with its own background. Two knock-on changes:
|
|
19
|
+
> `className` now targets the **tray** (the old inner-surface meaning moves to `DrawerPanel`),
|
|
20
|
+
> and `showHandle` moves to `DrawerPanel` where it defaults to `false`. `trayClassName` still
|
|
21
|
+
> works as a deprecated alias for `className`.
|
|
22
|
+
>
|
|
23
|
+
> ```diff
|
|
24
|
+
> - <DrawerContent className="rounded-[10px]">…</DrawerContent>
|
|
25
|
+
> + <DrawerContent>
|
|
26
|
+
> + <DrawerPanel className="rounded-[10px]">…</DrawerPanel>
|
|
27
|
+
> + </DrawerContent>
|
|
28
|
+
> ```
|
|
14
29
|
|
|
15
30
|
## Installation
|
|
16
31
|
|
|
32
|
+
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
33
|
+
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
34
|
+
|
|
17
35
|
```bash
|
|
36
|
+
npx torch-glare@latest init
|
|
18
37
|
npx torch-glare@latest add Drawer
|
|
19
38
|
```
|
|
20
39
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
> [!NOTE]
|
|
24
|
-
> **Building create / edit forms?** The Drawer ships on its own. The form examples on this page also use `SectionBlock`, `InputField`, and `Button`. Install them alongside it:
|
|
25
|
-
>
|
|
26
|
-
> ```bash
|
|
27
|
-
> npx torch-glare@latest add Drawer SectionBlock InputField Button
|
|
28
|
-
> ```
|
|
29
|
-
>
|
|
30
|
-
> These are *not* auto-installed by `add Drawer`, because `Drawer.tsx` does not import them — they are only needed for the form composition pattern, not for the Drawer itself.
|
|
40
|
+
`add` also copies any components, hooks, and utilities that `Drawer` depends on.
|
|
31
41
|
|
|
32
42
|
## Import
|
|
33
43
|
|
|
44
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
45
|
+
|
|
34
46
|
```tsx
|
|
35
|
-
import {
|
|
36
|
-
Drawer,
|
|
37
|
-
DrawerNested,
|
|
38
|
-
DrawerTrigger,
|
|
39
|
-
DrawerClose,
|
|
40
|
-
DrawerContent,
|
|
41
|
-
DrawerHeader,
|
|
42
|
-
DrawerHeaderTitle,
|
|
43
|
-
DrawerHeaderActions,
|
|
44
|
-
DrawerBadge,
|
|
45
|
-
DrawerFooter,
|
|
46
|
-
DrawerTitle,
|
|
47
|
-
DrawerDescription,
|
|
48
|
-
// Notch (the tab that sticks out of the top edge)
|
|
49
|
-
DrawerNotch,
|
|
50
|
-
DrawerNotchClose,
|
|
51
|
-
DrawerNotchPill,
|
|
52
|
-
DrawerNotchDivider,
|
|
53
|
-
DrawerNotchApp,
|
|
54
|
-
// Lower-level primitives (rarely needed directly)
|
|
55
|
-
DrawerPortal,
|
|
56
|
-
DrawerOverlay,
|
|
57
|
-
} from "@/components/Drawer";
|
|
47
|
+
import { Drawer } from "@/components/Drawer";
|
|
58
48
|
```
|
|
59
49
|
|
|
60
50
|
## Anatomy
|
|
@@ -62,20 +52,25 @@ import {
|
|
|
62
52
|
```tsx
|
|
63
53
|
<Drawer> {/* root — owns open state + direction */}
|
|
64
54
|
<DrawerTrigger /> {/* what opens the drawer (use asChild) */}
|
|
65
|
-
<DrawerContent>
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
<
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
<
|
|
78
|
-
|
|
55
|
+
<DrawerContent> {/* the dark tray; frame / positioning / notch */}
|
|
56
|
+
<DrawerPanel> {/* the light content surface */}
|
|
57
|
+
<DrawerHeader>
|
|
58
|
+
<DrawerHeaderTitle> {/* dark pill holding the title + a badge */}
|
|
59
|
+
<DrawerBadge />
|
|
60
|
+
<DrawerTitle />
|
|
61
|
+
</DrawerHeaderTitle>
|
|
62
|
+
<DrawerHeaderActions /> {/* dark pill holding header buttons */}
|
|
63
|
+
</DrawerHeader>
|
|
64
|
+
|
|
65
|
+
{/* ...your body content... */}
|
|
66
|
+
|
|
67
|
+
<DrawerFooter>
|
|
68
|
+
<DrawerClose /> {/* anything that should close the drawer */}
|
|
69
|
+
</DrawerFooter>
|
|
70
|
+
</DrawerPanel>
|
|
71
|
+
|
|
72
|
+
{/* Anything else here sits BESIDE the panel, with its own background —
|
|
73
|
+
e.g. a <FormSummary />. Give the tray a `gap-*` to space them. */}
|
|
79
74
|
</DrawerContent>
|
|
80
75
|
</Drawer>
|
|
81
76
|
```
|
|
@@ -92,27 +87,29 @@ The default. Slides up from the bottom with a drag handle. Use `framed={false}`
|
|
|
92
87
|
<Button variant="PrimeStyle">Open drawer</Button>
|
|
93
88
|
</DrawerTrigger>
|
|
94
89
|
<DrawerContent framed={false}>
|
|
95
|
-
<
|
|
96
|
-
<
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
90
|
+
<DrawerPanel framed={false} showHandle>
|
|
91
|
+
<DrawerHeader>
|
|
92
|
+
<DrawerTitle>Basic drawer</DrawerTitle>
|
|
93
|
+
<DrawerDescription>
|
|
94
|
+
Drag the handle down or press Escape to close.
|
|
95
|
+
</DrawerDescription>
|
|
96
|
+
</DrawerHeader>
|
|
97
|
+
|
|
98
|
+
<div className="px-4 pb-4">
|
|
99
|
+
<p className="typography-body-small-regular text-content-presentation-action-light-secondary">
|
|
100
|
+
Put any content here — forms, lists, settings.
|
|
101
|
+
</p>
|
|
102
|
+
</div>
|
|
107
103
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
104
|
+
<DrawerFooter>
|
|
105
|
+
<DrawerClose asChild>
|
|
106
|
+
<Button variant="PrimeStyle">Done</Button>
|
|
107
|
+
</DrawerClose>
|
|
108
|
+
<DrawerClose asChild>
|
|
109
|
+
<Button variant="BorderStyle">Cancel</Button>
|
|
110
|
+
</DrawerClose>
|
|
111
|
+
</DrawerFooter>
|
|
112
|
+
</DrawerPanel>
|
|
116
113
|
</DrawerContent>
|
|
117
114
|
</Drawer>
|
|
118
115
|
```
|
|
@@ -152,7 +149,6 @@ function ContactDrawer({ mode = "create", contact }) {
|
|
|
152
149
|
</DrawerTrigger>
|
|
153
150
|
|
|
154
151
|
<DrawerContent
|
|
155
|
-
showHandle={false}
|
|
156
152
|
/* The top-edge notch: close button + "Open in new tab" pill. */
|
|
157
153
|
notch={
|
|
158
154
|
<DrawerNotch>
|
|
@@ -166,9 +162,9 @@ function ContactDrawer({ mode = "create", contact }) {
|
|
|
166
162
|
</DrawerNotch>
|
|
167
163
|
}
|
|
168
164
|
wrapperClassName="top-2 right-2 bottom-2 left-auto mt-0 h-auto w-[1046px] max-w-[calc(100vw-16px)]"
|
|
169
|
-
/* With a notch, round all corners EXCEPT the top one the notch sits on. */
|
|
170
|
-
className="rounded-tr-[16px] rounded-b-[16px]"
|
|
171
165
|
>
|
|
166
|
+
{/* With a notch, round all corners EXCEPT the top one the notch sits on. */}
|
|
167
|
+
<DrawerPanel className="rounded-tr-[16px] rounded-b-[16px]">
|
|
172
168
|
{/* Header: badge flips New / Edit, actions live in their own dark pill */}
|
|
173
169
|
<DrawerHeader>
|
|
174
170
|
<DrawerHeaderTitle>
|
|
@@ -259,6 +255,7 @@ function ContactDrawer({ mode = "create", contact }) {
|
|
|
259
255
|
/>
|
|
260
256
|
</SectionBlock>
|
|
261
257
|
</div>
|
|
258
|
+
</DrawerPanel>
|
|
262
259
|
</DrawerContent>
|
|
263
260
|
</Drawer>
|
|
264
261
|
);
|
|
@@ -304,38 +301,40 @@ function RowDivider() {
|
|
|
304
301
|
<Button variant="PrimeStyle">Checkout</Button>
|
|
305
302
|
</DrawerTrigger>
|
|
306
303
|
<DrawerContent framed={false}>
|
|
307
|
-
<
|
|
308
|
-
<
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
<
|
|
314
|
-
<
|
|
315
|
-
<
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
<
|
|
319
|
-
<
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
304
|
+
<DrawerPanel framed={false} showHandle>
|
|
305
|
+
<DrawerHeader>
|
|
306
|
+
<DrawerTitle>Your cart</DrawerTitle>
|
|
307
|
+
<DrawerDescription>1 item — $129.00</DrawerDescription>
|
|
308
|
+
</DrawerHeader>
|
|
309
|
+
|
|
310
|
+
<DrawerFooter>
|
|
311
|
+
<DrawerNested>
|
|
312
|
+
<DrawerTrigger asChild>
|
|
313
|
+
<Button variant="PrimeStyle">Continue to shipping</Button>
|
|
314
|
+
</DrawerTrigger>
|
|
315
|
+
<DrawerContent framed={false}>
|
|
316
|
+
<DrawerPanel framed={false} showHandle>
|
|
317
|
+
<DrawerHeader>
|
|
318
|
+
<DrawerTitle>Shipping</DrawerTitle>
|
|
319
|
+
</DrawerHeader>
|
|
320
|
+
{/* ...another DrawerNested inside here for payment... */}
|
|
321
|
+
</DrawerPanel>
|
|
322
|
+
</DrawerContent>
|
|
323
|
+
</DrawerNested>
|
|
324
|
+
</DrawerFooter>
|
|
325
|
+
</DrawerPanel>
|
|
325
326
|
</DrawerContent>
|
|
326
327
|
</Drawer>
|
|
327
328
|
```
|
|
328
329
|
|
|
329
330
|
### Notch (top-edge tab)
|
|
330
331
|
|
|
331
|
-
The notch is an optional tab that sticks out of the top edge of the drawer — used for a close button plus an "Open in new tab" / "Open in the app" affordance. Pass it to `DrawerContent` via the `notch` prop. When a notch is present,
|
|
332
|
+
The notch is an optional tab that sticks out of the top edge of the drawer — used for a close button plus an "Open in new tab" / "Open in the app" affordance. Pass it to `DrawerContent` via the `notch` prop. When a notch is present, leave the drag handle off (`DrawerPanel`'s `showHandle` defaults to `false`) and use the asymmetric corner rounding on the panel (`className="rounded-tr-[16px] rounded-b-[16px]"` for a right drawer) so it tucks under the notch.
|
|
332
333
|
|
|
333
334
|
**Simple notch** — close button + "Open in new tab" pill. This is the most common form, used on the create/edit drawer above:
|
|
334
335
|
|
|
335
336
|
```tsx
|
|
336
337
|
<DrawerContent
|
|
337
|
-
showHandle={false}
|
|
338
|
-
className="rounded-tr-[16px] rounded-b-[16px]"
|
|
339
338
|
notch={
|
|
340
339
|
<DrawerNotch>
|
|
341
340
|
<DrawerClose asChild>
|
|
@@ -348,7 +347,9 @@ The notch is an optional tab that sticks out of the top edge of the drawer — u
|
|
|
348
347
|
</DrawerNotch>
|
|
349
348
|
}
|
|
350
349
|
>
|
|
351
|
-
|
|
350
|
+
<DrawerPanel className="rounded-tr-[16px] rounded-b-[16px]">
|
|
351
|
+
{/* ... */}
|
|
352
|
+
</DrawerPanel>
|
|
352
353
|
</DrawerContent>
|
|
353
354
|
```
|
|
354
355
|
|
|
@@ -356,8 +357,6 @@ The notch is an optional tab that sticks out of the top edge of the drawer — u
|
|
|
356
357
|
|
|
357
358
|
```tsx
|
|
358
359
|
<DrawerContent
|
|
359
|
-
showHandle={false}
|
|
360
|
-
className="rounded-tr-[16px] rounded-b-[16px]"
|
|
361
360
|
notch={
|
|
362
361
|
<DrawerNotch>
|
|
363
362
|
<DrawerClose asChild>
|
|
@@ -375,7 +374,9 @@ The notch is an optional tab that sticks out of the top edge of the drawer — u
|
|
|
375
374
|
</DrawerNotch>
|
|
376
375
|
}
|
|
377
376
|
>
|
|
378
|
-
|
|
377
|
+
<DrawerPanel className="rounded-tr-[16px] rounded-b-[16px]">
|
|
378
|
+
{/* ... */}
|
|
379
|
+
</DrawerPanel>
|
|
379
380
|
</DrawerContent>
|
|
380
381
|
```
|
|
381
382
|
|
|
@@ -429,7 +430,7 @@ There is **no automatic per-direction styling**. The anchor is set on the root w
|
|
|
429
430
|
|---|---|---|---|
|
|
430
431
|
| Root prop | _(none)_ | `direction="right"` | `direction="left"` |
|
|
431
432
|
| Sits at | full width, pinned to bottom | floating panel on the right | floating panel on the left |
|
|
432
|
-
| Drag handle |
|
|
433
|
+
| Drag handle | on — `<DrawerPanel showHandle>` | off (the default) | off (the default) |
|
|
433
434
|
| Frame / tray | usually off (`framed={false}`) for clean sheet | on (default) for the dark tray | on (default) |
|
|
434
435
|
| Rounded corners | top corners only | all/left corners | top-left + bottom corners |
|
|
435
436
|
| Notch side | top-left (`notchSide="left"`) | top-left | mirror to `notchSide="right"` |
|
|
@@ -445,11 +446,12 @@ No `direction` prop. Keep the drag handle; drop the frame for a clean sheet.
|
|
|
445
446
|
<Button variant="PrimeStyle">Open bottom sheet</Button>
|
|
446
447
|
</DrawerTrigger>
|
|
447
448
|
<DrawerContent framed={false}>
|
|
448
|
-
{
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
449
|
+
<DrawerPanel framed={false} showHandle>
|
|
450
|
+
<DrawerHeader>
|
|
451
|
+
<DrawerTitle>Comments</DrawerTitle>
|
|
452
|
+
</DrawerHeader>
|
|
453
|
+
{/* ... */}
|
|
454
|
+
</DrawerPanel>
|
|
453
455
|
</DrawerContent>
|
|
454
456
|
</Drawer>
|
|
455
457
|
```
|
|
@@ -462,7 +464,9 @@ No `direction` prop. Keep the drag handle; drop the frame for a clean sheet.
|
|
|
462
464
|
<Button variant="PrimeStyle">Open half-screen</Button>
|
|
463
465
|
</DrawerTrigger>
|
|
464
466
|
<DrawerContent framed={false} wrapperClassName="h-full max-h-[97vh]">
|
|
465
|
-
{
|
|
467
|
+
<DrawerPanel framed={false} showHandle>
|
|
468
|
+
{/* ... */}
|
|
469
|
+
</DrawerPanel>
|
|
466
470
|
</DrawerContent>
|
|
467
471
|
</Drawer>
|
|
468
472
|
```
|
|
@@ -477,26 +481,26 @@ A floating panel anchored to the right edge — the canonical home for create/ed
|
|
|
477
481
|
<Button variant="PrimeStyle">Open right drawer</Button>
|
|
478
482
|
</DrawerTrigger>
|
|
479
483
|
<DrawerContent
|
|
480
|
-
showHandle={false}
|
|
481
484
|
wrapperClassName="top-2 right-2 bottom-2 left-auto mt-0 h-auto w-[420px] max-w-[calc(100vw-16px)]"
|
|
482
|
-
|
|
483
|
-
className="rounded-[10px]"
|
|
485
|
+
className="rounded-[16px]"
|
|
484
486
|
>
|
|
485
|
-
<
|
|
486
|
-
<
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
<
|
|
494
|
-
<
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
<
|
|
498
|
-
|
|
499
|
-
|
|
487
|
+
<DrawerPanel className="rounded-[10px]">
|
|
488
|
+
<DrawerHeader>
|
|
489
|
+
<DrawerTitle>Filters</DrawerTitle>
|
|
490
|
+
<DrawerDescription>Status, owner, tags, priority…</DrawerDescription>
|
|
491
|
+
</DrawerHeader>
|
|
492
|
+
<div className="px-4 pb-4 space-y-3 flex-1 overflow-y-auto">
|
|
493
|
+
{/* ...filter rows... */}
|
|
494
|
+
</div>
|
|
495
|
+
<DrawerFooter>
|
|
496
|
+
<DrawerClose asChild>
|
|
497
|
+
<Button variant="PrimeStyle">Apply</Button>
|
|
498
|
+
</DrawerClose>
|
|
499
|
+
<DrawerClose asChild>
|
|
500
|
+
<Button variant="BorderStyle">Reset</Button>
|
|
501
|
+
</DrawerClose>
|
|
502
|
+
</DrawerFooter>
|
|
503
|
+
</DrawerPanel>
|
|
500
504
|
</DrawerContent>
|
|
501
505
|
</Drawer>
|
|
502
506
|
```
|
|
@@ -513,10 +517,8 @@ Mirror of the right recipe: `direction="left"`, anchor to the left edge, and if
|
|
|
513
517
|
<Button variant="PrimeStyle">Open left drawer</Button>
|
|
514
518
|
</DrawerTrigger>
|
|
515
519
|
<DrawerContent
|
|
516
|
-
showHandle={false}
|
|
517
520
|
notchSide="right"
|
|
518
521
|
wrapperClassName="top-2 left-2 bottom-2 right-auto mt-0 h-auto w-[420px] max-w-[calc(100vw-16px)]"
|
|
519
|
-
className="rounded-tl-[16px] rounded-b-[16px]"
|
|
520
522
|
notch={
|
|
521
523
|
<DrawerNotch>
|
|
522
524
|
<DrawerClose asChild>
|
|
@@ -529,13 +531,15 @@ Mirror of the right recipe: `direction="left"`, anchor to the left edge, and if
|
|
|
529
531
|
</DrawerNotch>
|
|
530
532
|
}
|
|
531
533
|
>
|
|
532
|
-
<
|
|
533
|
-
<
|
|
534
|
-
<
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
534
|
+
<DrawerPanel className="rounded-tl-[16px] rounded-b-[16px]">
|
|
535
|
+
<DrawerHeader>
|
|
536
|
+
<DrawerHeaderTitle>
|
|
537
|
+
<DrawerBadge color="Purple">Menu</DrawerBadge>
|
|
538
|
+
<DrawerTitle>Navigation</DrawerTitle>
|
|
539
|
+
</DrawerHeaderTitle>
|
|
540
|
+
</DrawerHeader>
|
|
541
|
+
{/* ...nav items... */}
|
|
542
|
+
</DrawerPanel>
|
|
539
543
|
</DrawerContent>
|
|
540
544
|
</Drawer>
|
|
541
545
|
```
|
|
@@ -553,7 +557,9 @@ Anchor a bottom drawer to every edge via `wrapperClassName`.
|
|
|
553
557
|
framed={false}
|
|
554
558
|
wrapperClassName="inset-x-0 top-0 bottom-0 m-0 h-screen w-screen max-w-none"
|
|
555
559
|
>
|
|
556
|
-
{
|
|
560
|
+
<DrawerPanel framed={false} showHandle>
|
|
561
|
+
{/* immersive editor / media viewer */}
|
|
562
|
+
</DrawerPanel>
|
|
557
563
|
</DrawerContent>
|
|
558
564
|
</Drawer>
|
|
559
565
|
```
|
|
@@ -576,25 +582,45 @@ Wraps Vaul's `Drawer.Root` and defaults `shouldScaleBackground` to `true`. Accep
|
|
|
576
582
|
|
|
577
583
|
### `DrawerContent`
|
|
578
584
|
|
|
579
|
-
The
|
|
585
|
+
The dark tray. It frames and positions, but paints nothing over its children — each child
|
|
586
|
+
brings its own background. This is where direction-specific styling is applied.
|
|
580
587
|
|
|
581
588
|
| Prop | Type | Default | Description |
|
|
582
589
|
|---|---|---|---|
|
|
583
590
|
| `framed` | `boolean` | `true` | Show the dark "tray" frame (border + inset shadow) around the panel. Set `false` for clean bottom sheets. |
|
|
584
|
-
| `showHandle` | `boolean` | `true` | Show the centered drag handle. Auto-hidden when a `notch` is present. Set `false` for side drawers. |
|
|
585
591
|
| `notch` | `ReactNode` | — | A `DrawerNotch` tab rendered on the top edge. |
|
|
586
592
|
| `notchSide` | `"left" \| "right"` | `"left"` | Which side the notch attaches to (and which corner stays square). Use `"right"` for left-anchored drawers. |
|
|
587
593
|
| `wrapperClassName` | `string` | — | Classes on the outer positioned element — this is how you anchor/size the panel per direction. |
|
|
588
|
-
| `
|
|
589
|
-
| `
|
|
594
|
+
| `className` | `string` | — | Classes on the **dark tray**. Add a `gap-*` here when the tray holds more than one child. |
|
|
595
|
+
| `trayClassName` | `string` | — | **Deprecated** — an alias for `className` (merged last, so it still wins). |
|
|
590
596
|
| `...props` | Vaul `Content` props | — | Forwarded to `Drawer.Content`. |
|
|
591
597
|
|
|
598
|
+
### `DrawerPanel`
|
|
599
|
+
|
|
600
|
+
The light `#F0F0F0` content surface. The tray paints nothing over its children, so a drawer
|
|
601
|
+
can hold a panel **plus something else beside it** — a [FormSummary](./form-summary.md), say —
|
|
602
|
+
with each bringing its own background.
|
|
603
|
+
|
|
604
|
+
```tsx
|
|
605
|
+
<DrawerContent className="gap-[6px]">
|
|
606
|
+
<DrawerPanel>…form…</DrawerPanel>
|
|
607
|
+
<FormSummary … /> {/* dark, sits beside the panel */}
|
|
608
|
+
</DrawerContent>
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
| Prop | Type | Default | Description |
|
|
612
|
+
|---|---|---|---|
|
|
613
|
+
| `framed` | `boolean` | `true` | Panel border + inset shadow that pairs with the tray's frame. Match the tray's `framed`. |
|
|
614
|
+
| `showHandle` | `boolean` | `false` | Show the centered drag handle. Turn on for bottom sheets; leave off when there's a `notch`. |
|
|
615
|
+
| `className` | `string` | — | Classes on the surface (e.g. corner rounding). |
|
|
616
|
+
|
|
592
617
|
### Sub-components
|
|
593
618
|
|
|
594
619
|
| Component | Description |
|
|
595
620
|
|---|---|
|
|
596
621
|
| `DrawerTrigger` | Opens the drawer. Use `asChild` to wrap your own button. |
|
|
597
622
|
| `DrawerClose` | Closes the drawer. Use `asChild` to wrap any element. |
|
|
623
|
+
| `DrawerPanel` | The light content surface. Wrap your body in it — see above. |
|
|
598
624
|
| `DrawerNested` | A nested/stacked drawer. Must be rendered inside an open `DrawerContent`. |
|
|
599
625
|
| `DrawerHeader` | Header row (space-between layout) holding title + actions. |
|
|
600
626
|
| `DrawerHeaderTitle` | Dark rounded pill that groups a `DrawerBadge` + `DrawerTitle`. |
|
|
@@ -11,40 +11,31 @@ keywords: [dropdown-menu, menu, radix-ui, submenu, checkbox, radio, auto-group]
|
|
|
11
11
|
|
|
12
12
|
## Installation
|
|
13
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
|
+
|
|
14
17
|
```bash
|
|
15
|
-
|
|
18
|
+
npx torch-glare@latest init
|
|
19
|
+
npx torch-glare@latest add DropdownMenu
|
|
16
20
|
```
|
|
17
21
|
|
|
22
|
+
`add` also copies any components, hooks, and utilities that `DropdownMenu` depends on.
|
|
23
|
+
|
|
18
24
|
## Import
|
|
19
25
|
|
|
20
|
-
|
|
21
|
-
import {
|
|
22
|
-
DropdownMenu,
|
|
23
|
-
DropdownMenuTrigger,
|
|
24
|
-
DropdownMenuContent,
|
|
25
|
-
DropdownMenuItem,
|
|
26
|
-
DropdownMenuCheckboxItem,
|
|
27
|
-
DropdownMenuRadioGroup,
|
|
28
|
-
DropdownMenuRadioItem,
|
|
29
|
-
DropdownMenuLabel,
|
|
30
|
-
DropdownMenuShortcut,
|
|
31
|
-
DropdownMenuSub,
|
|
32
|
-
DropdownMenuSubTrigger,
|
|
33
|
-
DropdownMenuSubContent,
|
|
34
|
-
DropdownMenuGroup,
|
|
35
|
-
DropdownMenuPortal,
|
|
36
|
-
} from '@torch-ui/components'
|
|
37
|
-
```
|
|
26
|
+
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
38
27
|
|
|
39
|
-
|
|
28
|
+
```tsx
|
|
29
|
+
import { DropdownMenu } from "@/components/DropdownMenu";
|
|
30
|
+
```
|
|
40
31
|
|
|
41
32
|
## Quick Examples
|
|
42
33
|
|
|
43
34
|
### Basic Menu
|
|
44
35
|
|
|
45
36
|
```typescript
|
|
46
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from
|
|
47
|
-
import { Button } from
|
|
37
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/DropdownMenu";
|
|
38
|
+
import { Button } from "@/components/Button";
|
|
48
39
|
|
|
49
40
|
function Example() {
|
|
50
41
|
return (
|
|
@@ -65,7 +56,7 @@ function Example() {
|
|
|
65
56
|
### With Icons
|
|
66
57
|
|
|
67
58
|
```typescript
|
|
68
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from
|
|
59
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/DropdownMenu";
|
|
69
60
|
|
|
70
61
|
function IconMenu() {
|
|
71
62
|
return (
|
|
@@ -97,7 +88,7 @@ function IconMenu() {
|
|
|
97
88
|
### With Keyboard Shortcuts
|
|
98
89
|
|
|
99
90
|
```typescript
|
|
100
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuShortcut } from
|
|
91
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuShortcut } from "@/components/DropdownMenu";
|
|
101
92
|
|
|
102
93
|
function ShortcutMenu() {
|
|
103
94
|
return (
|
|
@@ -129,7 +120,7 @@ function ShortcutMenu() {
|
|
|
129
120
|
Labels act as section boundaries. The loose items between labels are automatically wrapped in boxed groups — no separator component needed.
|
|
130
121
|
|
|
131
122
|
```typescript
|
|
132
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel } from
|
|
123
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel } from "@/components/DropdownMenu";
|
|
133
124
|
|
|
134
125
|
function OrganizedMenu() {
|
|
135
126
|
return (
|
|
@@ -158,7 +149,7 @@ function OrganizedMenu() {
|
|
|
158
149
|
Checkbox and radio items keep the menu **open** when toggled (the built-in `onSelect` calls `preventDefault`), so users can change several options without the menu closing each time.
|
|
159
150
|
|
|
160
151
|
```typescript
|
|
161
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem } from
|
|
152
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuCheckboxItem } from "@/components/DropdownMenu";
|
|
162
153
|
import { useState } from 'react'
|
|
163
154
|
|
|
164
155
|
function CheckboxMenu() {
|
|
@@ -199,7 +190,7 @@ function CheckboxMenu() {
|
|
|
199
190
|
### With Radio Group
|
|
200
191
|
|
|
201
192
|
```typescript
|
|
202
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem } from
|
|
193
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuRadioGroup, DropdownMenuRadioItem } from "@/components/DropdownMenu";
|
|
203
194
|
import { useState } from 'react'
|
|
204
195
|
|
|
205
196
|
function RadioMenu() {
|
|
@@ -225,7 +216,7 @@ function RadioMenu() {
|
|
|
225
216
|
### With Submenu
|
|
226
217
|
|
|
227
218
|
```typescript
|
|
228
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent } from
|
|
219
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent } from "@/components/DropdownMenu";
|
|
229
220
|
|
|
230
221
|
function SubmenuExample() {
|
|
231
222
|
return (
|
|
@@ -258,7 +249,7 @@ function SubmenuExample() {
|
|
|
258
249
|
### Disabled Items
|
|
259
250
|
|
|
260
251
|
```typescript
|
|
261
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from
|
|
252
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/DropdownMenu";
|
|
262
253
|
|
|
263
254
|
function DisabledMenu() {
|
|
264
255
|
return (
|
|
@@ -281,7 +272,7 @@ function DisabledMenu() {
|
|
|
281
272
|
For a true right-click (context) menu, use the dedicated [ContextMenu](./context-menu.md) component instead of DropdownMenu — it opens at the pointer on right-click / long-press.
|
|
282
273
|
|
|
283
274
|
```typescript
|
|
284
|
-
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from
|
|
275
|
+
import { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from "@/components/ContextMenu";
|
|
285
276
|
|
|
286
277
|
function Example() {
|
|
287
278
|
return (
|
|
@@ -304,8 +295,8 @@ function Example() {
|
|
|
304
295
|
Tall menus scroll instead of overflowing off-screen. The surface caps at `maxHeight` (default `320`px) and never exceeds the space available after collision handling. Pass `maxHeight` to change the cap.
|
|
305
296
|
|
|
306
297
|
```typescript
|
|
307
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel } from
|
|
308
|
-
import { Button } from
|
|
298
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel } from "@/components/DropdownMenu";
|
|
299
|
+
import { Button } from "@/components/Button";
|
|
309
300
|
|
|
310
301
|
function LongMenu() {
|
|
311
302
|
return (
|
|
@@ -497,7 +488,7 @@ export const DropdownMenuRadioItem: React.ForwardRefExoticComponent<DropdownMenu
|
|
|
497
488
|
### With State Management
|
|
498
489
|
|
|
499
490
|
```typescript
|
|
500
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from
|
|
491
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/DropdownMenu";
|
|
501
492
|
import { useState } from 'react'
|
|
502
493
|
|
|
503
494
|
function useDropdownMenu() {
|
|
@@ -536,7 +527,7 @@ function StatefulMenu() {
|
|
|
536
527
|
|
|
537
528
|
```typescript
|
|
538
529
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
539
|
-
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from
|
|
530
|
+
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/DropdownMenu";
|
|
540
531
|
|
|
541
532
|
describe('DropdownMenu', () => {
|
|
542
533
|
it('opens on trigger click', () => {
|