@shohojdhara/atomix 0.3.14 → 0.3.15
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/CHANGELOG.md +20 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +43 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +67 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +203 -90
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +3 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +43 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +67 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +1 -1
- package/dist/charts.js +86 -57
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +136 -112
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +2 -5
- package/dist/forms.js +140 -128
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +136 -112
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +9 -61
- package/dist/index.esm.js +237 -286
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +250 -299
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +23 -8
- package/scripts/atomix-cli.js +170 -73
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +161 -0
- package/scripts/cli/component-generator.js +253 -299
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/interactive-init.js +46 -5
- package/scripts/cli/template-manager.js +0 -2
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +148 -126
- package/scripts/cli/templates/index.js +23 -16
- package/scripts/cli/templates/project-templates.js +151 -23
- package/scripts/cli/templates/react-templates.js +280 -210
- package/scripts/cli/templates/scss-templates.js +90 -91
- package/scripts/cli/templates/testing-templates.js +206 -27
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/types-templates.js +70 -56
- package/scripts/cli/theme-bridge.js +8 -2
- package/scripts/cli/token-manager.js +318 -206
- package/scripts/cli/utils.js +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +369 -870
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +2 -2
- package/src/components/AtomixGlass/shader-utils.ts +5 -0
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -35
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +213 -1
- package/src/components/Badge/Badge.stories.tsx +121 -362
- package/src/components/Block/Block.stories.tsx +21 -12
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
- package/src/components/Button/Button.stories.tsx +463 -1126
- package/src/components/Button/Button.test.tsx +107 -0
- package/src/components/Button/Button.tsx +46 -50
- package/src/components/Button/ButtonGroup.stories.tsx +373 -217
- package/src/components/Callout/Callout.stories.tsx +289 -634
- package/src/components/Card/Card.stories.tsx +248 -68
- package/src/components/Chart/Chart.stories.tsx +150 -8
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
- package/src/components/Countdown/Countdown.stories.tsx +115 -8
- package/src/components/DataTable/DataTable.stories.tsx +346 -146
- package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
- package/src/components/Dropdown/Dropdown.stories.tsx +153 -33
- package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
- package/src/components/Footer/Footer.stories.tsx +392 -328
- package/src/components/Form/Checkbox.stories.tsx +140 -6
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +87 -51
- package/src/components/Form/Form.stories.tsx +119 -20
- package/src/components/Form/FormGroup.stories.tsx +127 -4
- package/src/components/Form/Radio.stories.tsx +140 -5
- package/src/components/Form/Select.stories.tsx +140 -8
- package/src/components/Form/Textarea.stories.tsx +149 -6
- package/src/components/Hero/Hero.stories.tsx +333 -32
- package/src/components/List/List.stories.tsx +141 -3
- package/src/components/Modal/Modal.stories.tsx +181 -42
- package/src/components/Popover/Popover.stories.tsx +448 -98
- package/src/components/Progress/Progress.stories.tsx +167 -5
- package/src/components/River/River.stories.tsx +1 -1
- package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
- package/src/components/Spinner/Spinner.stories.tsx +102 -8
- package/src/components/Steps/Steps.stories.tsx +172 -43
- package/src/components/Tabs/Tabs.stories.tsx +136 -10
- package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +126 -39
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
- package/src/components/Upload/Upload.stories.tsx +113 -24
- package/src/lib/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +193 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/useAtomixGlass.ts +28 -56
- package/src/lib/composables/useChartExport.ts +2 -7
- package/src/lib/composables/useDataTable.ts +46 -29
- package/src/lib/constants/components.ts +9 -32
- package/src/lib/theme/devtools/CLI.ts +1 -1
- package/src/lib/types/components.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/csv.ts +17 -0
- package/src/lib/utils/dataTableExport.ts +1 -10
- package/src/styles/01-settings/_index.scss +2 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- package/src/styles/01-settings/_settings.typography.scss +5 -5
- package/src/styles/02-tools/_tools.utility-api.scss +14 -0
- package/src/styles/06-components/_components.accordion.scss +56 -14
- package/src/styles/06-components/_components.checkbox.scss +23 -17
- package/src/styles/99-utilities/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.scss +3 -1
- package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/templates-original-backup.js +0 -1655
- package/scripts/cli/templates_backup.js +0 -684
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- package/src/lib/composables/useCheckbox.ts +0 -70
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
2
3
|
import React, { useState } from 'react';
|
|
3
4
|
import { ThemeColor } from '../../lib/types/components';
|
|
4
5
|
import { Icon } from '../Icon';
|
|
@@ -12,8 +13,72 @@ const meta = {
|
|
|
12
13
|
layout: 'centered',
|
|
13
14
|
docs: {
|
|
14
15
|
description: {
|
|
15
|
-
component:
|
|
16
|
-
|
|
16
|
+
component: `
|
|
17
|
+
# Dropdown
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
Dropdown provides a toggleable menu that appears relative to a trigger element. It supports multiple placement options, click or hover triggers, and can include dividers, headers, and icons. Dropdowns are ideal for navigation menus, action menus, or any context where options need to be revealed on demand.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Multiple placement options (top, bottom, left, right with start/end variations)
|
|
26
|
+
- Click or hover trigger modes
|
|
27
|
+
- Color variants
|
|
28
|
+
- Glass morphism effect
|
|
29
|
+
- Customizable dimensions
|
|
30
|
+
- Auto-close behaviors
|
|
31
|
+
- Rich content support (headers, dividers, icons)
|
|
32
|
+
|
|
33
|
+
## Accessibility
|
|
34
|
+
|
|
35
|
+
- Keyboard support: Navigate with arrow keys, activate with Enter/Space
|
|
36
|
+
- Screen reader: Menu items and structure announced properly
|
|
37
|
+
- ARIA support: Proper roles and properties for dropdown components
|
|
38
|
+
- Focus management: Maintains focus within the dropdown menu
|
|
39
|
+
|
|
40
|
+
## Usage Examples
|
|
41
|
+
|
|
42
|
+
### Basic Usage
|
|
43
|
+
|
|
44
|
+
\`\`\`tsx
|
|
45
|
+
<Dropdown
|
|
46
|
+
trigger="click"
|
|
47
|
+
placement="bottom-start"
|
|
48
|
+
children={<button>Dropdown</button>}
|
|
49
|
+
menu={<div>Menu content</div>}
|
|
50
|
+
/>
|
|
51
|
+
\`\`\`
|
|
52
|
+
|
|
53
|
+
### With Glass Effect
|
|
54
|
+
|
|
55
|
+
\`\`\`tsx
|
|
56
|
+
<Dropdown
|
|
57
|
+
trigger="click"
|
|
58
|
+
placement="bottom-start"
|
|
59
|
+
glass={true}
|
|
60
|
+
children={<button>Dropdown</button>}
|
|
61
|
+
menu={<div>Menu content</div>}
|
|
62
|
+
/>
|
|
63
|
+
\`\`\`
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### Props
|
|
68
|
+
|
|
69
|
+
| Prop | Type | Default | Description |
|
|
70
|
+
| ---- | ---- | ------- | ----------- |
|
|
71
|
+
| placement | Placement | 'bottom-start' | The placement of the dropdown menu relative to the trigger element |
|
|
72
|
+
| trigger | 'click' \\| 'hover' | 'click' | How the dropdown is triggered - by click or hover |
|
|
73
|
+
| variant | ThemeColor | 'secondary' | The color variant of the dropdown |
|
|
74
|
+
| minWidth | string | - | Minimum width of the dropdown menu |
|
|
75
|
+
| maxHeight | string | - | Maximum height of the dropdown menu |
|
|
76
|
+
| closeOnClickOutside | boolean | true | Whether to close the dropdown when clicking outside |
|
|
77
|
+
| closeOnEscape | boolean | true | Whether to close the dropdown when pressing the Escape key |
|
|
78
|
+
| glass | boolean | false | Enable glass morphism effect |
|
|
79
|
+
| isOpen | boolean | - | Controlled open state of the dropdown |
|
|
80
|
+
| onOpenChange | (open: boolean) => void | - | Callback when open state changes |
|
|
81
|
+
`,
|
|
17
82
|
},
|
|
18
83
|
},
|
|
19
84
|
},
|
|
@@ -32,36 +97,80 @@ const meta = {
|
|
|
32
97
|
'right-end',
|
|
33
98
|
],
|
|
34
99
|
description: 'The placement of the dropdown menu relative to the trigger element',
|
|
100
|
+
table: {
|
|
101
|
+
type: { summary: 'Placement' },
|
|
102
|
+
defaultValue: { summary: 'bottom-start' },
|
|
103
|
+
},
|
|
35
104
|
},
|
|
36
105
|
trigger: {
|
|
37
106
|
control: { type: 'radio' },
|
|
38
107
|
options: ['click', 'hover'],
|
|
39
108
|
description: 'How the dropdown is triggered - by click or hover',
|
|
109
|
+
table: {
|
|
110
|
+
type: { summary: '"click" | "hover"' },
|
|
111
|
+
defaultValue: { summary: 'click' },
|
|
112
|
+
},
|
|
40
113
|
},
|
|
41
114
|
variant: {
|
|
42
115
|
control: { type: 'select' },
|
|
43
116
|
options: THEME_COLORS,
|
|
44
117
|
description: 'The color variant of the dropdown',
|
|
118
|
+
table: {
|
|
119
|
+
type: { summary: 'ThemeColor' },
|
|
120
|
+
defaultValue: { summary: 'secondary' },
|
|
121
|
+
},
|
|
45
122
|
},
|
|
46
123
|
minWidth: {
|
|
47
124
|
control: 'text',
|
|
48
125
|
description: 'Minimum width of the dropdown menu',
|
|
126
|
+
table: {
|
|
127
|
+
type: { summary: 'string' },
|
|
128
|
+
defaultValue: { summary: '-' },
|
|
129
|
+
},
|
|
49
130
|
},
|
|
50
131
|
maxHeight: {
|
|
51
132
|
control: 'text',
|
|
52
133
|
description: 'Maximum height of the dropdown menu',
|
|
134
|
+
table: {
|
|
135
|
+
type: { summary: 'string' },
|
|
136
|
+
defaultValue: { summary: '-' },
|
|
137
|
+
},
|
|
53
138
|
},
|
|
54
139
|
closeOnClickOutside: {
|
|
55
140
|
control: 'boolean',
|
|
56
141
|
description: 'Whether to close the dropdown when clicking outside',
|
|
142
|
+
table: {
|
|
143
|
+
type: { summary: 'boolean' },
|
|
144
|
+
defaultValue: { summary: true },
|
|
145
|
+
},
|
|
57
146
|
},
|
|
58
147
|
closeOnEscape: {
|
|
59
148
|
control: 'boolean',
|
|
60
149
|
description: 'Whether to close the dropdown when pressing the Escape key',
|
|
150
|
+
table: {
|
|
151
|
+
type: { summary: 'boolean' },
|
|
152
|
+
defaultValue: { summary: true },
|
|
153
|
+
},
|
|
61
154
|
},
|
|
62
155
|
glass: {
|
|
63
156
|
control: 'boolean',
|
|
64
157
|
description: 'Enable glass morphism effect',
|
|
158
|
+
table: {
|
|
159
|
+
type: { summary: 'boolean' },
|
|
160
|
+
defaultValue: { summary: false },
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
isOpen: {
|
|
164
|
+
control: 'boolean',
|
|
165
|
+
description: 'Controlled open state of the dropdown',
|
|
166
|
+
table: {
|
|
167
|
+
type: { summary: 'boolean' },
|
|
168
|
+
defaultValue: { summary: '-' },
|
|
169
|
+
},
|
|
170
|
+
},
|
|
171
|
+
onOpenChange: {
|
|
172
|
+
action: 'open state changed',
|
|
173
|
+
description: 'Callback when open state changes',
|
|
65
174
|
},
|
|
66
175
|
},
|
|
67
176
|
} satisfies Meta<typeof Dropdown>;
|
|
@@ -85,10 +194,7 @@ const InteractiveDropdown = (args: React.ComponentProps<typeof Dropdown>) => {
|
|
|
85
194
|
);
|
|
86
195
|
};
|
|
87
196
|
|
|
88
|
-
|
|
89
|
-
* Basic dropdown example with default settings
|
|
90
|
-
*/
|
|
91
|
-
export const Default: Story = {
|
|
197
|
+
export const BasicUsage: Story = {
|
|
92
198
|
args: {
|
|
93
199
|
trigger: 'click',
|
|
94
200
|
placement: 'bottom-start',
|
|
@@ -99,35 +205,49 @@ export const Default: Story = {
|
|
|
99
205
|
),
|
|
100
206
|
menu: (
|
|
101
207
|
<>
|
|
102
|
-
<
|
|
103
|
-
<
|
|
104
|
-
<DropdownItem>
|
|
208
|
+
<DropdownHeader>Dropdown Header</DropdownHeader>
|
|
209
|
+
<DropdownDivider />
|
|
210
|
+
<DropdownItem>Option 1</DropdownItem>
|
|
211
|
+
<DropdownItem>Option 2</DropdownItem>
|
|
212
|
+
<DropdownItem>Option 3</DropdownItem>
|
|
213
|
+
<DropdownDivider />
|
|
214
|
+
<DropdownItem disabled>Disabled Option</DropdownItem>
|
|
105
215
|
</>
|
|
106
216
|
),
|
|
107
217
|
},
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
export const ClickTrigger: Story = {
|
|
115
|
-
args: {
|
|
116
|
-
...Default.args,
|
|
117
|
-
trigger: 'click',
|
|
218
|
+
parameters: {
|
|
219
|
+
docs: {
|
|
220
|
+
description: {
|
|
221
|
+
story: 'Basic dropdown with default settings and menu items.',
|
|
222
|
+
},
|
|
223
|
+
},
|
|
118
224
|
},
|
|
119
|
-
render: args => <InteractiveDropdown {...args} />,
|
|
120
225
|
};
|
|
121
226
|
|
|
122
|
-
/**
|
|
123
|
-
* Dropdown that opens on hover
|
|
124
|
-
*/
|
|
125
227
|
export const HoverTrigger: Story = {
|
|
126
228
|
args: {
|
|
127
|
-
...Default.args,
|
|
128
229
|
trigger: 'hover',
|
|
230
|
+
placement: 'bottom-start',
|
|
231
|
+
children: (
|
|
232
|
+
<button className="c-btn c-btn--secondary">
|
|
233
|
+
Hover Dropdown <Icon name="CaretDown" className="c-dropdown__toggle-icon" size="sm" />
|
|
234
|
+
</button>
|
|
235
|
+
),
|
|
236
|
+
menu: (
|
|
237
|
+
<>
|
|
238
|
+
<DropdownItem>Hover Option 1</DropdownItem>
|
|
239
|
+
<DropdownItem>Hover Option 2</DropdownItem>
|
|
240
|
+
<DropdownItem>Hover Option 3</DropdownItem>
|
|
241
|
+
</>
|
|
242
|
+
),
|
|
243
|
+
},
|
|
244
|
+
parameters: {
|
|
245
|
+
docs: {
|
|
246
|
+
description: {
|
|
247
|
+
story: 'Dropdown that opens on hover instead of click.',
|
|
248
|
+
},
|
|
249
|
+
},
|
|
129
250
|
},
|
|
130
|
-
render: args => <InteractiveDropdown {...args} />,
|
|
131
251
|
};
|
|
132
252
|
|
|
133
253
|
/**
|
|
@@ -135,7 +255,7 @@ export const HoverTrigger: Story = {
|
|
|
135
255
|
*/
|
|
136
256
|
export const WithIcons: Story = {
|
|
137
257
|
args: {
|
|
138
|
-
...
|
|
258
|
+
...BasicUsage.args,
|
|
139
259
|
menu: (
|
|
140
260
|
<>
|
|
141
261
|
<DropdownItem icon={<Icon name="House" size="sm" />}>Home</DropdownItem>
|
|
@@ -153,7 +273,7 @@ export const WithIcons: Story = {
|
|
|
153
273
|
*/
|
|
154
274
|
export const WithLinks: Story = {
|
|
155
275
|
args: {
|
|
156
|
-
...
|
|
276
|
+
...BasicUsage.args,
|
|
157
277
|
menu: (
|
|
158
278
|
<>
|
|
159
279
|
<DropdownItem href="#home">Home</DropdownItem>
|
|
@@ -171,7 +291,7 @@ export const WithLinks: Story = {
|
|
|
171
291
|
*/
|
|
172
292
|
export const WithHeader: Story = {
|
|
173
293
|
args: {
|
|
174
|
-
...
|
|
294
|
+
...BasicUsage.args,
|
|
175
295
|
menu: (
|
|
176
296
|
<>
|
|
177
297
|
<DropdownHeader>Account Options</DropdownHeader>
|
|
@@ -192,7 +312,7 @@ export const WithHeader: Story = {
|
|
|
192
312
|
*/
|
|
193
313
|
export const ActiveItem: Story = {
|
|
194
314
|
args: {
|
|
195
|
-
...
|
|
315
|
+
...BasicUsage.args,
|
|
196
316
|
menu: (
|
|
197
317
|
<>
|
|
198
318
|
<DropdownItem active>Active Item</DropdownItem>
|
|
@@ -209,7 +329,7 @@ export const ActiveItem: Story = {
|
|
|
209
329
|
*/
|
|
210
330
|
export const DisabledItem: Story = {
|
|
211
331
|
args: {
|
|
212
|
-
...
|
|
332
|
+
...BasicUsage.args,
|
|
213
333
|
menu: (
|
|
214
334
|
<>
|
|
215
335
|
<DropdownItem>Regular Item</DropdownItem>
|
|
@@ -358,7 +478,7 @@ export const AllVariants: Story = {
|
|
|
358
478
|
*/
|
|
359
479
|
export const GlassDropdown: Story = {
|
|
360
480
|
args: {
|
|
361
|
-
...
|
|
481
|
+
...BasicUsage.args,
|
|
362
482
|
glass: true,
|
|
363
483
|
},
|
|
364
484
|
render: args => <InteractiveDropdown {...args} />,
|
|
@@ -382,7 +502,7 @@ export const GlassDropdown: Story = {
|
|
|
382
502
|
*/
|
|
383
503
|
export const GlassDropdownCustom: Story = {
|
|
384
504
|
args: {
|
|
385
|
-
...
|
|
505
|
+
...BasicUsage.args,
|
|
386
506
|
glass: {
|
|
387
507
|
displacementScale: 80,
|
|
388
508
|
blurAmount: 2,
|
|
@@ -499,4 +619,4 @@ export const GlassAllVariants: Story = {
|
|
|
499
619
|
</div>
|
|
500
620
|
);
|
|
501
621
|
},
|
|
502
|
-
};
|
|
622
|
+
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { fn } from '@storybook/test';
|
|
2
3
|
import { useEffect, useState } from 'react';
|
|
3
4
|
import React from 'react';
|
|
4
5
|
import { Button } from '../Button/Button';
|
|
@@ -12,8 +13,76 @@ const meta = {
|
|
|
12
13
|
layout: 'fullscreen',
|
|
13
14
|
docs: {
|
|
14
15
|
description: {
|
|
15
|
-
component:
|
|
16
|
-
|
|
16
|
+
component: `
|
|
17
|
+
# EdgePanel
|
|
18
|
+
|
|
19
|
+
## Overview
|
|
20
|
+
|
|
21
|
+
EdgePanel is a versatile sliding panel that can appear from any edge of the screen. Commonly used for mobile navigation, filters, chat windows, or contextual actions.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- Multiple position options (start, end, top, bottom)
|
|
26
|
+
- Different animation modes (slide, push, none)
|
|
27
|
+
- Backdrop with optional click-to-close
|
|
28
|
+
- Keyboard support (Escape to close)
|
|
29
|
+
- Title support
|
|
30
|
+
- Controlled and uncontrolled usage
|
|
31
|
+
- Accessible design
|
|
32
|
+
- Responsive behavior
|
|
33
|
+
|
|
34
|
+
## Accessibility
|
|
35
|
+
|
|
36
|
+
- Keyboard support: Close with Escape key
|
|
37
|
+
- Screen reader: Panel content and purpose announced appropriately
|
|
38
|
+
- ARIA support: Proper roles and properties for panel components
|
|
39
|
+
- Focus management: Traps focus within the panel when open
|
|
40
|
+
|
|
41
|
+
## Usage Examples
|
|
42
|
+
|
|
43
|
+
### Basic Usage
|
|
44
|
+
|
|
45
|
+
\`\`\`tsx
|
|
46
|
+
<EdgePanel
|
|
47
|
+
isOpen={isOpen}
|
|
48
|
+
onOpenChange={setIsOpen}
|
|
49
|
+
position="start"
|
|
50
|
+
title="Panel Title"
|
|
51
|
+
>
|
|
52
|
+
<p>Panel content</p>
|
|
53
|
+
</EdgePanel>
|
|
54
|
+
\`\`\`
|
|
55
|
+
|
|
56
|
+
### With Configuration
|
|
57
|
+
|
|
58
|
+
\`\`\`tsx
|
|
59
|
+
<EdgePanel
|
|
60
|
+
position="end"
|
|
61
|
+
mode="slide"
|
|
62
|
+
backdrop={true}
|
|
63
|
+
closeOnBackdropClick={true}
|
|
64
|
+
closeOnEscape={true}
|
|
65
|
+
title="Configured Panel"
|
|
66
|
+
>
|
|
67
|
+
<p>Panel content</p>
|
|
68
|
+
</EdgePanel>
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
## API Reference
|
|
72
|
+
|
|
73
|
+
### Props
|
|
74
|
+
|
|
75
|
+
| Prop | Type | Default | Description |
|
|
76
|
+
| ---- | ---- | ------- | ----------- |
|
|
77
|
+
| position | 'start' \\| 'end' \\| 'top' \\| 'bottom' | 'start' | Position of the edge panel |
|
|
78
|
+
| mode | 'slide' \\| 'push' \\| 'none' | 'slide' | Animation mode of the panel |
|
|
79
|
+
| backdrop | boolean | true | Show backdrop behind the panel |
|
|
80
|
+
| closeOnBackdropClick | boolean | true | Close the panel when clicking on backdrop |
|
|
81
|
+
| closeOnEscape | boolean | true | Close the panel when pressing Escape key |
|
|
82
|
+
| title | string | - | Panel title |
|
|
83
|
+
| isOpen | boolean | false | Whether the panel is open (controlled component) |
|
|
84
|
+
| onOpenChange | (open: boolean) => void | - | Callback when open state changes |
|
|
85
|
+
`,
|
|
17
86
|
},
|
|
18
87
|
},
|
|
19
88
|
},
|
|
@@ -23,31 +92,63 @@ const meta = {
|
|
|
23
92
|
control: { type: 'select' },
|
|
24
93
|
options: ['start', 'end', 'top', 'bottom'],
|
|
25
94
|
description: 'Position of the edge panel',
|
|
95
|
+
table: {
|
|
96
|
+
type: { summary: '"start" | "end" | "top" | "bottom"' },
|
|
97
|
+
defaultValue: { summary: 'start' },
|
|
98
|
+
},
|
|
26
99
|
},
|
|
27
100
|
mode: {
|
|
28
101
|
control: { type: 'select' },
|
|
29
102
|
options: ['slide', 'push', 'none'],
|
|
30
103
|
description: 'Animation mode of the panel',
|
|
104
|
+
table: {
|
|
105
|
+
type: { summary: '"slide" | "push" | "none"' },
|
|
106
|
+
defaultValue: { summary: 'slide' },
|
|
107
|
+
},
|
|
31
108
|
},
|
|
32
109
|
backdrop: {
|
|
33
110
|
control: 'boolean',
|
|
34
111
|
description: 'Show backdrop behind the panel',
|
|
112
|
+
table: {
|
|
113
|
+
type: { summary: 'boolean' },
|
|
114
|
+
defaultValue: { summary: true },
|
|
115
|
+
},
|
|
35
116
|
},
|
|
36
117
|
closeOnBackdropClick: {
|
|
37
118
|
control: 'boolean',
|
|
38
119
|
description: 'Close the panel when clicking on backdrop',
|
|
120
|
+
table: {
|
|
121
|
+
type: { summary: 'boolean' },
|
|
122
|
+
defaultValue: { summary: true },
|
|
123
|
+
},
|
|
39
124
|
},
|
|
40
125
|
closeOnEscape: {
|
|
41
126
|
control: 'boolean',
|
|
42
127
|
description: 'Close the panel when pressing Escape key',
|
|
128
|
+
table: {
|
|
129
|
+
type: { summary: 'boolean' },
|
|
130
|
+
defaultValue: { summary: true },
|
|
131
|
+
},
|
|
43
132
|
},
|
|
44
133
|
title: {
|
|
45
134
|
control: 'text',
|
|
46
135
|
description: 'Panel title',
|
|
136
|
+
table: {
|
|
137
|
+
type: { summary: 'string' },
|
|
138
|
+
defaultValue: { summary: '-' },
|
|
139
|
+
},
|
|
47
140
|
},
|
|
48
141
|
isOpen: {
|
|
49
142
|
control: 'boolean',
|
|
50
143
|
description: 'Whether the panel is open (controlled component)',
|
|
144
|
+
table: {
|
|
145
|
+
type: { summary: 'boolean' },
|
|
146
|
+
defaultValue: { summary: false },
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
onOpenChange: {
|
|
150
|
+
action: 'open state changed',
|
|
151
|
+
description: 'Callback when open state changes',
|
|
51
152
|
},
|
|
52
153
|
},
|
|
53
154
|
decorators: [
|
|
@@ -101,35 +202,143 @@ const DemoPanelContent = ({
|
|
|
101
202
|
<strong>Mode:</strong> {mode}
|
|
102
203
|
</li>
|
|
103
204
|
<li className="u-mb-1">
|
|
104
|
-
<strong>Backdrop:</strong> {backdrop ? '
|
|
205
|
+
<strong>Backdrop:</strong> {backdrop ? 'Yes' : 'No'}
|
|
105
206
|
</li>
|
|
106
207
|
<li className="u-mb-1">
|
|
107
|
-
<strong>Close on backdrop:</strong> {closeOnBackdropClick ? 'Yes' : 'No'}
|
|
208
|
+
<strong>Close on backdrop click:</strong> {closeOnBackdropClick ? 'Yes' : 'No'}
|
|
108
209
|
</li>
|
|
109
|
-
<li>
|
|
110
|
-
<strong>Close on
|
|
210
|
+
<li className="u-mb-1">
|
|
211
|
+
<strong>Close on escape:</strong> {closeOnEscape ? 'Yes' : 'No'}
|
|
111
212
|
</li>
|
|
112
213
|
</ul>
|
|
113
214
|
</div>
|
|
114
215
|
|
|
115
|
-
<p className="u-mb-3">
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
</li>
|
|
129
|
-
</ul>
|
|
216
|
+
<p className="u-mb-3">
|
|
217
|
+
You can put any content inside the Edge Panel. This could be navigation links, filter options,
|
|
218
|
+
notifications, or any other UI elements that need to slide in from the edge.
|
|
219
|
+
</p>
|
|
220
|
+
|
|
221
|
+
<div className="u-flex u-gap-2">
|
|
222
|
+
<Button variant="primary" size="sm">
|
|
223
|
+
Primary Action
|
|
224
|
+
</Button>
|
|
225
|
+
<Button variant="secondary" size="sm">
|
|
226
|
+
Secondary
|
|
227
|
+
</Button>
|
|
228
|
+
</div>
|
|
130
229
|
</>
|
|
131
230
|
);
|
|
132
231
|
|
|
232
|
+
export const BasicUsage: Story = {
|
|
233
|
+
render: (args) => {
|
|
234
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
235
|
+
|
|
236
|
+
return (
|
|
237
|
+
<>
|
|
238
|
+
<Button onClick={() => setIsOpen(true)}>Open Edge Panel</Button>
|
|
239
|
+
<EdgePanel
|
|
240
|
+
{...args}
|
|
241
|
+
isOpen={isOpen}
|
|
242
|
+
onOpenChange={setIsOpen}
|
|
243
|
+
title="Basic Edge Panel"
|
|
244
|
+
>
|
|
245
|
+
<DemoPanelContent {...args} />
|
|
246
|
+
</EdgePanel>
|
|
247
|
+
</>
|
|
248
|
+
);
|
|
249
|
+
},
|
|
250
|
+
args: {
|
|
251
|
+
position: 'start',
|
|
252
|
+
mode: 'slide',
|
|
253
|
+
backdrop: true,
|
|
254
|
+
closeOnBackdropClick: true,
|
|
255
|
+
closeOnEscape: true,
|
|
256
|
+
},
|
|
257
|
+
parameters: {
|
|
258
|
+
docs: {
|
|
259
|
+
description: {
|
|
260
|
+
story: 'Basic Edge Panel with default configuration.',
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
export const AllPositions: Story = {
|
|
267
|
+
render: () => {
|
|
268
|
+
const [position, setPosition] = useState<'start' | 'end' | 'top' | 'bottom'>('start');
|
|
269
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<>
|
|
273
|
+
<div className="u-flex u-gap-2 u-flex-wrap">
|
|
274
|
+
{(['start', 'end', 'top', 'bottom'] as const).map((pos) => (
|
|
275
|
+
<Button
|
|
276
|
+
key={pos}
|
|
277
|
+
variant={position === pos ? 'primary' : 'secondary'}
|
|
278
|
+
onClick={() => {
|
|
279
|
+
setPosition(pos);
|
|
280
|
+
setIsOpen(true);
|
|
281
|
+
}}
|
|
282
|
+
>
|
|
283
|
+
{pos.charAt(0).toUpperCase() + pos.slice(1)} Panel
|
|
284
|
+
</Button>
|
|
285
|
+
))}
|
|
286
|
+
</div>
|
|
287
|
+
|
|
288
|
+
<EdgePanel
|
|
289
|
+
position={position}
|
|
290
|
+
isOpen={isOpen}
|
|
291
|
+
onOpenChange={setIsOpen}
|
|
292
|
+
title={`${position} Edge Panel`}
|
|
293
|
+
>
|
|
294
|
+
<DemoPanelContent position={position} />
|
|
295
|
+
</EdgePanel>
|
|
296
|
+
</>
|
|
297
|
+
);
|
|
298
|
+
},
|
|
299
|
+
parameters: {
|
|
300
|
+
docs: {
|
|
301
|
+
description: {
|
|
302
|
+
story: 'Edge Panel in all available positions.',
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
export const WithSlideMode: Story = {
|
|
309
|
+
render: (args) => {
|
|
310
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
311
|
+
|
|
312
|
+
return (
|
|
313
|
+
<>
|
|
314
|
+
<Button onClick={() => setIsOpen(true)}>Open Slide Mode Panel</Button>
|
|
315
|
+
<EdgePanel
|
|
316
|
+
{...args}
|
|
317
|
+
isOpen={isOpen}
|
|
318
|
+
onOpenChange={setIsOpen}
|
|
319
|
+
title="Slide Mode Panel"
|
|
320
|
+
>
|
|
321
|
+
<DemoPanelContent {...args} />
|
|
322
|
+
</EdgePanel>
|
|
323
|
+
</>
|
|
324
|
+
);
|
|
325
|
+
},
|
|
326
|
+
args: {
|
|
327
|
+
position: 'start',
|
|
328
|
+
mode: 'slide',
|
|
329
|
+
backdrop: true,
|
|
330
|
+
closeOnBackdropClick: true,
|
|
331
|
+
closeOnEscape: true,
|
|
332
|
+
},
|
|
333
|
+
parameters: {
|
|
334
|
+
docs: {
|
|
335
|
+
description: {
|
|
336
|
+
story: 'Edge Panel with slide animation mode.',
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
};
|
|
341
|
+
|
|
133
342
|
// Controller component to demonstrate the EdgePanel
|
|
134
343
|
const EdgePanelController = ({
|
|
135
344
|
position,
|