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,654 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Drawer
|
|
3
|
-
description: Gesture-based sliding panel built on Vaul. Anchors to the bottom, left, or right of the screen, supports nested/stacked drawers, and composes with SectionBlock + InputField to build create and edit forms.
|
|
4
|
-
group: Overlays & Dialogs
|
|
5
|
-
keywords: [drawer, sheet, side-panel, bottom-sheet, slide, vaul, form, create, edit, sectionblock, nested, drag-to-dismiss]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Drawer
|
|
9
|
-
|
|
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
|
-
|
|
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`) 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
|
-
> ```
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
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
|
-
|
|
35
|
-
```bash
|
|
36
|
-
npx torch-glare@latest init
|
|
37
|
-
npx torch-glare@latest add Drawer
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
`add` also copies any components, hooks, and utilities that `Drawer` depends on.
|
|
41
|
-
|
|
42
|
-
## Import
|
|
43
|
-
|
|
44
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
45
|
-
|
|
46
|
-
```tsx
|
|
47
|
-
import { Drawer } from "@/components/Drawer";
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Anatomy
|
|
51
|
-
|
|
52
|
-
```tsx
|
|
53
|
-
<Drawer> {/* root — owns open state + direction */}
|
|
54
|
-
<DrawerTrigger /> {/* what opens the drawer (use asChild) */}
|
|
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. */}
|
|
74
|
-
</DrawerContent>
|
|
75
|
-
</Drawer>
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
## Quick Examples
|
|
79
|
-
|
|
80
|
-
### Basic (bottom sheet)
|
|
81
|
-
|
|
82
|
-
The default. Slides up from the bottom with a drag handle. Use `framed={false}` for the clean sheet look (no dark tray border).
|
|
83
|
-
|
|
84
|
-
```tsx
|
|
85
|
-
<Drawer>
|
|
86
|
-
<DrawerTrigger asChild>
|
|
87
|
-
<Button variant="PrimeStyle">Open drawer</Button>
|
|
88
|
-
</DrawerTrigger>
|
|
89
|
-
<DrawerContent framed={false}>
|
|
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>
|
|
103
|
-
|
|
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>
|
|
113
|
-
</DrawerContent>
|
|
114
|
-
</Drawer>
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
### Create / Edit form (Drawer + SectionBlock)
|
|
118
|
-
|
|
119
|
-
This is the headline pattern: a **right-anchored** drawer that holds a form, grouped into `SectionBlock`s, with the inputs laid out as label-on-left / field-on-right rows. The same layout works for both **"New item"** (empty fields) and **"Edit item"** (pass `defaultValue` to each field and swap the badge/title).
|
|
120
|
-
|
|
121
|
-
```tsx
|
|
122
|
-
import {
|
|
123
|
-
Drawer,
|
|
124
|
-
DrawerTrigger,
|
|
125
|
-
DrawerContent,
|
|
126
|
-
DrawerHeader,
|
|
127
|
-
DrawerHeaderTitle,
|
|
128
|
-
DrawerHeaderActions,
|
|
129
|
-
DrawerBadge,
|
|
130
|
-
DrawerTitle,
|
|
131
|
-
DrawerClose,
|
|
132
|
-
DrawerNotch,
|
|
133
|
-
DrawerNotchClose,
|
|
134
|
-
DrawerNotchPill,
|
|
135
|
-
} from "@/components/Drawer";
|
|
136
|
-
import { Button } from "@/components/Button";
|
|
137
|
-
import { SectionBlock } from "@/components/SectionBlock";
|
|
138
|
-
import { InputField } from "@/components/InputField";
|
|
139
|
-
|
|
140
|
-
function ContactDrawer({ mode = "create", contact }) {
|
|
141
|
-
const isEdit = mode === "edit";
|
|
142
|
-
|
|
143
|
-
return (
|
|
144
|
-
<Drawer direction="right">
|
|
145
|
-
<DrawerTrigger asChild>
|
|
146
|
-
<Button variant="PrimeStyle">
|
|
147
|
-
{isEdit ? "Edit contact" : "New contact"}
|
|
148
|
-
</Button>
|
|
149
|
-
</DrawerTrigger>
|
|
150
|
-
|
|
151
|
-
<DrawerContent
|
|
152
|
-
/* The top-edge notch: close button + "Open in new tab" pill. */
|
|
153
|
-
notch={
|
|
154
|
-
<DrawerNotch>
|
|
155
|
-
<DrawerClose asChild>
|
|
156
|
-
<DrawerNotchClose />
|
|
157
|
-
</DrawerClose>
|
|
158
|
-
<DrawerNotchPill color="Yellow">
|
|
159
|
-
Open in new tab
|
|
160
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
161
|
-
</DrawerNotchPill>
|
|
162
|
-
</DrawerNotch>
|
|
163
|
-
}
|
|
164
|
-
wrapperClassName="top-2 right-2 bottom-2 left-auto mt-0 h-auto w-[1046px] max-w-[calc(100vw-16px)]"
|
|
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]">
|
|
168
|
-
{/* Header: badge flips New / Edit, actions live in their own dark pill */}
|
|
169
|
-
<DrawerHeader>
|
|
170
|
-
<DrawerHeaderTitle>
|
|
171
|
-
<DrawerBadge color={isEdit ? "Yellow" : "Blue"}>
|
|
172
|
-
{isEdit ? "Edit" : "New"}
|
|
173
|
-
</DrawerBadge>
|
|
174
|
-
<DrawerTitle>Individual Contact</DrawerTitle>
|
|
175
|
-
</DrawerHeaderTitle>
|
|
176
|
-
<div className="flex items-center">
|
|
177
|
-
<Button variant="PrimeStyle" size="L">Save Draft</Button>
|
|
178
|
-
</div>
|
|
179
|
-
</DrawerHeader>
|
|
180
|
-
|
|
181
|
-
{/* Scrollable body holds the grouped form sections */}
|
|
182
|
-
<div className="flex-1 overflow-y-auto px-12 py-6 space-y-3">
|
|
183
|
-
<SectionBlock
|
|
184
|
-
color="Blue"
|
|
185
|
-
containerClassName="w-full"
|
|
186
|
-
title={
|
|
187
|
-
<span className="flex items-center gap-[6px]">
|
|
188
|
-
<i className="ri-draft-fill" />
|
|
189
|
-
Identity
|
|
190
|
-
</span>
|
|
191
|
-
}
|
|
192
|
-
>
|
|
193
|
-
<FieldRow
|
|
194
|
-
label="Name"
|
|
195
|
-
required
|
|
196
|
-
right={
|
|
197
|
-
<div className="flex flex-1 min-w-0 items-center gap-3">
|
|
198
|
-
<InputField
|
|
199
|
-
placeholder="First Name*"
|
|
200
|
-
defaultValue={contact?.firstName}
|
|
201
|
-
className="flex-1 min-w-0"
|
|
202
|
-
/>
|
|
203
|
-
<InputField
|
|
204
|
-
placeholder="Last Name*"
|
|
205
|
-
defaultValue={contact?.lastName}
|
|
206
|
-
className="flex-1 min-w-0"
|
|
207
|
-
/>
|
|
208
|
-
</div>
|
|
209
|
-
}
|
|
210
|
-
/>
|
|
211
|
-
<RowDivider />
|
|
212
|
-
<FieldRow
|
|
213
|
-
label="Email"
|
|
214
|
-
required
|
|
215
|
-
right={
|
|
216
|
-
<InputField
|
|
217
|
-
type="email"
|
|
218
|
-
placeholder="name@example.com"
|
|
219
|
-
defaultValue={contact?.email}
|
|
220
|
-
className="flex-1"
|
|
221
|
-
/>
|
|
222
|
-
}
|
|
223
|
-
/>
|
|
224
|
-
<RowDivider />
|
|
225
|
-
<FieldRow
|
|
226
|
-
label="Phone"
|
|
227
|
-
right={
|
|
228
|
-
<InputField
|
|
229
|
-
placeholder="+1 555 0000"
|
|
230
|
-
defaultValue={contact?.phone}
|
|
231
|
-
className="flex-1"
|
|
232
|
-
/>
|
|
233
|
-
}
|
|
234
|
-
/>
|
|
235
|
-
</SectionBlock>
|
|
236
|
-
|
|
237
|
-
<SectionBlock
|
|
238
|
-
color="Purple"
|
|
239
|
-
containerClassName="w-full"
|
|
240
|
-
title={
|
|
241
|
-
<span className="flex items-center gap-[6px]">
|
|
242
|
-
<i className="ri-map-pin-line" />
|
|
243
|
-
Address
|
|
244
|
-
</span>
|
|
245
|
-
}
|
|
246
|
-
>
|
|
247
|
-
<FieldRow
|
|
248
|
-
label="Street"
|
|
249
|
-
right={<InputField placeholder="123 Main St" className="flex-1" />}
|
|
250
|
-
/>
|
|
251
|
-
<RowDivider />
|
|
252
|
-
<FieldRow
|
|
253
|
-
label="City"
|
|
254
|
-
right={<InputField placeholder="San Francisco" className="flex-1" />}
|
|
255
|
-
/>
|
|
256
|
-
</SectionBlock>
|
|
257
|
-
</div>
|
|
258
|
-
</DrawerPanel>
|
|
259
|
-
</DrawerContent>
|
|
260
|
-
</Drawer>
|
|
261
|
-
);
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/* Reusable label-on-left / field-on-right row. */
|
|
265
|
-
function FieldRow({ label, required, right }) {
|
|
266
|
-
return (
|
|
267
|
-
<div className="flex items-center gap-6 py-[18px]">
|
|
268
|
-
<div className="flex w-[180px] shrink-0 items-center gap-[6px]">
|
|
269
|
-
<span className="typography-body-medium-regular text-content-presentation-action-light-primary">
|
|
270
|
-
{label}
|
|
271
|
-
</span>
|
|
272
|
-
{required && (
|
|
273
|
-
<span className="typography-body-small-medium text-content-presentation-state-negative">
|
|
274
|
-
(Required)
|
|
275
|
-
</span>
|
|
276
|
-
)}
|
|
277
|
-
</div>
|
|
278
|
-
<div className="flex flex-1 min-w-0 items-center">{right}</div>
|
|
279
|
-
</div>
|
|
280
|
-
);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/* Thin separator between rows inside a SectionBlock. */
|
|
284
|
-
function RowDivider() {
|
|
285
|
-
return <div className="h-px w-full bg-border-presentation-global-primary" />;
|
|
286
|
-
}
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
> **Create vs. Edit in one component.** Keep a single drawer and branch on a `mode` prop:
|
|
290
|
-
> - **Badge / title** — `<DrawerBadge color={isEdit ? "Yellow" : "Blue"}>{isEdit ? "Edit" : "New"}</DrawerBadge>`.
|
|
291
|
-
> - **Fields** — spread the existing record into each input's `defaultValue` (or `value` if controlled). Empty in create mode, pre-filled in edit mode.
|
|
292
|
-
> - **Footer / actions** — keep "Save Draft" / "Save" identical; only the submit handler changes (POST vs. PATCH).
|
|
293
|
-
|
|
294
|
-
### Nested drawers (multi-step)
|
|
295
|
-
|
|
296
|
-
`DrawerNested` must live **inside** an already-open `DrawerContent`. The parent scales down and slides back; the child slides in on top. Great for `cart → shipping → payment` style flows or drill-down settings.
|
|
297
|
-
|
|
298
|
-
```tsx
|
|
299
|
-
<Drawer>
|
|
300
|
-
<DrawerTrigger asChild>
|
|
301
|
-
<Button variant="PrimeStyle">Checkout</Button>
|
|
302
|
-
</DrawerTrigger>
|
|
303
|
-
<DrawerContent framed={false}>
|
|
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>
|
|
326
|
-
</DrawerContent>
|
|
327
|
-
</Drawer>
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
### Notch (top-edge tab)
|
|
331
|
-
|
|
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.
|
|
333
|
-
|
|
334
|
-
**Simple notch** — close button + "Open in new tab" pill. This is the most common form, used on the create/edit drawer above:
|
|
335
|
-
|
|
336
|
-
```tsx
|
|
337
|
-
<DrawerContent
|
|
338
|
-
notch={
|
|
339
|
-
<DrawerNotch>
|
|
340
|
-
<DrawerClose asChild>
|
|
341
|
-
<DrawerNotchClose />
|
|
342
|
-
</DrawerClose>
|
|
343
|
-
<DrawerNotchPill color="Yellow">
|
|
344
|
-
Open in new tab
|
|
345
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
346
|
-
</DrawerNotchPill>
|
|
347
|
-
</DrawerNotch>
|
|
348
|
-
}
|
|
349
|
-
>
|
|
350
|
-
<DrawerPanel className="rounded-tr-[16px] rounded-b-[16px]">
|
|
351
|
-
{/* ... */}
|
|
352
|
-
</DrawerPanel>
|
|
353
|
-
</DrawerContent>
|
|
354
|
-
```
|
|
355
|
-
|
|
356
|
-
**App notch** — adds an app icon + name and a colored "Open in the app" pill, separated by a divider:
|
|
357
|
-
|
|
358
|
-
```tsx
|
|
359
|
-
<DrawerContent
|
|
360
|
-
notch={
|
|
361
|
-
<DrawerNotch>
|
|
362
|
-
<DrawerClose asChild>
|
|
363
|
-
<DrawerNotchClose />
|
|
364
|
-
</DrawerClose>
|
|
365
|
-
<DrawerNotchDivider />
|
|
366
|
-
<DrawerNotchApp
|
|
367
|
-
icon={<i className="ri-customer-service-2-fill text-white text-[14px]" />}
|
|
368
|
-
name="Sales & Services App"
|
|
369
|
-
/>
|
|
370
|
-
<DrawerNotchPill color="Blue">
|
|
371
|
-
Open in the app
|
|
372
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
373
|
-
</DrawerNotchPill>
|
|
374
|
-
</DrawerNotch>
|
|
375
|
-
}
|
|
376
|
-
>
|
|
377
|
-
<DrawerPanel className="rounded-tr-[16px] rounded-b-[16px]">
|
|
378
|
-
{/* ... */}
|
|
379
|
-
</DrawerPanel>
|
|
380
|
-
</DrawerContent>
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
#### What "Open in new tab" does
|
|
384
|
-
|
|
385
|
-
> [!IMPORTANT]
|
|
386
|
-
> **`DrawerNotchPill` has no built-in navigation — it is a styled `<button>`.** The "Open in new tab" interaction is a pattern *you* wire up. The intended behavior is:
|
|
387
|
-
>
|
|
388
|
-
> **Clicking "Open in new tab" opens the *same content* the drawer is showing, but as a standalone full page (its own route) in a new browser tab — not as a drawer.**
|
|
389
|
-
>
|
|
390
|
-
> The drawer is the *quick/inline* way to view or edit a record; the full page is the *expanded* view of the exact same thing (same form, same data), just rendered at full width instead of in the side panel. So a "New contact" drawer opens a full-page "New contact" form; an "Edit contact #42" drawer opens the full-page edit route for contact 42.
|
|
391
|
-
|
|
392
|
-
**How to wire it.** Point the pill at the route that renders the same section as a page, and open it in a new tab. `DrawerNotchPill` forwards all button props, so use `onClick`:
|
|
393
|
-
|
|
394
|
-
```tsx
|
|
395
|
-
// `href` is the full-page route that renders the SAME section/form as the drawer.
|
|
396
|
-
// For an edit drawer, include the record id so the page opens pre-filled:
|
|
397
|
-
// const href = isEdit ? `/contacts/${contact.id}/edit` : "/contacts/new";
|
|
398
|
-
|
|
399
|
-
<DrawerNotchPill
|
|
400
|
-
color="Yellow"
|
|
401
|
-
onClick={() => window.open(href, "_blank", "noopener")}
|
|
402
|
-
>
|
|
403
|
-
Open in new tab
|
|
404
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
405
|
-
</DrawerNotchPill>
|
|
406
|
-
```
|
|
407
|
-
|
|
408
|
-
Or, if you prefer a real anchor (better for middle-click / "copy link"), wrap a styled link instead of the pill — the pill is just a button, so for true link semantics render your own `<a target="_blank">` with the same classes, or in Next.js:
|
|
409
|
-
|
|
410
|
-
```tsx
|
|
411
|
-
import Link from "next/link";
|
|
412
|
-
|
|
413
|
-
<Link href={href} target="_blank" rel="noopener" className="contents">
|
|
414
|
-
<DrawerNotchPill color="Yellow" tabIndex={-1}>
|
|
415
|
-
Open in new tab
|
|
416
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
417
|
-
</DrawerNotchPill>
|
|
418
|
-
</Link>
|
|
419
|
-
```
|
|
420
|
-
|
|
421
|
-
**The contract:** the drawer and the full page must render the **same section component** with the **same data**. Build the form body (the `SectionBlock` groups + fields) as a shared component, drop it into the `DrawerContent` for the inline view and into a normal page route for the full-page view. That guarantees "open in new tab" shows an identical form — just full-page instead of in the drawer.
|
|
422
|
-
|
|
423
|
-
> The **"Open in the app"** pill (App notch) follows the same idea but targets a different surface — e.g. a deep link into a separate application — rather than a full-page route in the same app.
|
|
424
|
-
|
|
425
|
-
## Direction — how bottom, right, and left differ
|
|
426
|
-
|
|
427
|
-
There is **no automatic per-direction styling**. The anchor is set on the root with `direction`, and the *look* (where it sits, which corners round, whether there's a drag handle or a frame) comes from props you pass to `DrawerContent`. Here is exactly what changes per direction and the copy-paste recipe for each.
|
|
428
|
-
|
|
429
|
-
| Aspect | Bottom (default) | Right | Left |
|
|
430
|
-
|---|---|---|---|
|
|
431
|
-
| Root prop | _(none)_ | `direction="right"` | `direction="left"` |
|
|
432
|
-
| Sits at | full width, pinned to bottom | floating panel on the right | floating panel on the left |
|
|
433
|
-
| Drag handle | on — `<DrawerPanel showHandle>` | off (the default) | off (the default) |
|
|
434
|
-
| Frame / tray | usually off (`framed={false}`) for clean sheet | on (default) for the dark tray | on (default) |
|
|
435
|
-
| Rounded corners | top corners only | all/left corners | top-left + bottom corners |
|
|
436
|
-
| Notch side | inline-start (`notchSide="start"`) | inline-start | mirror to `notchSide="end"` |
|
|
437
|
-
| Best for | mobile sheets, action sheets, comments | create/edit forms, filters, detail panels | RTL panels, side navigation |
|
|
438
|
-
|
|
439
|
-
### Bottom (default)
|
|
440
|
-
|
|
441
|
-
No `direction` prop. Keep the drag handle; drop the frame for a clean sheet.
|
|
442
|
-
|
|
443
|
-
```tsx
|
|
444
|
-
<Drawer>
|
|
445
|
-
<DrawerTrigger asChild>
|
|
446
|
-
<Button variant="PrimeStyle">Open bottom sheet</Button>
|
|
447
|
-
</DrawerTrigger>
|
|
448
|
-
<DrawerContent framed={false}>
|
|
449
|
-
<DrawerPanel framed={false} showHandle>
|
|
450
|
-
<DrawerHeader>
|
|
451
|
-
<DrawerTitle>Comments</DrawerTitle>
|
|
452
|
-
</DrawerHeader>
|
|
453
|
-
{/* ... */}
|
|
454
|
-
</DrawerPanel>
|
|
455
|
-
</DrawerContent>
|
|
456
|
-
</Drawer>
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
**Half-screen / snap points** — the bottom drawer can open to half height then snap to full. Drive it with Vaul's `snapPoints` on the root:
|
|
460
|
-
|
|
461
|
-
```tsx
|
|
462
|
-
<Drawer snapPoints={[0.5, 1]} fadeFromIndex={1}>
|
|
463
|
-
<DrawerTrigger asChild>
|
|
464
|
-
<Button variant="PrimeStyle">Open half-screen</Button>
|
|
465
|
-
</DrawerTrigger>
|
|
466
|
-
<DrawerContent framed={false} wrapperClassName="h-full max-h-[97vh]">
|
|
467
|
-
<DrawerPanel framed={false} showHandle>
|
|
468
|
-
{/* ... */}
|
|
469
|
-
</DrawerPanel>
|
|
470
|
-
</DrawerContent>
|
|
471
|
-
</Drawer>
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Right
|
|
475
|
-
|
|
476
|
-
A floating panel anchored to the right edge — the canonical home for create/edit forms and filter panels. Hide the handle, anchor with `wrapperClassName`, round the corners.
|
|
477
|
-
|
|
478
|
-
```tsx
|
|
479
|
-
<Drawer direction="right">
|
|
480
|
-
<DrawerTrigger asChild>
|
|
481
|
-
<Button variant="PrimeStyle">Open right drawer</Button>
|
|
482
|
-
</DrawerTrigger>
|
|
483
|
-
<DrawerContent
|
|
484
|
-
wrapperClassName="top-2 right-2 bottom-2 left-auto mt-0 h-auto w-[420px] max-w-[calc(100vw-16px)]"
|
|
485
|
-
className="rounded-[16px]"
|
|
486
|
-
>
|
|
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>
|
|
504
|
-
</DrawerContent>
|
|
505
|
-
</Drawer>
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
> Widen `w-[420px]` to `w-[1046px]` (as in the form example) for a roomy two-column form. Always pair a fixed width with `max-w-[calc(100vw-16px)]` so it never overflows on small screens.
|
|
509
|
-
|
|
510
|
-
### Left (RTL / navigation)
|
|
511
|
-
|
|
512
|
-
Mirror of the right recipe: `direction="left"`, anchor to the left edge, and if you use a notch, set `notchSide="end"` so the tab sits on the panel's trailing edge.
|
|
513
|
-
|
|
514
|
-
```tsx
|
|
515
|
-
<Drawer direction="left">
|
|
516
|
-
<DrawerTrigger asChild>
|
|
517
|
-
<Button variant="PrimeStyle">Open left drawer</Button>
|
|
518
|
-
</DrawerTrigger>
|
|
519
|
-
<DrawerContent
|
|
520
|
-
notchSide="end"
|
|
521
|
-
wrapperClassName="top-2 left-2 bottom-2 right-auto mt-0 h-auto w-[420px] max-w-[calc(100vw-16px)]"
|
|
522
|
-
notch={
|
|
523
|
-
<DrawerNotch>
|
|
524
|
-
<DrawerClose asChild>
|
|
525
|
-
<DrawerNotchClose />
|
|
526
|
-
</DrawerClose>
|
|
527
|
-
<DrawerNotchPill color="Yellow">
|
|
528
|
-
Open in new tab
|
|
529
|
-
<i className="ri-arrow-right-up-line text-[12px]" />
|
|
530
|
-
</DrawerNotchPill>
|
|
531
|
-
</DrawerNotch>
|
|
532
|
-
}
|
|
533
|
-
>
|
|
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>
|
|
543
|
-
</DrawerContent>
|
|
544
|
-
</Drawer>
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
### Full-screen
|
|
548
|
-
|
|
549
|
-
Anchor a bottom drawer to every edge via `wrapperClassName`.
|
|
550
|
-
|
|
551
|
-
```tsx
|
|
552
|
-
<Drawer>
|
|
553
|
-
<DrawerTrigger asChild>
|
|
554
|
-
<Button variant="PrimeStyle">Open full-screen</Button>
|
|
555
|
-
</DrawerTrigger>
|
|
556
|
-
<DrawerContent
|
|
557
|
-
framed={false}
|
|
558
|
-
wrapperClassName="inset-x-0 top-0 bottom-0 m-0 h-screen w-screen max-w-none"
|
|
559
|
-
>
|
|
560
|
-
<DrawerPanel framed={false} showHandle>
|
|
561
|
-
{/* immersive editor / media viewer */}
|
|
562
|
-
</DrawerPanel>
|
|
563
|
-
</DrawerContent>
|
|
564
|
-
</Drawer>
|
|
565
|
-
```
|
|
566
|
-
|
|
567
|
-
## API Reference
|
|
568
|
-
|
|
569
|
-
### `Drawer` (root)
|
|
570
|
-
|
|
571
|
-
Wraps Vaul's `Drawer.Root` and defaults `shouldScaleBackground` to `true`. Accepts all [Vaul Root props](https://vaul.emilkowal.ski/api).
|
|
572
|
-
|
|
573
|
-
| Prop | Type | Default | Description |
|
|
574
|
-
|---|---|---|---|
|
|
575
|
-
| `direction` | `"bottom" \| "top" \| "left" \| "right"` | `"bottom"` | Edge the drawer slides in from. |
|
|
576
|
-
| `shouldScaleBackground` | `boolean` | `true` | Scales/pushes the page back when open (the iOS sheet effect). |
|
|
577
|
-
| `open` | `boolean` | — | Controlled open state. |
|
|
578
|
-
| `onOpenChange` | `(open: boolean) => void` | — | Fires when open state changes. |
|
|
579
|
-
| `snapPoints` | `(number \| string)[]` | — | Snap stops, e.g. `[0.5, 1]` for half then full. |
|
|
580
|
-
| `fadeFromIndex` | `number` | — | Snap index from which the overlay starts to fade. |
|
|
581
|
-
| `nested` | `boolean` | — | Prefer the `DrawerNested` component instead. |
|
|
582
|
-
|
|
583
|
-
### `DrawerContent`
|
|
584
|
-
|
|
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.
|
|
587
|
-
|
|
588
|
-
| Prop | Type | Default | Description |
|
|
589
|
-
|---|---|---|---|
|
|
590
|
-
| `framed` | `boolean` | `true` | Show the dark "tray" frame (border + inset shadow) around the panel. Set `false` for clean bottom sheets. |
|
|
591
|
-
| `notch` | `ReactNode` | — | A `DrawerNotch` tab rendered on the top edge. |
|
|
592
|
-
| `notchSide` | `"start" \| "end"` | `"start"` | Which **inline** edge the notch attaches to (and which corner stays square). Logical, so it mirrors under `dir="rtl"` without you computing a direction. Use `"end"` for left-anchored drawers. |
|
|
593
|
-
| `wrapperClassName` | `string` | — | Classes on the outer positioned element — this is how you anchor/size the panel per direction. |
|
|
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). |
|
|
596
|
-
| `...props` | Vaul `Content` props | — | Forwarded to `Drawer.Content`. |
|
|
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
|
-
|
|
617
|
-
### Sub-components
|
|
618
|
-
|
|
619
|
-
| Component | Description |
|
|
620
|
-
|---|---|
|
|
621
|
-
| `DrawerTrigger` | Opens the drawer. Use `asChild` to wrap your own button. |
|
|
622
|
-
| `DrawerClose` | Closes the drawer. Use `asChild` to wrap any element. |
|
|
623
|
-
| `DrawerPanel` | The light content surface. Wrap your body in it — see above. |
|
|
624
|
-
| `DrawerNested` | A nested/stacked drawer. Must be rendered inside an open `DrawerContent`. |
|
|
625
|
-
| `DrawerHeader` | Header row (space-between layout) holding title + actions. |
|
|
626
|
-
| `DrawerHeaderTitle` | Dark rounded pill that groups a `DrawerBadge` + `DrawerTitle`. |
|
|
627
|
-
| `DrawerHeaderActions` | Dark rounded pill (right-aligned) for header buttons. |
|
|
628
|
-
| `DrawerTitle` | Accessible title (maps to Vaul `Drawer.Title`). |
|
|
629
|
-
| `DrawerDescription` | Muted supporting text (maps to Vaul `Drawer.Description`). |
|
|
630
|
-
| `DrawerBadge` | Small uppercase status pill. `color`: `Blue \| Green \| Red \| Yellow \| Purple \| Gray` (default `Blue`). |
|
|
631
|
-
| `DrawerFooter` | Bottom action area (`mt-auto`, stacked). |
|
|
632
|
-
| `DrawerNotch` | The top-edge tab container. `side`: `"start" \| "end"` (default `"start"`); normally cloned in by `DrawerContent` from `notchSide`. |
|
|
633
|
-
| `DrawerNotchClose` | Round close button for inside a notch. |
|
|
634
|
-
| `DrawerNotchPill` | Pill button for inside a notch. `color`: `Yellow \| Blue \| Gray` (default `Yellow`). Styled `<button>` only — wire navigation yourself via `onClick` (see ["What 'Open in new tab' does"](#what-open-in-new-tab-does)). |
|
|
635
|
-
| `DrawerNotchDivider` | Thin vertical divider between notch items. |
|
|
636
|
-
| `DrawerNotchApp` | App identity block (icon + name) for inside a notch. Props: `icon?`, `name`. |
|
|
637
|
-
| `DrawerPortal` / `DrawerOverlay` | Lower-level primitives; rarely used directly. |
|
|
638
|
-
|
|
639
|
-
## Best Practices
|
|
640
|
-
|
|
641
|
-
- **Pick the anchor by job.** Bottom for mobile sheets / action sheets / comments; right for create-edit forms and filter/detail panels; left for RTL panels and side navigation.
|
|
642
|
-
- **Side drawers: hide the handle.** Always pass `showHandle={false}` on left/right drawers — the drag handle only makes sense on a bottom sheet.
|
|
643
|
-
- **Always cap the width.** Pair any fixed `w-[…]` with `max-w-[calc(100vw-16px)]` so the panel never overflows narrow viewports.
|
|
644
|
-
- **One drawer for create *and* edit.** Branch on a `mode` prop for the badge/title and feed `defaultValue`/`value` from the record. Don't build two near-identical drawers.
|
|
645
|
-
- **Group form fields with `SectionBlock`.** Use a colored `SectionBlock` per logical group (Identity, Address, …) and the `FieldRow` / `RowDivider` helpers for consistent label/field rows.
|
|
646
|
-
- **Make the body scroll, not the panel.** Put `flex-1 overflow-y-auto` on the body wrapper so the header/footer stay pinned while content scrolls.
|
|
647
|
-
- **`DrawerNested` only inside an open drawer.** It will not work as a standalone trigger.
|
|
648
|
-
|
|
649
|
-
## Related Components
|
|
650
|
-
|
|
651
|
-
- **[Dialog](./dialog.md)** — centered modal for short confirmations and compact forms.
|
|
652
|
-
- **[AlertDialog](./alert-dialog.md)** — blocking confirmation for destructive actions.
|
|
653
|
-
- **[SectionBlock](./section-block.md)** — the grouping container used for the form body above.
|
|
654
|
-
- **[InputField](./input-field.md)** — the input used in the form rows.
|