torch-glare 2.5.5 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/bin/index.js +9 -24
- package/dist/bin/index.js.map +1 -1
- package/dist/src/commands/add.d.ts +2 -2
- package/dist/src/commands/add.d.ts.map +1 -1
- package/dist/src/commands/add.js +4 -70
- package/dist/src/commands/add.js.map +1 -1
- package/dist/src/commands/hook.d.ts +5 -4
- package/dist/src/commands/hook.d.ts.map +1 -1
- package/dist/src/commands/hook.js +7 -75
- package/dist/src/commands/hook.js.map +1 -1
- package/dist/src/commands/init.js +1 -1
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/layout.d.ts +5 -4
- package/dist/src/commands/layout.d.ts.map +1 -1
- package/dist/src/commands/layout.js +7 -75
- package/dist/src/commands/layout.js.map +1 -1
- package/dist/src/commands/provider.d.ts +5 -4
- package/dist/src/commands/provider.d.ts.map +1 -1
- package/dist/src/commands/provider.js +7 -75
- package/dist/src/commands/provider.js.map +1 -1
- package/dist/src/commands/update.d.ts.map +1 -1
- package/dist/src/commands/update.js +78 -43
- package/dist/src/commands/update.js.map +1 -1
- package/dist/src/commands/utils.d.ts +5 -4
- package/dist/src/commands/utils.d.ts.map +1 -1
- package/dist/src/commands/utils.js +7 -80
- package/dist/src/commands/utils.js.map +1 -1
- package/dist/src/shared/addFromRegistry.d.ts +16 -0
- package/dist/src/shared/addFromRegistry.d.ts.map +1 -0
- package/dist/src/shared/addFromRegistry.js +88 -0
- package/dist/src/shared/addFromRegistry.js.map +1 -0
- package/dist/src/shared/getInstallCommand.d.ts.map +1 -1
- package/dist/src/shared/getInstallCommand.js +5 -0
- package/dist/src/shared/getInstallCommand.js.map +1 -1
- package/dist/src/shared/installDependencies.d.ts +0 -10
- package/dist/src/shared/installDependencies.d.ts.map +1 -1
- package/dist/src/shared/installDependencies.js +0 -17
- package/dist/src/shared/installDependencies.js.map +1 -1
- package/dist/src/shared/installFromPlan.d.ts +7 -5
- package/dist/src/shared/installFromPlan.d.ts.map +1 -1
- package/dist/src/shared/installFromPlan.js +103 -36
- package/dist/src/shared/installFromPlan.js.map +1 -1
- package/dist/src/shared/loadRegistry.d.ts +12 -3
- package/dist/src/shared/loadRegistry.d.ts.map +1 -1
- package/dist/src/shared/loadRegistry.js +19 -20
- package/dist/src/shared/loadRegistry.js.map +1 -1
- package/dist/src/shared/registryClient.d.ts +19 -0
- package/dist/src/shared/registryClient.d.ts.map +1 -0
- package/dist/src/shared/registryClient.js +128 -0
- package/dist/src/shared/registryClient.js.map +1 -0
- package/dist/src/shared/resolveEntry.d.ts +10 -7
- package/dist/src/shared/resolveEntry.d.ts.map +1 -1
- package/dist/src/shared/resolveEntry.js +18 -13
- package/dist/src/shared/resolveEntry.js.map +1 -1
- package/dist/src/shared/suggestOtherCommand.d.ts +7 -1
- package/dist/src/shared/suggestOtherCommand.d.ts.map +1 -1
- package/dist/src/shared/suggestOtherCommand.js +29 -23
- package/dist/src/shared/suggestOtherCommand.js.map +1 -1
- package/dist/src/types/main.d.ts +31 -2
- package/dist/src/types/main.d.ts.map +1 -1
- package/package.json +6 -11
- package/apps/lib/components/ActionButton.tsx +0 -93
- package/apps/lib/components/ActionsGroup.tsx +0 -27
- package/apps/lib/components/AlertDialog.tsx +0 -204
- package/apps/lib/components/Avatar.tsx +0 -46
- package/apps/lib/components/Badge.tsx +0 -250
- package/apps/lib/components/BadgeField.tsx +0 -338
- package/apps/lib/components/Breadcrumb.tsx +0 -280
- package/apps/lib/components/Button.tsx +0 -317
- package/apps/lib/components/ButtonGroup.tsx +0 -190
- package/apps/lib/components/Calendar.tsx +0 -115
- package/apps/lib/components/Card.tsx +0 -95
- package/apps/lib/components/Checkbox.tsx +0 -42
- package/apps/lib/components/ColorPicker.tsx +0 -441
- package/apps/lib/components/ConclusionHeader.tsx +0 -148
- package/apps/lib/components/ContextMenu.tsx +0 -571
- package/apps/lib/components/CountBadge.tsx +0 -52
- package/apps/lib/components/DataTable.tsx +0 -213
- package/apps/lib/components/DataViews/badge.ts +0 -49
- package/apps/lib/components/DataViews/cell.tsx +0 -324
- package/apps/lib/components/DataViews/context.ts +0 -144
- package/apps/lib/components/DataViews/data-views.tsx +0 -383
- package/apps/lib/components/DataViews/filters/children.tsx +0 -98
- package/apps/lib/components/DataViews/filters/custom.tsx +0 -34
- package/apps/lib/components/DataViews/filters/filters.tsx +0 -157
- package/apps/lib/components/DataViews/filters/index.ts +0 -4
- package/apps/lib/components/DataViews/filters/labelled.tsx +0 -20
- package/apps/lib/components/DataViews/filters/presets.tsx +0 -65
- package/apps/lib/components/DataViews/filters/sync.tsx +0 -35
- package/apps/lib/components/DataViews/filters/values.ts +0 -173
- package/apps/lib/components/DataViews/header.tsx +0 -220
- package/apps/lib/components/DataViews/hooks/index.ts +0 -5
- package/apps/lib/components/DataViews/hooks/useActiveRow.ts +0 -22
- package/apps/lib/components/DataViews/hooks/useControllable.ts +0 -52
- package/apps/lib/components/DataViews/index.ts +0 -84
- package/apps/lib/components/DataViews/panel/columns.tsx +0 -153
- package/apps/lib/components/DataViews/panel/controls.tsx +0 -106
- package/apps/lib/components/DataViews/panel/index.ts +0 -3
- package/apps/lib/components/DataViews/panel/panel.tsx +0 -164
- package/apps/lib/components/DataViews/panel/saved-views.tsx +0 -67
- package/apps/lib/components/DataViews/panel/section.tsx +0 -81
- package/apps/lib/components/DataViews/panel/sort.tsx +0 -42
- package/apps/lib/components/DataViews/panel/tab.tsx +0 -31
- package/apps/lib/components/DataViews/slots.ts +0 -63
- package/apps/lib/components/DataViews/states.tsx +0 -38
- package/apps/lib/components/DataViews/types.ts +0 -510
- package/apps/lib/components/DataViews/views/board-view.tsx +0 -381
- package/apps/lib/components/DataViews/views/card-rows.tsx +0 -36
- package/apps/lib/components/DataViews/views/inbox-view.tsx +0 -260
- package/apps/lib/components/DataViews/views/pane-views.tsx +0 -196
- package/apps/lib/components/DataViews/views/table-view.tsx +0 -493
- package/apps/lib/components/DataViews/views/tree-view.tsx +0 -367
- package/apps/lib/components/DatePicker.tsx +0 -232
- package/apps/lib/components/Dialog.tsx +0 -116
- package/apps/lib/components/Divider.tsx +0 -28
- package/apps/lib/components/Drawer.tsx +0 -420
- package/apps/lib/components/DropdownMenu.tsx +0 -540
- package/apps/lib/components/FieldHint.tsx +0 -69
- package/apps/lib/components/Form.tsx +0 -182
- package/apps/lib/components/FormBuilder/context.ts +0 -73
- package/apps/lib/components/FormBuilder/field-kind.ts +0 -28
- package/apps/lib/components/FormBuilder/fields/ChoiceFields.tsx +0 -60
- package/apps/lib/components/FormBuilder/fields/ColorField.tsx +0 -59
- package/apps/lib/components/FormBuilder/fields/CustomField.tsx +0 -11
- package/apps/lib/components/FormBuilder/fields/DateField.tsx +0 -32
- package/apps/lib/components/FormBuilder/fields/FieldArray.tsx +0 -74
- package/apps/lib/components/FormBuilder/fields/FieldShell.tsx +0 -163
- package/apps/lib/components/FormBuilder/fields/FileField.tsx +0 -39
- package/apps/lib/components/FormBuilder/fields/OptionListFields.tsx +0 -132
- package/apps/lib/components/FormBuilder/fields/OtpField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/PhoneField.tsx +0 -109
- package/apps/lib/components/FormBuilder/fields/RichTextEditorField.tsx +0 -31
- package/apps/lib/components/FormBuilder/fields/SelectField.tsx +0 -91
- package/apps/lib/components/FormBuilder/fields/SignatureField.tsx +0 -157
- package/apps/lib/components/FormBuilder/fields/SliderField.tsx +0 -67
- package/apps/lib/components/FormBuilder/fields/SwitchBoxField.tsx +0 -41
- package/apps/lib/components/FormBuilder/fields/TableField.tsx +0 -336
- package/apps/lib/components/FormBuilder/fields/TextField.tsx +0 -213
- package/apps/lib/components/FormBuilder/fields/TreeSelectField.tsx +0 -43
- package/apps/lib/components/FormBuilder/fields/countries.ts +0 -303
- package/apps/lib/components/FormBuilder/fields/index.ts +0 -25
- package/apps/lib/components/FormBuilder/form-builder.tsx +0 -198
- package/apps/lib/components/FormBuilder/index.ts +0 -31
- package/apps/lib/components/FormBuilder/numberFormat.ts +0 -16
- package/apps/lib/components/FormBuilder/submit.tsx +0 -47
- package/apps/lib/components/FormBuilder/types.ts +0 -311
- package/apps/lib/components/FormRenderer/FormDrawer.tsx +0 -128
- package/apps/lib/components/FormRenderer/detail.tsx +0 -207
- package/apps/lib/components/FormRenderer/form-renderer.tsx +0 -297
- package/apps/lib/components/FormRenderer/header.tsx +0 -88
- package/apps/lib/components/FormRenderer/index.ts +0 -15
- package/apps/lib/components/FormRenderer/section.tsx +0 -39
- package/apps/lib/components/FormRenderer/stepper.tsx +0 -339
- package/apps/lib/components/FormRenderer/types.ts +0 -78
- package/apps/lib/components/FormSummary.tsx +0 -282
- package/apps/lib/components/HeaderBar.tsx +0 -117
- package/apps/lib/components/ImageAttachment.tsx +0 -209
- package/apps/lib/components/InnerLabelField.tsx +0 -154
- package/apps/lib/components/Input.tsx +0 -224
- package/apps/lib/components/InputField.tsx +0 -147
- package/apps/lib/components/InputOTP.tsx +0 -84
- package/apps/lib/components/Label.tsx +0 -129
- package/apps/lib/components/LabelField.tsx +0 -76
- package/apps/lib/components/LabeledCheckBox.tsx +0 -51
- package/apps/lib/components/LabeledRadio.tsx +0 -51
- package/apps/lib/components/LinkButton.tsx +0 -94
- package/apps/lib/components/LoginButton.tsx +0 -51
- package/apps/lib/components/PasswordLevel.tsx +0 -58
- package/apps/lib/components/Popover.tsx +0 -312
- package/apps/lib/components/ProfileMenu.tsx +0 -85
- package/apps/lib/components/Radio.tsx +0 -59
- package/apps/lib/components/RadioCard.tsx +0 -50
- package/apps/lib/components/ScrollArea.tsx +0 -54
- package/apps/lib/components/SearchField.tsx +0 -62
- package/apps/lib/components/SearchableSelect.tsx +0 -318
- package/apps/lib/components/SearchableTable.tsx +0 -344
- package/apps/lib/components/SearchableTree.tsx +0 -485
- package/apps/lib/components/SearchableTreeDialog.tsx +0 -502
- package/apps/lib/components/SectionBlock.tsx +0 -147
- package/apps/lib/components/Select.tsx +0 -347
- package/apps/lib/components/SimpleSelect.tsx +0 -225
- package/apps/lib/components/Skeleton.tsx +0 -12
- package/apps/lib/components/SlideDatePicker.tsx +0 -253
- package/apps/lib/components/SpinLoading.tsx +0 -174
- package/apps/lib/components/Stepper.tsx +0 -480
- package/apps/lib/components/Switch.tsx +0 -82
- package/apps/lib/components/TabFormItem.tsx +0 -153
- package/apps/lib/components/TabSwitch.tsx +0 -172
- package/apps/lib/components/Table.tsx +0 -610
- package/apps/lib/components/TextEditor/ChartBlockTool.ts +0 -676
- package/apps/lib/components/TextEditor/RichTextField.tsx +0 -46
- package/apps/lib/components/TextEditor/TableDnDWrapper.ts +0 -462
- package/apps/lib/components/TextEditor/TextEditor.tsx +0 -1164
- package/apps/lib/components/TextEditor/TextEditorToolbar.tsx +0 -429
- package/apps/lib/components/TextEditor/editor-tools/AlignmentTune.ts +0 -70
- package/apps/lib/components/TextEditor/editor-tools/ColorInlineTool.ts +0 -50
- package/apps/lib/components/TextEditor/editor-tools/StrikethroughInlineTool.ts +0 -48
- package/apps/lib/components/TextEditor/editor-tools/inlineFormat.ts +0 -98
- package/apps/lib/components/TextEditor/editorjs.d.ts +0 -60
- package/apps/lib/components/TextEditor/index.ts +0 -7
- package/apps/lib/components/TextEditor/markdownParser.ts +0 -346
- package/apps/lib/components/Textarea.tsx +0 -117
- package/apps/lib/components/Timeline.tsx +0 -263
- package/apps/lib/components/Toast.tsx +0 -87
- package/apps/lib/components/Toggle.tsx +0 -125
- package/apps/lib/components/ToggleButton.tsx +0 -140
- package/apps/lib/components/Tooltip.tsx +0 -116
- package/apps/lib/components/TransparentLabel.tsx +0 -71
- package/apps/lib/components/TreeDropDown.tsx +0 -115
- package/apps/lib/components/TreeFolder/TreeFolder.tsx +0 -380
- package/apps/lib/components/TreeFolder/TreeFolderBreadcrumb.tsx +0 -75
- package/apps/lib/components/TreeFolder/TreeFolderRow.tsx +0 -354
- package/apps/lib/components/TreeFolder/TreeFolderStyles.tsx +0 -60
- package/apps/lib/components/TreeFolder/icons.tsx +0 -60
- package/apps/lib/components/TreeFolder/index.ts +0 -24
- package/apps/lib/components/TreeFolder/treeFolderUtils.ts +0 -109
- package/apps/lib/components/TreeFolder/types.ts +0 -77
- package/apps/lib/components/TreeFolder/useTreeFolderDnD.ts +0 -118
- package/apps/lib/hooks/useActiveTreeItem.ts +0 -58
- package/apps/lib/hooks/useClickOutside.ts +0 -27
- package/apps/lib/hooks/useDragDrop.tsx +0 -365
- package/apps/lib/hooks/useInfiniteScroll.ts +0 -108
- package/apps/lib/hooks/useIsMobile.ts +0 -21
- package/apps/lib/hooks/useResize.ts +0 -67
- package/apps/lib/hooks/useTagSelection.ts +0 -214
- package/apps/lib/layouts/CNLayout.tsx +0 -372
- package/apps/lib/layouts/DataViewCard.tsx +0 -62
- package/apps/lib/layouts/FieldSection.tsx +0 -91
- package/apps/lib/layouts/TreeSubLayout.tsx +0 -173
- package/apps/lib/providers/ThemeProvider.tsx +0 -84
- package/apps/lib/registry.json +0 -1201
- package/apps/lib/tsconfig.json +0 -9
- package/apps/lib/tsconfig.tsbuildinfo +0 -1
- package/apps/lib/utils/cn.ts +0 -6
- package/apps/lib/utils/color.ts +0 -175
- package/apps/lib/utils/dataViews/path.ts +0 -67
- package/apps/lib/utils/dataViews/query.ts +0 -73
- package/apps/lib/utils/dataViews/types.ts +0 -187
- package/apps/lib/utils/dateFormat.ts +0 -108
- package/apps/lib/utils/resize.ts +0 -31
- package/apps/lib/utils/types.ts +0 -16
- package/docs/BLOCKS.md +0 -129
- package/docs/CHANGELOG-1.1.16.md +0 -108
- package/docs/Cover.png +0 -0
- package/docs/README.md +0 -215
- package/docs/components/action-button.md +0 -638
- package/docs/components/actions-group.md +0 -708
- package/docs/components/alert-dialog.md +0 -920
- package/docs/components/avatar.md +0 -709
- package/docs/components/badge-field.md +0 -712
- package/docs/components/badge.md +0 -301
- package/docs/components/breadcrumb.md +0 -930
- package/docs/components/button-group.md +0 -650
- package/docs/components/button.md +0 -639
- package/docs/components/calendar.md +0 -555
- package/docs/components/card.md +0 -622
- package/docs/components/chart-block-tool.md +0 -129
- package/docs/components/checkbox.md +0 -699
- package/docs/components/cn-layout.md +0 -854
- package/docs/components/color-picker.md +0 -101
- package/docs/components/conclusion-header.md +0 -80
- package/docs/components/context-menu.md +0 -483
- package/docs/components/count-badge.md +0 -560
- package/docs/components/data-table.md +0 -854
- package/docs/components/data-views/backend-response.md +0 -324
- package/docs/components/data-views/examples/a11y-rtl.md +0 -250
- package/docs/components/data-views/examples/api-orders-route.md +0 -130
- package/docs/components/data-views/examples/fields.md +0 -362
- package/docs/components/data-views/examples/filters.md +0 -307
- package/docs/components/data-views/examples/inbox-routing.md +0 -218
- package/docs/components/data-views/examples/index.md +0 -29
- package/docs/components/data-views/examples/overview.md +0 -244
- package/docs/components/data-views/examples/panel.md +0 -212
- package/docs/components/data-views/examples/scale.md +0 -231
- package/docs/components/data-views/examples/server-side.md +0 -210
- package/docs/components/data-views/examples/state.md +0 -250
- package/docs/components/data-views/examples/tree-custom.md +0 -388
- package/docs/components/data-views/examples/view-registry.md +0 -313
- package/docs/components/data-views/examples/views.md +0 -534
- package/docs/components/data-views/guide.md +0 -405
- package/docs/components/data-views/index.md +0 -1495
- package/docs/components/data-views/migration.md +0 -79
- package/docs/components/date-picker.md +0 -857
- package/docs/components/dialog.md +0 -929
- package/docs/components/divider.md +0 -766
- package/docs/components/drawer.md +0 -654
- package/docs/components/dropdown-menu.md +0 -668
- package/docs/components/field-hint.md +0 -898
- package/docs/components/field-section.md +0 -781
- package/docs/components/form-builder.md +0 -276
- package/docs/components/form-renderer.md +0 -326
- package/docs/components/form-summary.md +0 -138
- package/docs/components/form.md +0 -785
- package/docs/components/header-bar.md +0 -188
- package/docs/components/image-attachment.md +0 -906
- package/docs/components/inner-label-field.md +0 -819
- package/docs/components/input-field.md +0 -623
- package/docs/components/input-otp.md +0 -756
- package/docs/components/input.md +0 -634
- package/docs/components/label-field.md +0 -770
- package/docs/components/label.md +0 -761
- package/docs/components/labeled-check-box.md +0 -642
- package/docs/components/labeled-radio.md +0 -796
- package/docs/components/link-button.md +0 -685
- package/docs/components/login-button.md +0 -872
- package/docs/components/password-level.md +0 -803
- package/docs/components/popover.md +0 -649
- package/docs/components/profile-menu.md +0 -656
- package/docs/components/radio-card.md +0 -801
- package/docs/components/radio.md +0 -735
- package/docs/components/scroll-area.md +0 -691
- package/docs/components/search-field.md +0 -702
- package/docs/components/searchable-select.md +0 -368
- package/docs/components/searchable-table.md +0 -438
- package/docs/components/searchable-tree-dialog.md +0 -190
- package/docs/components/searchable-tree.md +0 -200
- package/docs/components/section-block.md +0 -477
- package/docs/components/select.md +0 -709
- package/docs/components/simple-select.md +0 -741
- package/docs/components/skeleton.md +0 -706
- package/docs/components/slide-date-picker.md +0 -837
- package/docs/components/spin-loading.md +0 -696
- package/docs/components/stepper.md +0 -316
- package/docs/components/switch.md +0 -770
- package/docs/components/tab-form-item.md +0 -773
- package/docs/components/tab-switch.md +0 -170
- package/docs/components/table-dnd-wrapper.md +0 -107
- package/docs/components/table.md +0 -1088
- package/docs/components/text-editor.md +0 -735
- package/docs/components/textarea.md +0 -681
- package/docs/components/timeline.md +0 -254
- package/docs/components/toast.md +0 -773
- package/docs/components/toggle-button.md +0 -643
- package/docs/components/toggle.md +0 -882
- package/docs/components/tooltip.md +0 -513
- package/docs/components/transparent-label.md +0 -721
- package/docs/components/tree-drop-down.md +0 -740
- package/docs/components/tree-folder.md +0 -110
- package/docs/components/tree-sub-layout.md +0 -707
- package/docs/explanation/architecture.md +0 -54
- package/docs/explanation/design-system.md +0 -52
- package/docs/how-to/form-and-list-recipes.md +0 -386
- package/docs/how-to/forms-with-form-builder.md +0 -472
- package/docs/how-to/guides.md +0 -1027
- package/docs/migration/changelog.md +0 -54
- package/docs/migration/form-builder-2.5.2.md +0 -113
- package/docs/reference/cli.md +0 -112
- package/docs/reference/components.md +0 -572
- package/docs/reference/hooks.md +0 -1500
- package/docs/reference/providers.md +0 -866
- package/docs/reference/tailwind-plugins.md +0 -942
- package/docs/reference/theme.md +0 -85
- package/docs/reference/types.md +0 -1016
- package/docs/reference/utilities.md +0 -704
- package/docs/tutorials/building-first-form.md +0 -846
- package/docs/tutorials/component-composition.md +0 -882
- package/docs/tutorials/getting-started.md +0 -302
- package/docs/tutorials/theming-basics.md +0 -785
|
@@ -1,740 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: TreeDropDown
|
|
3
|
-
description: Expandable/collapsible tree navigation item with smooth animations for hierarchical content
|
|
4
|
-
group: Data Display
|
|
5
|
-
keywords: [tree, dropdown, navigation, expandable, collapsible, accordion, hierarchy, nested]
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# TreeDropDown
|
|
9
|
-
|
|
10
|
-
> An animated expandable/collapsible tree navigation component for displaying hierarchical content structures. Perfect for nested navigation menus, file trees, and categorized lists.
|
|
11
|
-
|
|
12
|
-
## Installation
|
|
13
|
-
|
|
14
|
-
TORCH Glare is a copy-in library: the CLI copies this component's source into your project
|
|
15
|
-
(you do **not** install it from the npm package). Run `init` once, then `add`:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
npx torch-glare@latest init
|
|
19
|
-
npx torch-glare@latest add TreeDropDown
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
`add` also copies any components, hooks, and utilities that `TreeDropDown` depends on.
|
|
23
|
-
|
|
24
|
-
## Import
|
|
25
|
-
|
|
26
|
-
Import from your project's local path — the alias configured in `glare.json` (e.g. `@/*`):
|
|
27
|
-
|
|
28
|
-
```tsx
|
|
29
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
## Quick Examples
|
|
33
|
-
|
|
34
|
-
### Basic Usage
|
|
35
|
-
|
|
36
|
-
```typescript
|
|
37
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
38
|
-
|
|
39
|
-
function Example() {
|
|
40
|
-
return (
|
|
41
|
-
<TreeDropDown treeLabel="Documents">
|
|
42
|
-
<div>README.md</div>
|
|
43
|
-
<div>package.json</div>
|
|
44
|
-
<div>tsconfig.json</div>
|
|
45
|
-
</TreeDropDown>
|
|
46
|
-
)
|
|
47
|
-
}
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Nested Tree Structure
|
|
51
|
-
|
|
52
|
-
```typescript
|
|
53
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
54
|
-
|
|
55
|
-
function FileTree() {
|
|
56
|
-
return (
|
|
57
|
-
<TreeDropDown treeLabel="src" variant="default">
|
|
58
|
-
<TreeDropDown treeLabel="components" variant="secondary">
|
|
59
|
-
<div>Button.tsx</div>
|
|
60
|
-
<div>Input.tsx</div>
|
|
61
|
-
<div>Card.tsx</div>
|
|
62
|
-
</TreeDropDown>
|
|
63
|
-
<TreeDropDown treeLabel="utils" variant="secondary">
|
|
64
|
-
<div>helpers.ts</div>
|
|
65
|
-
<div>constants.ts</div>
|
|
66
|
-
</TreeDropDown>
|
|
67
|
-
<div>index.ts</div>
|
|
68
|
-
</TreeDropDown>
|
|
69
|
-
)
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
### Controlled State
|
|
74
|
-
|
|
75
|
-
```typescript
|
|
76
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
77
|
-
import { useState } from 'react'
|
|
78
|
-
|
|
79
|
-
function ControlledTree() {
|
|
80
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
81
|
-
|
|
82
|
-
return (
|
|
83
|
-
<div>
|
|
84
|
-
<button onClick={() => setIsOpen(!isOpen)}>
|
|
85
|
-
{isOpen ? 'Collapse' : 'Expand'} Tree
|
|
86
|
-
</button>
|
|
87
|
-
<TreeDropDown
|
|
88
|
-
treeLabel="Settings"
|
|
89
|
-
open={isOpen}
|
|
90
|
-
>
|
|
91
|
-
<div>General</div>
|
|
92
|
-
<div>Privacy</div>
|
|
93
|
-
<div>Security</div>
|
|
94
|
-
</TreeDropDown>
|
|
95
|
-
</div>
|
|
96
|
-
)
|
|
97
|
-
}
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
### With Custom Labels
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
104
|
-
import { Badge } from "@/components/Badge";
|
|
105
|
-
|
|
106
|
-
function TreeWithBadges() {
|
|
107
|
-
return (
|
|
108
|
-
<TreeDropDown
|
|
109
|
-
treeLabel={
|
|
110
|
-
<div className="flex items-center gap-2">
|
|
111
|
-
<span>Notifications</span>
|
|
112
|
-
<Badge color="redOrange" label="3" size="XS" />
|
|
113
|
-
</div>
|
|
114
|
-
}
|
|
115
|
-
>
|
|
116
|
-
<div>New message from Alice</div>
|
|
117
|
-
<div>Comment on your post</div>
|
|
118
|
-
<div>System update available</div>
|
|
119
|
-
</TreeDropDown>
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
### Documentation Navigation
|
|
125
|
-
|
|
126
|
-
```typescript
|
|
127
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
128
|
-
|
|
129
|
-
function DocsNavigation() {
|
|
130
|
-
return (
|
|
131
|
-
<div className="space-y-1">
|
|
132
|
-
<TreeDropDown treeLabel="Getting Started" variant="default">
|
|
133
|
-
<div>Installation</div>
|
|
134
|
-
<div>Quick Start</div>
|
|
135
|
-
<div>Configuration</div>
|
|
136
|
-
</TreeDropDown>
|
|
137
|
-
|
|
138
|
-
<TreeDropDown treeLabel="Components" variant="default">
|
|
139
|
-
<TreeDropDown treeLabel="Forms" variant="secondary">
|
|
140
|
-
<div>Button</div>
|
|
141
|
-
<div>Input</div>
|
|
142
|
-
<div>Checkbox</div>
|
|
143
|
-
</TreeDropDown>
|
|
144
|
-
<TreeDropDown treeLabel="Layout" variant="secondary">
|
|
145
|
-
<div>Card</div>
|
|
146
|
-
<div>Grid</div>
|
|
147
|
-
</TreeDropDown>
|
|
148
|
-
</TreeDropDown>
|
|
149
|
-
|
|
150
|
-
<TreeDropDown treeLabel="API Reference" variant="default">
|
|
151
|
-
<div>Props</div>
|
|
152
|
-
<div>Hooks</div>
|
|
153
|
-
<div>Types</div>
|
|
154
|
-
</TreeDropDown>
|
|
155
|
-
</div>
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
### Dark Theme
|
|
161
|
-
|
|
162
|
-
```typescript
|
|
163
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
164
|
-
|
|
165
|
-
function DarkTree() {
|
|
166
|
-
return (
|
|
167
|
-
<TreeDropDown
|
|
168
|
-
treeLabel="Dark Mode Tree"
|
|
169
|
-
theme="dark"
|
|
170
|
-
variant="default"
|
|
171
|
-
>
|
|
172
|
-
<div>Item 1</div>
|
|
173
|
-
<div>Item 2</div>
|
|
174
|
-
<div>Item 3</div>
|
|
175
|
-
</TreeDropDown>
|
|
176
|
-
)
|
|
177
|
-
}
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
### With Icons
|
|
181
|
-
|
|
182
|
-
```typescript
|
|
183
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
184
|
-
|
|
185
|
-
function IconTree() {
|
|
186
|
-
return (
|
|
187
|
-
<TreeDropDown
|
|
188
|
-
treeLabel={
|
|
189
|
-
<div className="flex items-center gap-2">
|
|
190
|
-
<i className="ri-folder-line" />
|
|
191
|
-
<span>Projects</span>
|
|
192
|
-
</div>
|
|
193
|
-
}
|
|
194
|
-
>
|
|
195
|
-
<div className="flex items-center gap-2">
|
|
196
|
-
<i className="ri-file-text-line" />
|
|
197
|
-
<span>project-1.md</span>
|
|
198
|
-
</div>
|
|
199
|
-
<div className="flex items-center gap-2">
|
|
200
|
-
<i className="ri-file-code-line" />
|
|
201
|
-
<span>app.tsx</span>
|
|
202
|
-
</div>
|
|
203
|
-
</TreeDropDown>
|
|
204
|
-
)
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### Multi-Level Navigation
|
|
209
|
-
|
|
210
|
-
```typescript
|
|
211
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
212
|
-
|
|
213
|
-
function MultiLevelNav() {
|
|
214
|
-
return (
|
|
215
|
-
<TreeDropDown treeLabel="Company" variant="default" open>
|
|
216
|
-
<TreeDropDown treeLabel="Engineering" variant="secondary">
|
|
217
|
-
<TreeDropDown treeLabel="Frontend" variant="secondary">
|
|
218
|
-
<div>React Team</div>
|
|
219
|
-
<div>Vue Team</div>
|
|
220
|
-
</TreeDropDown>
|
|
221
|
-
<TreeDropDown treeLabel="Backend" variant="secondary">
|
|
222
|
-
<div>API Team</div>
|
|
223
|
-
<div>Database Team</div>
|
|
224
|
-
</TreeDropDown>
|
|
225
|
-
</TreeDropDown>
|
|
226
|
-
<TreeDropDown treeLabel="Design" variant="secondary">
|
|
227
|
-
<div>UI/UX</div>
|
|
228
|
-
<div>Graphics</div>
|
|
229
|
-
</TreeDropDown>
|
|
230
|
-
</TreeDropDown>
|
|
231
|
-
)
|
|
232
|
-
}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
### Custom Styling
|
|
236
|
-
|
|
237
|
-
```typescript
|
|
238
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
239
|
-
|
|
240
|
-
function StyledTree() {
|
|
241
|
-
return (
|
|
242
|
-
<TreeDropDown
|
|
243
|
-
treeLabel="Custom Styled Tree"
|
|
244
|
-
className="border border-gray-300 rounded-lg p-2"
|
|
245
|
-
childrenContainerClassName="bg-gray-50 rounded p-2"
|
|
246
|
-
>
|
|
247
|
-
<div className="hover:bg-gray-100 p-2 rounded">Item 1</div>
|
|
248
|
-
<div className="hover:bg-gray-100 p-2 rounded">Item 2</div>
|
|
249
|
-
<div className="hover:bg-gray-100 p-2 rounded">Item 3</div>
|
|
250
|
-
</TreeDropDown>
|
|
251
|
-
)
|
|
252
|
-
}
|
|
253
|
-
```
|
|
254
|
-
|
|
255
|
-
### Initially Expanded
|
|
256
|
-
|
|
257
|
-
```typescript
|
|
258
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
259
|
-
|
|
260
|
-
function ExpandedByDefault() {
|
|
261
|
-
return (
|
|
262
|
-
<TreeDropDown
|
|
263
|
-
treeLabel="Expanded Section"
|
|
264
|
-
open={true} // Initially expanded
|
|
265
|
-
>
|
|
266
|
-
<div>Visible content 1</div>
|
|
267
|
-
<div>Visible content 2</div>
|
|
268
|
-
<div>Visible content 3</div>
|
|
269
|
-
</TreeDropDown>
|
|
270
|
-
)
|
|
271
|
-
}
|
|
272
|
-
```
|
|
273
|
-
|
|
274
|
-
## API Reference
|
|
275
|
-
|
|
276
|
-
### TreeDropDown Props
|
|
277
|
-
|
|
278
|
-
| Prop | Type | Default | Description |
|
|
279
|
-
|------|------|---------|-------------|
|
|
280
|
-
| `treeLabel` | `ReactNode` | Required | Label/header for the tree item (can be string or JSX) |
|
|
281
|
-
| `variant` | `'default' \| 'secondary'` | `'secondary'` | Visual style variant |
|
|
282
|
-
| `open` | `boolean` | `undefined` | Controlled open/closed state |
|
|
283
|
-
| `theme` | `'dark' \| 'light' \| 'default'` | - | Theme variant |
|
|
284
|
-
| `className` | `string` | - | Additional CSS classes for the header |
|
|
285
|
-
| `childrenContainerClassName` | `string` | - | Additional CSS classes for children container |
|
|
286
|
-
| `children` | `ReactNode` | - | Content to show when expanded |
|
|
287
|
-
|
|
288
|
-
### Inherited Props
|
|
289
|
-
|
|
290
|
-
Extends `HTMLAttributes<HTMLDivElement>`, so all standard div props are supported:
|
|
291
|
-
- `onClick`, `onMouseEnter`, `onMouseLeave`, etc.
|
|
292
|
-
- `id`, `role`, `aria-*` attributes
|
|
293
|
-
- `style`, `data-*` attributes
|
|
294
|
-
|
|
295
|
-
## TypeScript
|
|
296
|
-
|
|
297
|
-
### Full Type Definitions
|
|
298
|
-
|
|
299
|
-
```typescript
|
|
300
|
-
import { HTMLAttributes, ReactNode } from 'react'
|
|
301
|
-
import { VariantProps } from 'class-variance-authority'
|
|
302
|
-
|
|
303
|
-
interface TreeDropDownProps
|
|
304
|
-
extends HTMLAttributes<HTMLDivElement>,
|
|
305
|
-
VariantProps<typeof TreeDropDownVariants> {
|
|
306
|
-
theme?: 'dark' | 'light' | 'default'
|
|
307
|
-
treeLabel: ReactNode
|
|
308
|
-
open?: boolean
|
|
309
|
-
variant?: 'secondary' | 'default'
|
|
310
|
-
childrenContainerClassName?: string
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
export const TreeDropDown: React.FC<TreeDropDownProps>
|
|
314
|
-
```
|
|
315
|
-
|
|
316
|
-
### Usage with TypeScript
|
|
317
|
-
|
|
318
|
-
```typescript
|
|
319
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
320
|
-
import { ReactNode } from 'react'
|
|
321
|
-
|
|
322
|
-
interface TreeItem {
|
|
323
|
-
id: string
|
|
324
|
-
label: ReactNode
|
|
325
|
-
children?: TreeItem[]
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
function TypedTree({ items }: { items: TreeItem[] }) {
|
|
329
|
-
return (
|
|
330
|
-
<>
|
|
331
|
-
{items.map((item) => (
|
|
332
|
-
<TreeDropDown key={item.id} treeLabel={item.label}>
|
|
333
|
-
{item.children?.map((child) => (
|
|
334
|
-
<div key={child.id}>{child.label}</div>
|
|
335
|
-
))}
|
|
336
|
-
</TreeDropDown>
|
|
337
|
-
))}
|
|
338
|
-
</>
|
|
339
|
-
)
|
|
340
|
-
}
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
## Common Patterns
|
|
344
|
-
|
|
345
|
-
### Recursive Tree Structure
|
|
346
|
-
|
|
347
|
-
```typescript
|
|
348
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
349
|
-
|
|
350
|
-
interface TreeNode {
|
|
351
|
-
id: string
|
|
352
|
-
label: string
|
|
353
|
-
children?: TreeNode[]
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
function RecursiveTree({ nodes }: { nodes: TreeNode[] }) {
|
|
357
|
-
return (
|
|
358
|
-
<>
|
|
359
|
-
{nodes.map((node) =>
|
|
360
|
-
node.children ? (
|
|
361
|
-
<TreeDropDown key={node.id} treeLabel={node.label}>
|
|
362
|
-
<RecursiveTree nodes={node.children} />
|
|
363
|
-
</TreeDropDown>
|
|
364
|
-
) : (
|
|
365
|
-
<div key={node.id}>{node.label}</div>
|
|
366
|
-
)
|
|
367
|
-
)}
|
|
368
|
-
</>
|
|
369
|
-
)
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
// Usage
|
|
373
|
-
const data: TreeNode[] = [
|
|
374
|
-
{
|
|
375
|
-
id: '1',
|
|
376
|
-
label: 'Parent 1',
|
|
377
|
-
children: [
|
|
378
|
-
{ id: '1.1', label: 'Child 1.1' },
|
|
379
|
-
{
|
|
380
|
-
id: '1.2',
|
|
381
|
-
label: 'Child 1.2',
|
|
382
|
-
children: [{ id: '1.2.1', label: 'Grandchild 1.2.1' }],
|
|
383
|
-
},
|
|
384
|
-
],
|
|
385
|
-
},
|
|
386
|
-
]
|
|
387
|
-
|
|
388
|
-
<RecursiveTree nodes={data} />
|
|
389
|
-
```
|
|
390
|
-
|
|
391
|
-
### Expand/Collapse All
|
|
392
|
-
|
|
393
|
-
```typescript
|
|
394
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
395
|
-
import { useState } from 'react'
|
|
396
|
-
|
|
397
|
-
function ExpandCollapseAll() {
|
|
398
|
-
const [expandAll, setExpandAll] = useState(false)
|
|
399
|
-
|
|
400
|
-
return (
|
|
401
|
-
<div>
|
|
402
|
-
<button onClick={() => setExpandAll(!expandAll)}>
|
|
403
|
-
{expandAll ? 'Collapse' : 'Expand'} All
|
|
404
|
-
</button>
|
|
405
|
-
|
|
406
|
-
<TreeDropDown treeLabel="Section 1" open={expandAll}>
|
|
407
|
-
<div>Item 1.1</div>
|
|
408
|
-
<div>Item 1.2</div>
|
|
409
|
-
</TreeDropDown>
|
|
410
|
-
|
|
411
|
-
<TreeDropDown treeLabel="Section 2" open={expandAll}>
|
|
412
|
-
<div>Item 2.1</div>
|
|
413
|
-
<div>Item 2.2</div>
|
|
414
|
-
</TreeDropDown>
|
|
415
|
-
</div>
|
|
416
|
-
)
|
|
417
|
-
}
|
|
418
|
-
```
|
|
419
|
-
|
|
420
|
-
### With Active State
|
|
421
|
-
|
|
422
|
-
```typescript
|
|
423
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
424
|
-
import { useState } from 'react'
|
|
425
|
-
|
|
426
|
-
function NavigationTree() {
|
|
427
|
-
const [activeItem, setActiveItem] = useState<string>('home')
|
|
428
|
-
|
|
429
|
-
const Item = ({ id, label }: { id: string; label: string }) => (
|
|
430
|
-
<div
|
|
431
|
-
onClick={() => setActiveItem(id)}
|
|
432
|
-
className={`cursor-pointer p-2 rounded ${
|
|
433
|
-
activeItem === id ? 'bg-blue-100 text-blue-600' : ''
|
|
434
|
-
}`}
|
|
435
|
-
>
|
|
436
|
-
{label}
|
|
437
|
-
</div>
|
|
438
|
-
)
|
|
439
|
-
|
|
440
|
-
return (
|
|
441
|
-
<TreeDropDown treeLabel="Navigation">
|
|
442
|
-
<Item id="home" label="Home" />
|
|
443
|
-
<Item id="about" label="About" />
|
|
444
|
-
<Item id="contact" label="Contact" />
|
|
445
|
-
</TreeDropDown>
|
|
446
|
-
)
|
|
447
|
-
}
|
|
448
|
-
```
|
|
449
|
-
|
|
450
|
-
## Variants
|
|
451
|
-
|
|
452
|
-
### Default Variant
|
|
453
|
-
|
|
454
|
-
- Used for top-level tree items
|
|
455
|
-
- Purple/blue accent colors when active
|
|
456
|
-
- Suitable for primary navigation sections
|
|
457
|
-
|
|
458
|
-
```typescript
|
|
459
|
-
<TreeDropDown variant="default" treeLabel="Main Section">
|
|
460
|
-
{/* content */}
|
|
461
|
-
</TreeDropDown>
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
### Secondary Variant
|
|
465
|
-
|
|
466
|
-
- Used for nested tree items
|
|
467
|
-
- Navy/blue accent colors when active
|
|
468
|
-
- Better for nested hierarchies
|
|
469
|
-
|
|
470
|
-
```typescript
|
|
471
|
-
<TreeDropDown variant="secondary" treeLabel="Subsection">
|
|
472
|
-
{/* content */}
|
|
473
|
-
</TreeDropDown>
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
## Animation Behavior
|
|
477
|
-
|
|
478
|
-
### Expand Animation
|
|
479
|
-
- Max-height transitions from 0 to 20000px
|
|
480
|
-
- Duration: 500ms ease-in-out
|
|
481
|
-
- Arrow rotates 180 degrees
|
|
482
|
-
- Margin-top adds 4px spacing
|
|
483
|
-
|
|
484
|
-
### Collapse Animation
|
|
485
|
-
- Max-height transitions to 0
|
|
486
|
-
- Duration: 500ms ease-in-out
|
|
487
|
-
- Arrow rotates back to 0 degrees
|
|
488
|
-
- Margin-top returns to 0
|
|
489
|
-
|
|
490
|
-
### Hover Effects
|
|
491
|
-
- Background color change
|
|
492
|
-
- Border color highlight
|
|
493
|
-
- Gap increases slightly (2px → 14px or 8px when active)
|
|
494
|
-
- Duration: 150ms ease-in-out
|
|
495
|
-
|
|
496
|
-
## Testing
|
|
497
|
-
|
|
498
|
-
### Unit Test Example
|
|
499
|
-
|
|
500
|
-
```typescript
|
|
501
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
502
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
503
|
-
|
|
504
|
-
describe('TreeDropDown', () => {
|
|
505
|
-
it('renders tree label', () => {
|
|
506
|
-
render(
|
|
507
|
-
<TreeDropDown treeLabel="My Tree">
|
|
508
|
-
<div>Child content</div>
|
|
509
|
-
</TreeDropDown>
|
|
510
|
-
)
|
|
511
|
-
|
|
512
|
-
expect(screen.getByText('My Tree')).toBeInTheDocument()
|
|
513
|
-
})
|
|
514
|
-
|
|
515
|
-
it('toggles content on click', () => {
|
|
516
|
-
render(
|
|
517
|
-
<TreeDropDown treeLabel="Toggle Tree">
|
|
518
|
-
<div>Hidden content</div>
|
|
519
|
-
</TreeDropDown>
|
|
520
|
-
)
|
|
521
|
-
|
|
522
|
-
const header = screen.getByText('Toggle Tree')
|
|
523
|
-
|
|
524
|
-
// Initially collapsed
|
|
525
|
-
expect(screen.queryByText('Hidden content')).not.toBeVisible()
|
|
526
|
-
|
|
527
|
-
// Click to expand
|
|
528
|
-
fireEvent.click(header)
|
|
529
|
-
expect(screen.getByText('Hidden content')).toBeVisible()
|
|
530
|
-
|
|
531
|
-
// Click to collapse
|
|
532
|
-
fireEvent.click(header)
|
|
533
|
-
expect(screen.queryByText('Hidden content')).not.toBeVisible()
|
|
534
|
-
})
|
|
535
|
-
|
|
536
|
-
it('respects controlled open prop', () => {
|
|
537
|
-
const { rerender } = render(
|
|
538
|
-
<TreeDropDown treeLabel="Controlled" open={false}>
|
|
539
|
-
<div>Content</div>
|
|
540
|
-
</TreeDropDown>
|
|
541
|
-
)
|
|
542
|
-
|
|
543
|
-
expect(screen.queryByText('Content')).not.toBeVisible()
|
|
544
|
-
|
|
545
|
-
rerender(
|
|
546
|
-
<TreeDropDown treeLabel="Controlled" open={true}>
|
|
547
|
-
<div>Content</div>
|
|
548
|
-
</TreeDropDown>
|
|
549
|
-
)
|
|
550
|
-
|
|
551
|
-
expect(screen.getByText('Content')).toBeVisible()
|
|
552
|
-
})
|
|
553
|
-
})
|
|
554
|
-
```
|
|
555
|
-
|
|
556
|
-
### Testing Nested Trees
|
|
557
|
-
|
|
558
|
-
```typescript
|
|
559
|
-
import { render, screen, fireEvent } from '@testing-library/react'
|
|
560
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
561
|
-
|
|
562
|
-
test('nested trees work independently', () => {
|
|
563
|
-
render(
|
|
564
|
-
<TreeDropDown treeLabel="Parent">
|
|
565
|
-
<TreeDropDown treeLabel="Child">
|
|
566
|
-
<div>Grandchild</div>
|
|
567
|
-
</TreeDropDown>
|
|
568
|
-
</TreeDropDown>
|
|
569
|
-
)
|
|
570
|
-
|
|
571
|
-
// Expand parent
|
|
572
|
-
fireEvent.click(screen.getByText('Parent'))
|
|
573
|
-
expect(screen.getByText('Child')).toBeInTheDocument()
|
|
574
|
-
|
|
575
|
-
// Expand child
|
|
576
|
-
fireEvent.click(screen.getByText('Child'))
|
|
577
|
-
expect(screen.getByText('Grandchild')).toBeVisible()
|
|
578
|
-
})
|
|
579
|
-
```
|
|
580
|
-
|
|
581
|
-
## Accessibility
|
|
582
|
-
|
|
583
|
-
- **Keyboard Support**:
|
|
584
|
-
- Enter/Space: Toggle expansion
|
|
585
|
-
- Tab: Navigate between tree items
|
|
586
|
-
- Arrow keys: Navigate within tree (when properly configured)
|
|
587
|
-
- **ARIA Attributes** (add manually for best support):
|
|
588
|
-
```typescript
|
|
589
|
-
<TreeDropDown
|
|
590
|
-
treeLabel="Section"
|
|
591
|
-
role="treeitem"
|
|
592
|
-
aria-expanded={isOpen}
|
|
593
|
-
>
|
|
594
|
-
{/* content */}
|
|
595
|
-
</TreeDropDown>
|
|
596
|
-
```
|
|
597
|
-
- **Screen Readers**: Announce expansion state changes
|
|
598
|
-
- **Focus Management**: Visible focus outline on keyboard navigation
|
|
599
|
-
- **Reduced Motion**: Respects `prefers-reduced-motion` for animations
|
|
600
|
-
|
|
601
|
-
### Enhanced Accessibility Example
|
|
602
|
-
|
|
603
|
-
```typescript
|
|
604
|
-
import { TreeDropDown } from "@/components/TreeDropDown";
|
|
605
|
-
import { useState } from 'react'
|
|
606
|
-
|
|
607
|
-
function AccessibleTree() {
|
|
608
|
-
const [isOpen, setIsOpen] = useState(false)
|
|
609
|
-
|
|
610
|
-
return (
|
|
611
|
-
<TreeDropDown
|
|
612
|
-
treeLabel="Accessible Tree"
|
|
613
|
-
open={isOpen}
|
|
614
|
-
role="treeitem"
|
|
615
|
-
aria-expanded={isOpen}
|
|
616
|
-
aria-label="File tree navigation"
|
|
617
|
-
>
|
|
618
|
-
<div role="group">
|
|
619
|
-
<div role="treeitem" tabIndex={0}>
|
|
620
|
-
Item 1
|
|
621
|
-
</div>
|
|
622
|
-
<div role="treeitem" tabIndex={0}>
|
|
623
|
-
Item 2
|
|
624
|
-
</div>
|
|
625
|
-
</div>
|
|
626
|
-
</TreeDropDown>
|
|
627
|
-
)
|
|
628
|
-
}
|
|
629
|
-
```
|
|
630
|
-
|
|
631
|
-
## Performance
|
|
632
|
-
|
|
633
|
-
| Metric | Value |
|
|
634
|
-
|--------|-------|
|
|
635
|
-
| Bundle size (gzip) | ~1.8kb |
|
|
636
|
-
| Dependencies | class-variance-authority |
|
|
637
|
-
| First render | <3ms |
|
|
638
|
-
| Animation duration | 500ms |
|
|
639
|
-
| Tree-shakeable | ✅ |
|
|
640
|
-
|
|
641
|
-
### Performance Tips
|
|
642
|
-
|
|
643
|
-
1. **Avoid deeply nested structures**: Limit to 3-4 levels for best UX
|
|
644
|
-
```typescript
|
|
645
|
-
// Good: 2-3 levels
|
|
646
|
-
<TreeDropDown>
|
|
647
|
-
<TreeDropDown>
|
|
648
|
-
<div>Content</div>
|
|
649
|
-
</TreeDropDown>
|
|
650
|
-
</TreeDropDown>
|
|
651
|
-
```
|
|
652
|
-
|
|
653
|
-
2. **Memoize tree labels**: Use `useMemo` for complex labels
|
|
654
|
-
```typescript
|
|
655
|
-
const label = useMemo(() => (
|
|
656
|
-
<ComplexLabel data={data} />
|
|
657
|
-
), [data])
|
|
658
|
-
```
|
|
659
|
-
|
|
660
|
-
3. **Virtualize large lists**: Use react-window for 100+ items
|
|
661
|
-
```typescript
|
|
662
|
-
import { FixedSizeList } from 'react-window'
|
|
663
|
-
```
|
|
664
|
-
|
|
665
|
-
## Migration from Accordion
|
|
666
|
-
|
|
667
|
-
```diff
|
|
668
|
-
- import { Accordion } from 'other-library'
|
|
669
|
-
+ import { TreeDropDown } from "@/components/TreeDropDown";
|
|
670
|
-
|
|
671
|
-
- <Accordion title="Section">
|
|
672
|
-
+ <TreeDropDown treeLabel="Section">
|
|
673
|
-
<div>Content</div>
|
|
674
|
-
- </Accordion>
|
|
675
|
-
+ </TreeDropDown>
|
|
676
|
-
```
|
|
677
|
-
|
|
678
|
-
## Best Practices
|
|
679
|
-
|
|
680
|
-
1. **Use appropriate variants**: `default` for top-level, `secondary` for nested items
|
|
681
|
-
```typescript
|
|
682
|
-
<TreeDropDown variant="default">
|
|
683
|
-
<TreeDropDown variant="secondary">
|
|
684
|
-
{/* content */}
|
|
685
|
-
</TreeDropDown>
|
|
686
|
-
</TreeDropDown>
|
|
687
|
-
```
|
|
688
|
-
|
|
689
|
-
2. **Provide meaningful labels**: Use clear, descriptive text or components
|
|
690
|
-
```typescript
|
|
691
|
-
<TreeDropDown treeLabel="User Settings (5)">
|
|
692
|
-
{/* Not just "Settings" */}
|
|
693
|
-
</TreeDropDown>
|
|
694
|
-
```
|
|
695
|
-
|
|
696
|
-
3. **Limit nesting depth**: Keep hierarchies shallow (3-4 levels max)
|
|
697
|
-
```typescript
|
|
698
|
-
// Avoid more than 3-4 levels of nesting
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
4. **Control state when needed**: Use `open` prop for coordinated behavior
|
|
702
|
-
```typescript
|
|
703
|
-
<TreeDropDown open={expandAll}>
|
|
704
|
-
{/* Synchronized expansion */}
|
|
705
|
-
</TreeDropDown>
|
|
706
|
-
```
|
|
707
|
-
|
|
708
|
-
5. **Add icons for context**: Help users understand content types
|
|
709
|
-
```typescript
|
|
710
|
-
<TreeDropDown
|
|
711
|
-
treeLabel={
|
|
712
|
-
<>
|
|
713
|
-
<i className="ri-folder-line" />
|
|
714
|
-
Folder Name
|
|
715
|
-
</>
|
|
716
|
-
}
|
|
717
|
-
>
|
|
718
|
-
```
|
|
719
|
-
|
|
720
|
-
6. **Style children appropriately**: Use `childrenContainerClassName` for custom styling
|
|
721
|
-
```typescript
|
|
722
|
-
<TreeDropDown childrenContainerClassName="space-y-2 p-2">
|
|
723
|
-
{/* Well-spaced children */}
|
|
724
|
-
</TreeDropDown>
|
|
725
|
-
```
|
|
726
|
-
|
|
727
|
-
7. **Handle empty states**: Show message when no children exist
|
|
728
|
-
```typescript
|
|
729
|
-
<TreeDropDown treeLabel="Empty Folder">
|
|
730
|
-
{children.length === 0 ? (
|
|
731
|
-
<div className="text-gray-500">No items</div>
|
|
732
|
-
) : children}
|
|
733
|
-
</TreeDropDown>
|
|
734
|
-
```
|
|
735
|
-
|
|
736
|
-
## Related Components
|
|
737
|
-
|
|
738
|
-
- [TreeSubLayout](./tree-sub-layout.md) - Complete tree navigation layout
|
|
739
|
-
- [ActionsGroup](./actions-group.md) - Group related tree actions
|
|
740
|
-
- [ScrollArea](./scroll-area.md) - Wrap long tree content
|