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,882 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Component Composition
|
|
3
|
-
description: Learn how to compose TORCH Glare components to build complex, production-ready user interfaces.
|
|
4
|
-
category: Tutorial
|
|
5
|
-
difficulty: Advanced
|
|
6
|
-
duration: 40 minutes
|
|
7
|
-
tags: [composition, patterns, architecture, complex-ui, best-practices]
|
|
8
|
-
related:
|
|
9
|
-
- Getting Started
|
|
10
|
-
- Building Your First Form
|
|
11
|
-
- Theming Basics
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Component Composition
|
|
15
|
-
|
|
16
|
-
Master the art of composing TORCH Glare components to build sophisticated, maintainable user interfaces.
|
|
17
|
-
|
|
18
|
-
## What You'll Learn
|
|
19
|
-
|
|
20
|
-
- Component composition patterns
|
|
21
|
-
- Building complex layouts
|
|
22
|
-
- Creating reusable composite components
|
|
23
|
-
- Managing component state across compositions
|
|
24
|
-
- Best practices for scalable architecture
|
|
25
|
-
|
|
26
|
-
## Prerequisites
|
|
27
|
-
|
|
28
|
-
- Completed previous tutorials
|
|
29
|
-
- Understanding of React composition patterns
|
|
30
|
-
- Experience with component props and state
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Understanding Composition
|
|
35
|
-
|
|
36
|
-
Composition is combining simple components to create more complex ones. Think of it as building with LEGO blocks.
|
|
37
|
-
|
|
38
|
-
### Basic Composition Pattern
|
|
39
|
-
|
|
40
|
-
```tsx
|
|
41
|
-
// Simple components
|
|
42
|
-
<Button />
|
|
43
|
-
<Input />
|
|
44
|
-
<Badge />
|
|
45
|
-
|
|
46
|
-
// Composed into a complex component
|
|
47
|
-
<SearchBar>
|
|
48
|
-
<Input />
|
|
49
|
-
<Button />
|
|
50
|
-
<Badge />
|
|
51
|
-
</SearchBar>
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## Pattern 1: Form Composition
|
|
57
|
-
|
|
58
|
-
### Basic Contact Form
|
|
59
|
-
|
|
60
|
-
```tsx
|
|
61
|
-
'use client';
|
|
62
|
-
|
|
63
|
-
import { Button } from "@/components/Button";
|
|
64
|
-
import { FieldHint } from "@/components/FieldHint";
|
|
65
|
-
import { LabelField } from "@/components/LabelField";
|
|
66
|
-
import { TextArea } from "@/components/TextArea";
|
|
67
|
-
import { toast } from "@/components/Toast";
|
|
68
|
-
import { useState } from 'react';
|
|
69
|
-
|
|
70
|
-
export default function ContactForm() {
|
|
71
|
-
const [formData, setFormData] = useState({
|
|
72
|
-
name: '',
|
|
73
|
-
email: '',
|
|
74
|
-
subject: '',
|
|
75
|
-
message: '',
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const handleSubmit = (e: React.FormEvent) => {
|
|
79
|
-
e.preventDefault();
|
|
80
|
-
toast.success('Message sent successfully!');
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<form onSubmit={handleSubmit} className="space-y-4">
|
|
85
|
-
<LabelField
|
|
86
|
-
theme="light"
|
|
87
|
-
label="Name"
|
|
88
|
-
requiredLabel="*"
|
|
89
|
-
value={formData.name}
|
|
90
|
-
onChange={(e) => setFormData({...formData, name: e.target.value})}
|
|
91
|
-
/>
|
|
92
|
-
|
|
93
|
-
<LabelField
|
|
94
|
-
theme="light"
|
|
95
|
-
label="Email"
|
|
96
|
-
requiredLabel="*"
|
|
97
|
-
type="email"
|
|
98
|
-
value={formData.email}
|
|
99
|
-
onChange={(e) => setFormData({...formData, email: e.target.value})}
|
|
100
|
-
/>
|
|
101
|
-
|
|
102
|
-
<LabelField
|
|
103
|
-
theme="light"
|
|
104
|
-
label="Subject"
|
|
105
|
-
value={formData.subject}
|
|
106
|
-
onChange={(e) => setFormData({...formData, subject: e.target.value})}
|
|
107
|
-
/>
|
|
108
|
-
|
|
109
|
-
<div>
|
|
110
|
-
<label className="typography-body-medium-semibold text-content-presentation-global-primary block mb-2">
|
|
111
|
-
Message *
|
|
112
|
-
</label>
|
|
113
|
-
<TextArea
|
|
114
|
-
theme="light"
|
|
115
|
-
value={formData.message}
|
|
116
|
-
onChange={(e) => setFormData({...formData, message: e.target.value})}
|
|
117
|
-
placeholder="Your message..."
|
|
118
|
-
rows={5}
|
|
119
|
-
/>
|
|
120
|
-
</div>
|
|
121
|
-
|
|
122
|
-
<Button theme="light" variant="PrimeStyle" type="submit" className="w-full">
|
|
123
|
-
Send Message
|
|
124
|
-
</Button>
|
|
125
|
-
</form>
|
|
126
|
-
);
|
|
127
|
-
}
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
---
|
|
131
|
-
|
|
132
|
-
## Pattern 2: Card with Actions
|
|
133
|
-
|
|
134
|
-
### Feature Card Component
|
|
135
|
-
|
|
136
|
-
```tsx
|
|
137
|
-
import { Badge } from "@/components/Badge";
|
|
138
|
-
import { Button } from "@/components/Button";
|
|
139
|
-
|
|
140
|
-
interface FeatureCardProps {
|
|
141
|
-
title: string;
|
|
142
|
-
description: string;
|
|
143
|
-
badge?: string;
|
|
144
|
-
onLearnMore?: () => void;
|
|
145
|
-
onGetStarted?: () => void;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export default function FeatureCard({
|
|
149
|
-
title,
|
|
150
|
-
description,
|
|
151
|
-
badge,
|
|
152
|
-
onLearnMore,
|
|
153
|
-
onGetStarted,
|
|
154
|
-
}: FeatureCardProps) {
|
|
155
|
-
return (
|
|
156
|
-
<div className="
|
|
157
|
-
bg-background-presentation-form-base
|
|
158
|
-
border border-border-presentation-global-primary
|
|
159
|
-
rounded-lg p-6
|
|
160
|
-
hover:border-border-presentation-action-hover
|
|
161
|
-
transition-all duration-200
|
|
162
|
-
">
|
|
163
|
-
{/* Header with Badge */}
|
|
164
|
-
<div className="flex items-start justify-between mb-4">
|
|
165
|
-
<h3 className="typography-headers-large-bold text-content-presentation-global-primary">
|
|
166
|
-
{title}
|
|
167
|
-
</h3>
|
|
168
|
-
{badge && (
|
|
169
|
-
<Badge theme="light" color="gray">
|
|
170
|
-
{badge}
|
|
171
|
-
</Badge>
|
|
172
|
-
)}
|
|
173
|
-
</div>
|
|
174
|
-
|
|
175
|
-
{/* Description */}
|
|
176
|
-
<p className="typography-body-medium-regular text-content-presentation-global-secondary mb-6">
|
|
177
|
-
{description}
|
|
178
|
-
</p>
|
|
179
|
-
|
|
180
|
-
{/* Actions */}
|
|
181
|
-
<div className="flex gap-2">
|
|
182
|
-
{onLearnMore && (
|
|
183
|
-
<Button
|
|
184
|
-
theme="light"
|
|
185
|
-
variant="BorderStyle"
|
|
186
|
-
size="S"
|
|
187
|
-
onClick={onLearnMore}
|
|
188
|
-
>
|
|
189
|
-
Learn More
|
|
190
|
-
</Button>
|
|
191
|
-
)}
|
|
192
|
-
{onGetStarted && (
|
|
193
|
-
<Button
|
|
194
|
-
theme="light"
|
|
195
|
-
variant="PrimeStyle"
|
|
196
|
-
size="S"
|
|
197
|
-
onClick={onGetStarted}
|
|
198
|
-
>
|
|
199
|
-
Get Started
|
|
200
|
-
</Button>
|
|
201
|
-
)}
|
|
202
|
-
</div>
|
|
203
|
-
</div>
|
|
204
|
-
);
|
|
205
|
-
}
|
|
206
|
-
```
|
|
207
|
-
|
|
208
|
-
### Usage
|
|
209
|
-
|
|
210
|
-
```tsx
|
|
211
|
-
<FeatureCard
|
|
212
|
-
title="Advanced Analytics"
|
|
213
|
-
description="Get insights into your data with real-time analytics and reporting."
|
|
214
|
-
badge="Pro"
|
|
215
|
-
onLearnMore={() => console.log('Learn more')}
|
|
216
|
-
onGetStarted={() => console.log('Get started')}
|
|
217
|
-
/>
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## Pattern 3: List with Actions
|
|
223
|
-
|
|
224
|
-
### User List Component
|
|
225
|
-
|
|
226
|
-
```tsx
|
|
227
|
-
'use client';
|
|
228
|
-
|
|
229
|
-
import { Avatar } from "@/components/Avatar";
|
|
230
|
-
import { Badge } from "@/components/Badge";
|
|
231
|
-
import { Button } from "@/components/Button";
|
|
232
|
-
import { Popover, PopoverTrigger, PopoverContent } from "@/components/Popover";
|
|
233
|
-
|
|
234
|
-
interface User {
|
|
235
|
-
id: string;
|
|
236
|
-
name: string;
|
|
237
|
-
email: string;
|
|
238
|
-
avatar?: string;
|
|
239
|
-
role: 'admin' | 'user' | 'guest';
|
|
240
|
-
status: 'active' | 'inactive';
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
interface UserListProps {
|
|
244
|
-
users: User[];
|
|
245
|
-
onEdit?: (user: User) => void;
|
|
246
|
-
onDelete?: (user: User) => void;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
export default function UserList({ users, onEdit, onDelete }: UserListProps) {
|
|
250
|
-
const getRoleBadgeVariant = (role: User['role']) => {
|
|
251
|
-
const variants = {
|
|
252
|
-
admin: 'PrimeStyle',
|
|
253
|
-
user: 'SecondStyle',
|
|
254
|
-
guest: 'ContStyle',
|
|
255
|
-
};
|
|
256
|
-
return variants[role];
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
return (
|
|
260
|
-
<div className="
|
|
261
|
-
bg-background-presentation-form-base
|
|
262
|
-
border border-border-presentation-global-primary
|
|
263
|
-
rounded-lg overflow-hidden
|
|
264
|
-
">
|
|
265
|
-
{/* Header */}
|
|
266
|
-
<div className="bg-background-presentation-form-header p-4 border-b border-border-presentation-global-primary">
|
|
267
|
-
<h3 className="typography-headers-medium-bold text-content-presentation-global-primary">
|
|
268
|
-
Team Members
|
|
269
|
-
</h3>
|
|
270
|
-
</div>
|
|
271
|
-
|
|
272
|
-
{/* User List */}
|
|
273
|
-
<div className="divide-y divide-border-presentation-global-primary">
|
|
274
|
-
{users.map((user) => (
|
|
275
|
-
<div
|
|
276
|
-
key={user.id}
|
|
277
|
-
className="
|
|
278
|
-
p-4 flex items-center justify-between
|
|
279
|
-
hover:bg-background-presentation-table-row-hover
|
|
280
|
-
transition-colors
|
|
281
|
-
"
|
|
282
|
-
>
|
|
283
|
-
{/* User Info */}
|
|
284
|
-
<div className="flex items-center gap-3">
|
|
285
|
-
<Avatar
|
|
286
|
-
theme="light"
|
|
287
|
-
src={user.avatar}
|
|
288
|
-
alt={user.name}
|
|
289
|
-
size="M"
|
|
290
|
-
/>
|
|
291
|
-
<div>
|
|
292
|
-
<p className="typography-body-medium-semibold text-content-presentation-global-primary">
|
|
293
|
-
{user.name}
|
|
294
|
-
</p>
|
|
295
|
-
<p className="typography-body-small-regular text-content-presentation-global-secondary">
|
|
296
|
-
{user.email}
|
|
297
|
-
</p>
|
|
298
|
-
</div>
|
|
299
|
-
</div>
|
|
300
|
-
|
|
301
|
-
{/* Badges and Actions */}
|
|
302
|
-
<div className="flex items-center gap-2">
|
|
303
|
-
<Badge
|
|
304
|
-
theme="light"
|
|
305
|
-
variant={getRoleBadgeVariant(user.role) as any}
|
|
306
|
-
>
|
|
307
|
-
{user.role}
|
|
308
|
-
</Badge>
|
|
309
|
-
|
|
310
|
-
{user.status === 'active' ? (
|
|
311
|
-
<span className="
|
|
312
|
-
px-2 py-1 rounded
|
|
313
|
-
bg-background-presentation-badge-green
|
|
314
|
-
text-content-presentation-badge-green
|
|
315
|
-
typography-labels-small-semibold
|
|
316
|
-
">
|
|
317
|
-
Active
|
|
318
|
-
</span>
|
|
319
|
-
) : (
|
|
320
|
-
<span className="
|
|
321
|
-
px-2 py-1 rounded
|
|
322
|
-
bg-background-presentation-badge-gray
|
|
323
|
-
text-content-presentation-badge-gray
|
|
324
|
-
typography-labels-small-semibold
|
|
325
|
-
">
|
|
326
|
-
Inactive
|
|
327
|
-
</span>
|
|
328
|
-
)}
|
|
329
|
-
|
|
330
|
-
{/* Actions Menu */}
|
|
331
|
-
<Popover>
|
|
332
|
-
<PopoverTrigger asChild>
|
|
333
|
-
<Button
|
|
334
|
-
theme="light"
|
|
335
|
-
variant="PrimeContStyle"
|
|
336
|
-
buttonType="icon"
|
|
337
|
-
size="S"
|
|
338
|
-
>
|
|
339
|
-
<i className="ri-more-2-fill"></i>
|
|
340
|
-
</Button>
|
|
341
|
-
</PopoverTrigger>
|
|
342
|
-
<PopoverContent theme="light" align="end">
|
|
343
|
-
<div className="flex flex-col gap-1">
|
|
344
|
-
{onEdit && (
|
|
345
|
-
<button
|
|
346
|
-
onClick={() => onEdit(user)}
|
|
347
|
-
className="
|
|
348
|
-
px-3 py-2 text-left rounded
|
|
349
|
-
hover:bg-background-presentation-action-hover
|
|
350
|
-
typography-body-small-regular
|
|
351
|
-
"
|
|
352
|
-
>
|
|
353
|
-
Edit
|
|
354
|
-
</button>
|
|
355
|
-
)}
|
|
356
|
-
{onDelete && (
|
|
357
|
-
<button
|
|
358
|
-
onClick={() => onDelete(user)}
|
|
359
|
-
className="
|
|
360
|
-
px-3 py-2 text-left rounded
|
|
361
|
-
hover:bg-background-presentation-state-negative-primary
|
|
362
|
-
text-content-presentation-state-negative
|
|
363
|
-
typography-body-small-regular
|
|
364
|
-
"
|
|
365
|
-
>
|
|
366
|
-
Delete
|
|
367
|
-
</button>
|
|
368
|
-
)}
|
|
369
|
-
</div>
|
|
370
|
-
</PopoverContent>
|
|
371
|
-
</Popover>
|
|
372
|
-
</div>
|
|
373
|
-
</div>
|
|
374
|
-
))}
|
|
375
|
-
</div>
|
|
376
|
-
</div>
|
|
377
|
-
);
|
|
378
|
-
}
|
|
379
|
-
```
|
|
380
|
-
|
|
381
|
-
---
|
|
382
|
-
|
|
383
|
-
## Pattern 4: Modal with Form
|
|
384
|
-
|
|
385
|
-
### Create Project Modal
|
|
386
|
-
|
|
387
|
-
```tsx
|
|
388
|
-
'use client';
|
|
389
|
-
|
|
390
|
-
import { useState } from 'react';
|
|
391
|
-
import { Button } from "@/components/Button";
|
|
392
|
-
import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription } from "@/components/Dialog";
|
|
393
|
-
import { LabelField } from "@/components/LabelField";
|
|
394
|
-
import { Select, SelectItem } from "@/components/Select";
|
|
395
|
-
import { TextArea } from "@/components/TextArea";
|
|
396
|
-
import { toast } from "@/components/Toast";
|
|
397
|
-
|
|
398
|
-
export default function CreateProjectModal() {
|
|
399
|
-
const [open, setOpen] = useState(false);
|
|
400
|
-
const [formData, setFormData] = useState({
|
|
401
|
-
name: '',
|
|
402
|
-
description: '',
|
|
403
|
-
category: '',
|
|
404
|
-
});
|
|
405
|
-
|
|
406
|
-
const handleSubmit = (e: React.FormEvent) => {
|
|
407
|
-
e.preventDefault();
|
|
408
|
-
toast.success('Project created successfully!');
|
|
409
|
-
setOpen(false);
|
|
410
|
-
// Reset form
|
|
411
|
-
setFormData({ name: '', description: '', category: '' });
|
|
412
|
-
};
|
|
413
|
-
|
|
414
|
-
return (
|
|
415
|
-
<Dialog open={open} onOpenChange={setOpen}>
|
|
416
|
-
<DialogTrigger asChild>
|
|
417
|
-
<Button theme="light" variant="PrimeStyle">
|
|
418
|
-
Create Project
|
|
419
|
-
</Button>
|
|
420
|
-
</DialogTrigger>
|
|
421
|
-
|
|
422
|
-
<DialogContent theme="light">
|
|
423
|
-
<DialogHeader>
|
|
424
|
-
<DialogTitle>Create New Project</DialogTitle>
|
|
425
|
-
<DialogDescription>
|
|
426
|
-
Fill in the details to create a new project
|
|
427
|
-
</DialogDescription>
|
|
428
|
-
</DialogHeader>
|
|
429
|
-
|
|
430
|
-
<form onSubmit={handleSubmit} className="space-y-4 mt-4">
|
|
431
|
-
<LabelField
|
|
432
|
-
theme="light"
|
|
433
|
-
label="Project Name"
|
|
434
|
-
requiredLabel="*"
|
|
435
|
-
value={formData.name}
|
|
436
|
-
onChange={(e) => setFormData({...formData, name: e.target.value})}
|
|
437
|
-
placeholder="My Awesome Project"
|
|
438
|
-
/>
|
|
439
|
-
|
|
440
|
-
<div>
|
|
441
|
-
<label className="typography-body-medium-semibold text-content-presentation-global-primary block mb-2">
|
|
442
|
-
Description *
|
|
443
|
-
</label>
|
|
444
|
-
<TextArea
|
|
445
|
-
theme="light"
|
|
446
|
-
value={formData.description}
|
|
447
|
-
onChange={(e) => setFormData({...formData, description: e.target.value})}
|
|
448
|
-
placeholder="Describe your project..."
|
|
449
|
-
rows={4}
|
|
450
|
-
/>
|
|
451
|
-
</div>
|
|
452
|
-
|
|
453
|
-
<div>
|
|
454
|
-
<label className="typography-body-medium-semibold text-content-presentation-global-primary block mb-2">
|
|
455
|
-
Category *
|
|
456
|
-
</label>
|
|
457
|
-
<Select
|
|
458
|
-
theme="light"
|
|
459
|
-
value={formData.category}
|
|
460
|
-
onValueChange={(value) => setFormData({...formData, category: value})}
|
|
461
|
-
>
|
|
462
|
-
<SelectItem value="web">Web Development</SelectItem>
|
|
463
|
-
<SelectItem value="mobile">Mobile App</SelectItem>
|
|
464
|
-
<SelectItem value="design">Design</SelectItem>
|
|
465
|
-
<SelectItem value="other">Other</SelectItem>
|
|
466
|
-
</Select>
|
|
467
|
-
</div>
|
|
468
|
-
|
|
469
|
-
<div className="flex gap-2 justify-end pt-4">
|
|
470
|
-
<Button
|
|
471
|
-
theme="light"
|
|
472
|
-
variant="BorderStyle"
|
|
473
|
-
type="button"
|
|
474
|
-
onClick={() => setOpen(false)}
|
|
475
|
-
>
|
|
476
|
-
Cancel
|
|
477
|
-
</Button>
|
|
478
|
-
<Button theme="light" variant="PrimeStyle" type="submit">
|
|
479
|
-
Create Project
|
|
480
|
-
</Button>
|
|
481
|
-
</div>
|
|
482
|
-
</form>
|
|
483
|
-
</DialogContent>
|
|
484
|
-
</Dialog>
|
|
485
|
-
);
|
|
486
|
-
}
|
|
487
|
-
```
|
|
488
|
-
|
|
489
|
-
---
|
|
490
|
-
|
|
491
|
-
## Pattern 5: Data Table with Filters
|
|
492
|
-
|
|
493
|
-
### Advanced Table Component
|
|
494
|
-
|
|
495
|
-
```tsx
|
|
496
|
-
'use client';
|
|
497
|
-
|
|
498
|
-
import { useState } from 'react';
|
|
499
|
-
import { Badge } from "@/components/Badge";
|
|
500
|
-
import { Button } from "@/components/Button";
|
|
501
|
-
import { InputField } from "@/components/InputField";
|
|
502
|
-
import { Select, SelectItem } from "@/components/Select";
|
|
503
|
-
import { Table } from "@/components/Table";
|
|
504
|
-
|
|
505
|
-
interface TableRow {
|
|
506
|
-
id: string;
|
|
507
|
-
name: string;
|
|
508
|
-
status: 'active' | 'pending' | 'inactive';
|
|
509
|
-
date: string;
|
|
510
|
-
revenue: number;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
export default function DataTableWithFilters() {
|
|
514
|
-
const [searchQuery, setSearchQuery] = useState('');
|
|
515
|
-
const [statusFilter, setStatusFilter] = useState('all');
|
|
516
|
-
|
|
517
|
-
const data: TableRow[] = [
|
|
518
|
-
{ id: '1', name: 'Project Alpha', status: 'active', date: '2024-01-15', revenue: 15000 },
|
|
519
|
-
{ id: '2', name: 'Project Beta', status: 'pending', date: '2024-01-20', revenue: 8000 },
|
|
520
|
-
{ id: '3', name: 'Project Gamma', status: 'inactive', date: '2024-01-25', revenue: 0 },
|
|
521
|
-
];
|
|
522
|
-
|
|
523
|
-
const filteredData = data.filter((row) => {
|
|
524
|
-
const matchesSearch = row.name.toLowerCase().includes(searchQuery.toLowerCase());
|
|
525
|
-
const matchesStatus = statusFilter === 'all' || row.status === statusFilter;
|
|
526
|
-
return matchesSearch && matchesStatus;
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
const getStatusBadge = (status: TableRow['status']) => {
|
|
530
|
-
const variants = {
|
|
531
|
-
active: 'bg-background-presentation-badge-green text-content-presentation-badge-green',
|
|
532
|
-
pending: 'bg-background-presentation-badge-yellow text-content-presentation-badge-yellow',
|
|
533
|
-
inactive: 'bg-background-presentation-badge-gray text-content-presentation-badge-gray',
|
|
534
|
-
};
|
|
535
|
-
return variants[status];
|
|
536
|
-
};
|
|
537
|
-
|
|
538
|
-
return (
|
|
539
|
-
<div className="space-y-4">
|
|
540
|
-
{/* Filters */}
|
|
541
|
-
<div className="
|
|
542
|
-
bg-background-presentation-form-base
|
|
543
|
-
border border-border-presentation-global-primary
|
|
544
|
-
rounded-lg p-4
|
|
545
|
-
">
|
|
546
|
-
<div className="flex gap-4">
|
|
547
|
-
<div className="flex-1">
|
|
548
|
-
<InputField
|
|
549
|
-
theme="light"
|
|
550
|
-
placeholder="Search projects..."
|
|
551
|
-
value={searchQuery}
|
|
552
|
-
onChange={(e) => setSearchQuery(e.target.value)}
|
|
553
|
-
/>
|
|
554
|
-
</div>
|
|
555
|
-
<div className="w-48">
|
|
556
|
-
<Select
|
|
557
|
-
theme="light"
|
|
558
|
-
value={statusFilter}
|
|
559
|
-
onValueChange={setStatusFilter}
|
|
560
|
-
>
|
|
561
|
-
<SelectItem value="all">All Status</SelectItem>
|
|
562
|
-
<SelectItem value="active">Active</SelectItem>
|
|
563
|
-
<SelectItem value="pending">Pending</SelectItem>
|
|
564
|
-
<SelectItem value="inactive">Inactive</SelectItem>
|
|
565
|
-
</Select>
|
|
566
|
-
</div>
|
|
567
|
-
</div>
|
|
568
|
-
</div>
|
|
569
|
-
|
|
570
|
-
{/* Table */}
|
|
571
|
-
<div className="
|
|
572
|
-
bg-background-presentation-form-base
|
|
573
|
-
border border-border-presentation-global-primary
|
|
574
|
-
rounded-lg overflow-hidden
|
|
575
|
-
">
|
|
576
|
-
<table className="w-full">
|
|
577
|
-
<thead className="bg-background-presentation-form-header">
|
|
578
|
-
<tr>
|
|
579
|
-
<th className="px-4 py-3 text-left typography-body-small-semibold text-content-presentation-global-primary">
|
|
580
|
-
Project
|
|
581
|
-
</th>
|
|
582
|
-
<th className="px-4 py-3 text-left typography-body-small-semibold text-content-presentation-global-primary">
|
|
583
|
-
Status
|
|
584
|
-
</th>
|
|
585
|
-
<th className="px-4 py-3 text-left typography-body-small-semibold text-content-presentation-global-primary">
|
|
586
|
-
Date
|
|
587
|
-
</th>
|
|
588
|
-
<th className="px-4 py-3 text-right typography-body-small-semibold text-content-presentation-global-primary">
|
|
589
|
-
Revenue
|
|
590
|
-
</th>
|
|
591
|
-
<th className="px-4 py-3 text-right typography-body-small-semibold text-content-presentation-global-primary">
|
|
592
|
-
Actions
|
|
593
|
-
</th>
|
|
594
|
-
</tr>
|
|
595
|
-
</thead>
|
|
596
|
-
<tbody className="divide-y divide-border-presentation-global-primary">
|
|
597
|
-
{filteredData.map((row) => (
|
|
598
|
-
<tr
|
|
599
|
-
key={row.id}
|
|
600
|
-
className="hover:bg-background-presentation-table-row-hover"
|
|
601
|
-
>
|
|
602
|
-
<td className="px-4 py-3 typography-body-medium-regular text-content-presentation-global-primary">
|
|
603
|
-
{row.name}
|
|
604
|
-
</td>
|
|
605
|
-
<td className="px-4 py-3">
|
|
606
|
-
<span className={`px-2 py-1 rounded typography-labels-small-semibold ${getStatusBadge(row.status)}`}>
|
|
607
|
-
{row.status}
|
|
608
|
-
</span>
|
|
609
|
-
</td>
|
|
610
|
-
<td className="px-4 py-3 typography-body-small-regular text-content-presentation-global-secondary">
|
|
611
|
-
{row.date}
|
|
612
|
-
</td>
|
|
613
|
-
<td className="px-4 py-3 text-right typography-body-medium-semibold text-content-presentation-global-primary">
|
|
614
|
-
${row.revenue.toLocaleString()}
|
|
615
|
-
</td>
|
|
616
|
-
<td className="px-4 py-3 text-right">
|
|
617
|
-
<Button theme="light" variant="PrimeContStyle" size="S">
|
|
618
|
-
View
|
|
619
|
-
</Button>
|
|
620
|
-
</td>
|
|
621
|
-
</tr>
|
|
622
|
-
))}
|
|
623
|
-
</tbody>
|
|
624
|
-
</table>
|
|
625
|
-
|
|
626
|
-
{filteredData.length === 0 && (
|
|
627
|
-
<div className="p-8 text-center">
|
|
628
|
-
<p className="typography-body-medium-regular text-content-presentation-global-secondary">
|
|
629
|
-
No projects found
|
|
630
|
-
</p>
|
|
631
|
-
</div>
|
|
632
|
-
)}
|
|
633
|
-
</div>
|
|
634
|
-
</div>
|
|
635
|
-
);
|
|
636
|
-
}
|
|
637
|
-
```
|
|
638
|
-
|
|
639
|
-
---
|
|
640
|
-
|
|
641
|
-
## Pattern 6: Dashboard Layout
|
|
642
|
-
|
|
643
|
-
### Complete Dashboard
|
|
644
|
-
|
|
645
|
-
```tsx
|
|
646
|
-
'use client';
|
|
647
|
-
|
|
648
|
-
import { Avatar } from "@/components/Avatar";
|
|
649
|
-
import { Badge } from "@/components/Badge";
|
|
650
|
-
import { Button } from "@/components/Button";
|
|
651
|
-
import { useTheme } from "@/providers/ThemeProvider";
|
|
652
|
-
import { useState } from 'react';
|
|
653
|
-
|
|
654
|
-
export default function Dashboard() {
|
|
655
|
-
const { theme, updateTheme } = useTheme();
|
|
656
|
-
const [sidebarOpen, setSidebarOpen] = useState(true);
|
|
657
|
-
|
|
658
|
-
return (
|
|
659
|
-
<div className="min-h-screen bg-background-system-body-primary">
|
|
660
|
-
{/* Sidebar */}
|
|
661
|
-
<aside
|
|
662
|
-
className={`
|
|
663
|
-
fixed top-0 left-0 h-full
|
|
664
|
-
bg-background-presentation-form-base
|
|
665
|
-
border-r border-border-presentation-global-primary
|
|
666
|
-
transition-all duration-300
|
|
667
|
-
${sidebarOpen ? 'w-64' : 'w-0'}
|
|
668
|
-
overflow-hidden
|
|
669
|
-
`}
|
|
670
|
-
>
|
|
671
|
-
<div className="p-4">
|
|
672
|
-
<h2 className="typography-headers-large-bold text-content-presentation-global-primary mb-6">
|
|
673
|
-
Dashboard
|
|
674
|
-
</h2>
|
|
675
|
-
|
|
676
|
-
<nav className="space-y-2">
|
|
677
|
-
{['Overview', 'Projects', 'Team', 'Settings'].map((item) => (
|
|
678
|
-
<button
|
|
679
|
-
key={item}
|
|
680
|
-
className="
|
|
681
|
-
w-full px-4 py-2 text-left rounded-lg
|
|
682
|
-
hover:bg-background-presentation-action-hover
|
|
683
|
-
typography-body-medium-regular
|
|
684
|
-
text-content-presentation-global-primary
|
|
685
|
-
"
|
|
686
|
-
>
|
|
687
|
-
{item}
|
|
688
|
-
</button>
|
|
689
|
-
))}
|
|
690
|
-
</nav>
|
|
691
|
-
</div>
|
|
692
|
-
</aside>
|
|
693
|
-
|
|
694
|
-
{/* Main Content */}
|
|
695
|
-
<main
|
|
696
|
-
className={`
|
|
697
|
-
transition-all duration-300
|
|
698
|
-
${sidebarOpen ? 'ml-64' : 'ml-0'}
|
|
699
|
-
`}
|
|
700
|
-
>
|
|
701
|
-
{/* Header */}
|
|
702
|
-
<header className="
|
|
703
|
-
bg-background-presentation-form-base
|
|
704
|
-
border-b border-border-presentation-global-primary
|
|
705
|
-
p-4
|
|
706
|
-
">
|
|
707
|
-
<div className="flex justify-between items-center">
|
|
708
|
-
<div className="flex items-center gap-4">
|
|
709
|
-
<Button
|
|
710
|
-
theme={theme as any}
|
|
711
|
-
variant="PrimeContStyle"
|
|
712
|
-
buttonType="icon"
|
|
713
|
-
onClick={() => setSidebarOpen(!sidebarOpen)}
|
|
714
|
-
>
|
|
715
|
-
<i className="ri-menu-line"></i>
|
|
716
|
-
</Button>
|
|
717
|
-
<h1 className="typography-display-medium-bold">
|
|
718
|
-
Overview
|
|
719
|
-
</h1>
|
|
720
|
-
</div>
|
|
721
|
-
|
|
722
|
-
<div className="flex items-center gap-4">
|
|
723
|
-
<Button
|
|
724
|
-
theme={theme as any}
|
|
725
|
-
variant="PrimeContStyle"
|
|
726
|
-
buttonType="icon"
|
|
727
|
-
onClick={() => updateTheme(theme === 'light' ? 'dark' : 'light')}
|
|
728
|
-
>
|
|
729
|
-
{theme === 'light' ? '🌙' : '☀️'}
|
|
730
|
-
</Button>
|
|
731
|
-
|
|
732
|
-
<Avatar
|
|
733
|
-
theme={theme as any}
|
|
734
|
-
src="/avatar.jpg"
|
|
735
|
-
alt="User"
|
|
736
|
-
size="M"
|
|
737
|
-
/>
|
|
738
|
-
</div>
|
|
739
|
-
</div>
|
|
740
|
-
</header>
|
|
741
|
-
|
|
742
|
-
{/* Content */}
|
|
743
|
-
<div className="p-6">
|
|
744
|
-
{/* Stats Grid */}
|
|
745
|
-
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6">
|
|
746
|
-
{[
|
|
747
|
-
{ label: 'Total Revenue', value: '$45,678', change: '+12%' },
|
|
748
|
-
{ label: 'Active Users', value: '1,234', change: '+8%' },
|
|
749
|
-
{ label: 'Projects', value: '42', change: '+3%' },
|
|
750
|
-
].map((stat, index) => (
|
|
751
|
-
<div
|
|
752
|
-
key={index}
|
|
753
|
-
className="
|
|
754
|
-
bg-background-presentation-form-base
|
|
755
|
-
border border-border-presentation-global-primary
|
|
756
|
-
rounded-lg p-6
|
|
757
|
-
"
|
|
758
|
-
>
|
|
759
|
-
<p className="typography-labels-small-regular text-content-presentation-global-secondary mb-2">
|
|
760
|
-
{stat.label}
|
|
761
|
-
</p>
|
|
762
|
-
<p className="typography-display-small-bold text-content-presentation-global-primary mb-2">
|
|
763
|
-
{stat.value}
|
|
764
|
-
</p>
|
|
765
|
-
<Badge theme={theme as any} color="green">
|
|
766
|
-
{stat.change}
|
|
767
|
-
</Badge>
|
|
768
|
-
</div>
|
|
769
|
-
))}
|
|
770
|
-
</div>
|
|
771
|
-
|
|
772
|
-
{/* Recent Activity */}
|
|
773
|
-
<div className="
|
|
774
|
-
bg-background-presentation-form-base
|
|
775
|
-
border border-border-presentation-global-primary
|
|
776
|
-
rounded-lg p-6
|
|
777
|
-
">
|
|
778
|
-
<h3 className="typography-headers-medium-bold mb-4">
|
|
779
|
-
Recent Activity
|
|
780
|
-
</h3>
|
|
781
|
-
<p className="typography-body-medium-regular text-content-presentation-global-secondary">
|
|
782
|
-
Activity feed would go here...
|
|
783
|
-
</p>
|
|
784
|
-
</div>
|
|
785
|
-
</div>
|
|
786
|
-
</main>
|
|
787
|
-
</div>
|
|
788
|
-
);
|
|
789
|
-
}
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
---
|
|
793
|
-
|
|
794
|
-
## Best Practices
|
|
795
|
-
|
|
796
|
-
### 1. Keep Components Focused
|
|
797
|
-
|
|
798
|
-
```tsx
|
|
799
|
-
// ✓ Good - Each component has one responsibility
|
|
800
|
-
function UserCard({ user }) { /* ... */ }
|
|
801
|
-
function UserActions({ user, onEdit, onDelete }) { /* ... */ }
|
|
802
|
-
|
|
803
|
-
// ✗ Bad - Too many responsibilities
|
|
804
|
-
function UserEverything({ user, onEdit, onDelete, onShare, onArchive }) { /* ... */ }
|
|
805
|
-
```
|
|
806
|
-
|
|
807
|
-
### 2. Use Composition Over Props
|
|
808
|
-
|
|
809
|
-
```tsx
|
|
810
|
-
// ✓ Good - Flexible composition
|
|
811
|
-
<Card>
|
|
812
|
-
<CardHeader>
|
|
813
|
-
<Title>Hello</Title>
|
|
814
|
-
<Badge>New</Badge>
|
|
815
|
-
</CardHeader>
|
|
816
|
-
<CardContent>
|
|
817
|
-
<p>Content</p>
|
|
818
|
-
</CardContent>
|
|
819
|
-
</Card>
|
|
820
|
-
|
|
821
|
-
// ✗ Less flexible - Everything via props
|
|
822
|
-
<Card title="Hello" badge="New" content={<p>Content</p>} />
|
|
823
|
-
```
|
|
824
|
-
|
|
825
|
-
### 3. Extract Reusable Patterns
|
|
826
|
-
|
|
827
|
-
```tsx
|
|
828
|
-
// Extract common patterns into custom components
|
|
829
|
-
function FormSection({ title, children }) {
|
|
830
|
-
return (
|
|
831
|
-
<div className="space-y-4">
|
|
832
|
-
<h3 className="typography-headers-medium-bold">{title}</h3>
|
|
833
|
-
{children}
|
|
834
|
-
</div>
|
|
835
|
-
);
|
|
836
|
-
}
|
|
837
|
-
```
|
|
838
|
-
|
|
839
|
-
### 4. Use TypeScript for Props
|
|
840
|
-
|
|
841
|
-
```tsx
|
|
842
|
-
interface CardProps {
|
|
843
|
-
title: string;
|
|
844
|
-
children: React.ReactNode;
|
|
845
|
-
actions?: React.ReactNode;
|
|
846
|
-
}
|
|
847
|
-
|
|
848
|
-
function Card({ title, children, actions }: CardProps) {
|
|
849
|
-
// ...
|
|
850
|
-
}
|
|
851
|
-
```
|
|
852
|
-
|
|
853
|
-
### 5. Keep State Close to Usage
|
|
854
|
-
|
|
855
|
-
```tsx
|
|
856
|
-
// ✓ Good - State in component that uses it
|
|
857
|
-
function SearchableList() {
|
|
858
|
-
const [search, setSearch] = useState('');
|
|
859
|
-
// Use search here
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
// ✗ Bad - State too high up
|
|
863
|
-
function App() {
|
|
864
|
-
const [search, setSearch] = useState('');
|
|
865
|
-
return <SearchableList search={search} />
|
|
866
|
-
}
|
|
867
|
-
```
|
|
868
|
-
|
|
869
|
-
---
|
|
870
|
-
|
|
871
|
-
## Next Steps
|
|
872
|
-
|
|
873
|
-
You now understand component composition! Continue learning:
|
|
874
|
-
|
|
875
|
-
1. **[Component Documentation](../components/)** - Explore all components
|
|
876
|
-
2. **[Hooks Reference](../reference/hooks.md)** - Custom hooks for common patterns
|
|
877
|
-
3. **[Best Practices Guide](../how-to/guides.md)** - Advanced patterns
|
|
878
|
-
|
|
879
|
-
## Additional Resources
|
|
880
|
-
|
|
881
|
-
- [React Composition Patterns](https://reactjs.org/docs/composition-vs-inheritance.html)
|
|
882
|
-
- [Component Design Patterns](https://www.patterns.dev/)
|