@shohojdhara/atomix 0.3.12 → 0.3.14
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 +19 -0
- package/README.md +2 -0
- package/dist/atomix.css +101 -88
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +5 -15258
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +1 -1
- package/dist/charts.js +17 -19
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +41 -11
- package/dist/core.js +55 -41
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +28 -11
- package/dist/forms.js +25 -24
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +32 -25
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +122 -46
- package/dist/index.esm.js +865 -200
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +870 -204
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +27 -2
- package/dist/theme.js +721 -108
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
- package/scripts/atomix-cli.js +610 -1111
- package/scripts/cli/component-generator.js +610 -0
- package/scripts/cli/documentation-sync.js +542 -0
- package/scripts/cli/interactive-init.js +84 -288
- package/scripts/cli/mappings.js +211 -0
- package/scripts/cli/migration-tools.js +95 -288
- package/scripts/cli/template-manager.js +107 -0
- package/scripts/cli/templates/README.md +123 -0
- package/scripts/cli/templates/composable-templates.js +149 -0
- package/scripts/cli/templates/config-templates.js +126 -0
- package/scripts/cli/templates/index.js +95 -0
- package/scripts/cli/templates/project-templates.js +214 -0
- package/scripts/cli/templates/react-templates.js +261 -0
- package/scripts/cli/templates/scss-templates.js +156 -0
- package/scripts/cli/templates/storybook-templates.js +236 -0
- package/scripts/cli/templates/testing-templates.js +45 -0
- package/scripts/cli/templates/token-templates.js +447 -0
- package/scripts/cli/templates/types-templates.js +133 -0
- package/scripts/cli/templates-original-backup.js +1655 -0
- package/scripts/cli/templates.js +35 -0
- package/scripts/cli/templates_backup.js +684 -0
- package/scripts/cli/theme-bridge.js +20 -14
- package/scripts/cli/token-manager.js +150 -77
- package/scripts/cli/utils.js +37 -25
- package/src/components/Accordion/Accordion.stories.tsx +5 -5
- package/src/components/Accordion/Accordion.test.tsx +57 -0
- package/src/components/Accordion/Accordion.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +41 -44
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +37 -37
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -2
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -51
- package/src/components/Avatar/Avatar.stories.tsx +26 -26
- package/src/components/Badge/Badge.stories.tsx +31 -31
- package/src/components/Badge/Badge.test.tsx +51 -0
- package/src/components/Badge/Badge.tsx +20 -1
- package/src/components/Block/Block.stories.tsx +5 -5
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
- package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
- package/src/components/Button/Button.stories.tsx +13 -13
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Button/ButtonGroup.stories.tsx +2 -2
- package/src/components/Button/README.md +5 -0
- package/src/components/Callout/Callout.stories.tsx +11 -11
- package/src/components/Callout/Callout.test.tsx +10 -10
- package/src/components/Callout/Callout.tsx +7 -7
- package/src/components/Callout/README.md +9 -8
- package/src/components/Card/Card.tsx +2 -2
- package/src/components/Chart/Chart.stories.tsx +6 -6
- package/src/components/Chart/Chart.tsx +1 -1
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +1 -1
- package/src/components/DataTable/DataTable.tsx +14 -12
- package/src/components/DatePicker/DatePicker.stories.tsx +6 -6
- package/src/components/Dropdown/Dropdown.stories.tsx +4 -4
- package/src/components/Form/Checkbox.stories.tsx +3 -3
- package/src/components/Form/Checkbox.tsx +4 -2
- package/src/components/Form/Form.stories.tsx +3 -3
- package/src/components/Form/FormGroup.stories.tsx +1 -1
- package/src/components/Form/Input.stories.tsx +28 -16
- package/src/components/Form/Input.test.tsx +59 -0
- package/src/components/Form/Input.tsx +97 -95
- package/src/components/Form/Radio.stories.tsx +94 -94
- package/src/components/Form/Radio.tsx +2 -2
- package/src/components/Form/Select.stories.tsx +4 -4
- package/src/components/Form/Select.tsx +2 -2
- package/src/components/Form/Textarea.stories.tsx +22 -7
- package/src/components/Form/Textarea.test.tsx +45 -0
- package/src/components/Form/Textarea.tsx +88 -86
- package/src/components/List/List.stories.tsx +2 -2
- package/src/components/Modal/Modal.stories.tsx +4 -4
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
- package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
- package/src/components/Navigation/README.md +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +5 -2
- package/src/components/Pagination/Pagination.tsx +1 -1
- package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
- package/src/components/Popover/Popover.stories.tsx +1 -1
- package/src/components/ProductReview/ProductReview.tsx +1 -1
- package/src/components/Progress/Progress.tsx +46 -46
- package/src/components/Rating/Rating.stories.tsx +4 -4
- package/src/components/Rating/Rating.tsx +8 -8
- package/src/components/Slider/Slider.stories.tsx +63 -63
- package/src/components/Spinner/Spinner.stories.tsx +2 -2
- package/src/components/Spinner/Spinner.test.tsx +35 -0
- package/src/components/Spinner/Spinner.tsx +9 -2
- package/src/components/Testimonial/Testimonial.stories.tsx +1 -1
- package/src/components/Toggle/Toggle.stories.tsx +32 -9
- package/src/components/Toggle/Toggle.test.tsx +91 -0
- package/src/components/Toggle/Toggle.tsx +44 -27
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/layouts/Grid/Grid.stories.tsx +49 -49
- package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
- package/src/lib/composables/useAccordion.ts +12 -3
- package/src/lib/composables/useBreadcrumb.ts +2 -2
- package/src/lib/composables/useCallout.ts +7 -7
- package/src/lib/composables/useNavbar.ts +1 -1
- package/src/lib/constants/components.ts +1 -1
- package/src/lib/storybook/InteractiveDemo.tsx +113 -0
- package/src/lib/storybook/PreviewContainer.tsx +36 -0
- package/src/lib/storybook/VariantsGrid.tsx +21 -0
- package/src/lib/storybook/index.ts +3 -0
- package/src/lib/theme/core/createThemeObject.ts +9 -5
- package/src/lib/theme/devtools/CLI.ts +155 -0
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
- package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
- package/src/lib/theme/devtools/index.ts +3 -0
- package/src/lib/theme/errors/errors.ts +8 -0
- package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
- package/src/lib/theme/utils/index.ts +1 -0
- package/src/lib/theme/utils/themeValidation.ts +501 -0
- package/src/lib/theme-tools.ts +32 -3
- package/src/lib/types/components.ts +81 -26
- package/src/lib/utils/themeNaming.ts +1 -1
- package/src/styles/06-components/_components.atomix-glass.scss +14 -15
- package/src/styles/06-components/_components.callout.scss +29 -33
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/99-utilities/_utilities.display.scss +14 -3
- package/src/styles/99-utilities/_utilities.flex.scss +10 -10
- package/src/styles/99-utilities/_utilities.text.scss +28 -8
- package/scripts/cli/__tests__/cli-commands.test.js +0 -204
- package/scripts/cli/__tests__/utils.test.js +0 -201
- package/scripts/cli/__tests__/vitest.config.js +0 -26
|
@@ -75,11 +75,11 @@ export const VariantsShowcase: Story = {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
return (
|
|
78
|
-
<div className="u-
|
|
78
|
+
<div className="u-grid u-gap-6" style={{ gridTemplateColumns: 'auto 1fr 1fr 1fr 1fr 1fr' }}>
|
|
79
79
|
{/* Header Row */}
|
|
80
|
-
<div className="u-
|
|
80
|
+
<div className="u-font-bold">Type</div>
|
|
81
81
|
{sizeOptions.map(size => (
|
|
82
|
-
<div key={size} className="u-
|
|
82
|
+
<div key={size} className="u-font-bold u-text-center">
|
|
83
83
|
{size.toUpperCase()}
|
|
84
84
|
</div>
|
|
85
85
|
))}
|
|
@@ -87,7 +87,7 @@ export const VariantsShowcase: Story = {
|
|
|
87
87
|
{/* Square Avatars */}
|
|
88
88
|
<div>Square</div>
|
|
89
89
|
{sizeOptions.map(size => (
|
|
90
|
-
<div key={size} className="u-
|
|
90
|
+
<div key={size} className="u-flex u-justify-center">
|
|
91
91
|
<Avatar src={variantImages.square} size={size} />
|
|
92
92
|
</div>
|
|
93
93
|
))}
|
|
@@ -95,7 +95,7 @@ export const VariantsShowcase: Story = {
|
|
|
95
95
|
{/* Circle Avatars */}
|
|
96
96
|
<div>Circle</div>
|
|
97
97
|
{sizeOptions.map(size => (
|
|
98
|
-
<div key={size} className="u-
|
|
98
|
+
<div key={size} className="u-flex u-justify-center">
|
|
99
99
|
<Avatar src={variantImages.circle} size={size} circle={true} />
|
|
100
100
|
</div>
|
|
101
101
|
))}
|
|
@@ -103,7 +103,7 @@ export const VariantsShowcase: Story = {
|
|
|
103
103
|
{/* Initials Avatars */}
|
|
104
104
|
<div>Initials</div>
|
|
105
105
|
{sizeOptions.map(size => (
|
|
106
|
-
<div key={size} className="u-
|
|
106
|
+
<div key={size} className="u-flex u-justify-center">
|
|
107
107
|
<Avatar initials="JD" size={size} />
|
|
108
108
|
</div>
|
|
109
109
|
))}
|
|
@@ -111,7 +111,7 @@ export const VariantsShowcase: Story = {
|
|
|
111
111
|
{/* Icon Avatars */}
|
|
112
112
|
<div>Icon</div>
|
|
113
113
|
{sizeOptions.map(size => (
|
|
114
|
-
<div key={size} className="u-
|
|
114
|
+
<div key={size} className="u-flex u-justify-center">
|
|
115
115
|
<Avatar
|
|
116
116
|
icon={<Icon name="User" size={size === 'xs' ? 'xs' : size === 'sm' ? 'sm' : 'md'} />}
|
|
117
117
|
size={size}
|
|
@@ -122,7 +122,7 @@ export const VariantsShowcase: Story = {
|
|
|
122
122
|
{/* Fallback Avatars */}
|
|
123
123
|
<div>Fallback</div>
|
|
124
124
|
{sizeOptions.map(size => (
|
|
125
|
-
<div key={size} className="u-
|
|
125
|
+
<div key={size} className="u-flex u-justify-center">
|
|
126
126
|
<Avatar src={variantImages.fallback} size={size} />
|
|
127
127
|
</div>
|
|
128
128
|
))}
|
|
@@ -130,7 +130,7 @@ export const VariantsShowcase: Story = {
|
|
|
130
130
|
{/* Interactive Avatars */}
|
|
131
131
|
<div>Interactive</div>
|
|
132
132
|
{sizeOptions.map(size => (
|
|
133
|
-
<div key={size} className="u-
|
|
133
|
+
<div key={size} className="u-flex u-justify-center">
|
|
134
134
|
<Avatar
|
|
135
135
|
src={`https://i.pravatar.cc/150?img=${size === 'xs' ? 4 : size === 'sm' ? 5 : size === 'md' ? 6 : size === 'lg' ? 7 : 8}`}
|
|
136
136
|
size={size}
|
|
@@ -143,7 +143,7 @@ export const VariantsShowcase: Story = {
|
|
|
143
143
|
{/* Disabled Avatars */}
|
|
144
144
|
<div>Disabled</div>
|
|
145
145
|
{sizeOptions.map(size => (
|
|
146
|
-
<div key={size} className="u-
|
|
146
|
+
<div key={size} className="u-flex u-justify-center">
|
|
147
147
|
<Avatar
|
|
148
148
|
src={`https://i.pravatar.cc/150?img=${size === 'xs' ? 9 : size === 'sm' ? 10 : size === 'md' ? 11 : size === 'lg' ? 12 : 13}`}
|
|
149
149
|
size={size}
|
|
@@ -164,15 +164,15 @@ export const AvatarGroupShowcase: Story = {
|
|
|
164
164
|
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
|
|
165
165
|
|
|
166
166
|
return (
|
|
167
|
-
<div className="u-
|
|
167
|
+
<div className="u-flex u-flex-column u-gap-8">
|
|
168
168
|
{/* First row: Standard and Stacked side by side */}
|
|
169
|
-
<div className="u-
|
|
169
|
+
<div className="u-flex u-gap-12">
|
|
170
170
|
{/* Standard Avatar Groups */}
|
|
171
171
|
<div className="u-flex-grow-1">
|
|
172
|
-
<h3 className="u-mb-4 u-
|
|
173
|
-
<div className="u-
|
|
172
|
+
<h3 className="u-mb-4 u-font-normal">Standard Avatar Groups</h3>
|
|
173
|
+
<div className="u-flex u-flex-column u-gap-4">
|
|
174
174
|
{sizes.map(size => (
|
|
175
|
-
<div key={size} className="u-
|
|
175
|
+
<div key={size} className="u-flex u-items-center u-gap-4">
|
|
176
176
|
<div className="u-w-12">{size.toUpperCase()}</div>
|
|
177
177
|
<AvatarGroup>
|
|
178
178
|
<Avatar src={`https://i.pravatar.cc/150?img=${14}`} size={size} circle />
|
|
@@ -188,10 +188,10 @@ export const AvatarGroupShowcase: Story = {
|
|
|
188
188
|
|
|
189
189
|
{/* Stacked Avatar Groups */}
|
|
190
190
|
<div className="u-flex-grow-1">
|
|
191
|
-
<h3 className="u-mb-4 u-
|
|
192
|
-
<div className="u-
|
|
191
|
+
<h3 className="u-mb-4 u-font-normal">Stacked Avatar Groups</h3>
|
|
192
|
+
<div className="u-flex u-flex-column u-gap-4">
|
|
193
193
|
{sizes.map(size => (
|
|
194
|
-
<div key={size} className="u-
|
|
194
|
+
<div key={size} className="u-flex u-items-center u-gap-4">
|
|
195
195
|
<div className="u-w-12">{size.toUpperCase()}</div>
|
|
196
196
|
<AvatarGroup stacked>
|
|
197
197
|
<Avatar src={`https://i.pravatar.cc/150?img=${24}`} size={size} circle />
|
|
@@ -207,13 +207,13 @@ export const AvatarGroupShowcase: Story = {
|
|
|
207
207
|
</div>
|
|
208
208
|
|
|
209
209
|
{/* Second row: Max and Stacked+Max side by side */}
|
|
210
|
-
<div className="u-
|
|
210
|
+
<div className="u-flex u-gap-12">
|
|
211
211
|
{/* Avatar Groups with Max Limit */}
|
|
212
212
|
<div className="u-flex-grow-1">
|
|
213
|
-
<h3 className="u-mb-4 u-
|
|
214
|
-
<div className="u-
|
|
213
|
+
<h3 className="u-mb-4 u-font-normal">Avatar Groups with Max Limit</h3>
|
|
214
|
+
<div className="u-flex u-flex-column u-gap-4">
|
|
215
215
|
{sizes.map(size => (
|
|
216
|
-
<div key={size} className="u-
|
|
216
|
+
<div key={size} className="u-flex u-items-center u-gap-4">
|
|
217
217
|
<div className="u-w-12">{size.toUpperCase()}</div>
|
|
218
218
|
<AvatarGroup max={3}>
|
|
219
219
|
<Avatar src={`https://i.pravatar.cc/150?img=${19}`} size={size} circle />
|
|
@@ -229,10 +229,10 @@ export const AvatarGroupShowcase: Story = {
|
|
|
229
229
|
|
|
230
230
|
{/* Stacked Avatar Groups with Max Limit */}
|
|
231
231
|
<div className="u-flex-grow-1">
|
|
232
|
-
<h3 className="u-mb-4 u-
|
|
233
|
-
<div className="u-
|
|
232
|
+
<h3 className="u-mb-4 u-font-normal">Stacked Groups with Max Limit</h3>
|
|
233
|
+
<div className="u-flex u-flex-column u-gap-4">
|
|
234
234
|
{sizes.map(size => (
|
|
235
|
-
<div key={size} className="u-
|
|
235
|
+
<div key={size} className="u-flex u-items-center u-gap-4">
|
|
236
236
|
<div className="u-w-12">{size.toUpperCase()}</div>
|
|
237
237
|
<AvatarGroup stacked max={3} moreText={`+more`}>
|
|
238
238
|
<Avatar src={`https://i.pravatar.cc/150?img=${29}`} size={size} circle />
|
|
@@ -249,7 +249,7 @@ export const AvatarGroupShowcase: Story = {
|
|
|
249
249
|
|
|
250
250
|
{/* Mixed Content Avatar Groups */}
|
|
251
251
|
<div>
|
|
252
|
-
<h3 className="u-mb-4 u-
|
|
252
|
+
<h3 className="u-mb-4 u-font-normal">Mixed Content Avatar Groups</h3>
|
|
253
253
|
<AvatarGroup>
|
|
254
254
|
<Avatar src={`https://i.pravatar.cc/150?img=${34}`} size="md" circle />
|
|
255
255
|
<Avatar initials="JD" size="md" circle />
|
|
@@ -231,7 +231,7 @@ export const AllVariants: Story = {
|
|
|
231
231
|
},
|
|
232
232
|
},
|
|
233
233
|
render: () => (
|
|
234
|
-
<div className="u-
|
|
234
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
235
235
|
{THEME_COLORS.map(color => (
|
|
236
236
|
<Badge key={color} label={color} variant={color} />
|
|
237
237
|
))}
|
|
@@ -255,7 +255,7 @@ export const AllSizes: Story = {
|
|
|
255
255
|
},
|
|
256
256
|
},
|
|
257
257
|
render: () => (
|
|
258
|
-
<div className="u-
|
|
258
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
259
259
|
<Badge label="Small" variant="primary" size="sm" />
|
|
260
260
|
<Badge label="Medium" variant="primary" size="md" />
|
|
261
261
|
<Badge label="Large" variant="primary" size="lg" />
|
|
@@ -271,10 +271,10 @@ export const WithDifferentContent: Story = {
|
|
|
271
271
|
label: 'Badge with different content',
|
|
272
272
|
},
|
|
273
273
|
render: () => (
|
|
274
|
-
<div className="u-
|
|
274
|
+
<div className="u-flex u-flex-column u-gap-4">
|
|
275
275
|
<div>
|
|
276
276
|
<h3 className="u-mt-0 u-mb-2">Numeric Badges</h3>
|
|
277
|
-
<div className="u-
|
|
277
|
+
<div className="u-flex u-gap-2">
|
|
278
278
|
<Badge label="1" variant="primary" />
|
|
279
279
|
<Badge label="2" variant="secondary" />
|
|
280
280
|
<Badge label="3" variant="success" />
|
|
@@ -285,7 +285,7 @@ export const WithDifferentContent: Story = {
|
|
|
285
285
|
</div>
|
|
286
286
|
<div>
|
|
287
287
|
<h3 className="u-mt-0 u-mb-2">Status Badges</h3>
|
|
288
|
-
<div className="u-
|
|
288
|
+
<div className="u-flex u-gap-2">
|
|
289
289
|
<Badge label="New" variant="primary" />
|
|
290
290
|
<Badge label="Active" variant="success" />
|
|
291
291
|
<Badge label="Pending" variant="warning" />
|
|
@@ -295,7 +295,7 @@ export const WithDifferentContent: Story = {
|
|
|
295
295
|
</div>
|
|
296
296
|
<div>
|
|
297
297
|
<h3 className="u-mt-0 u-mb-2">Badges with Icons</h3>
|
|
298
|
-
<div className="u-
|
|
298
|
+
<div className="u-flex u-gap-2">
|
|
299
299
|
<Badge label="Info" variant="info" icon={<Icon />} />
|
|
300
300
|
<Badge label="Warning" variant="warning" icon={<Icon />} />
|
|
301
301
|
<Badge label="Success" variant="success" icon={<Icon />} />
|
|
@@ -321,19 +321,19 @@ export const UsageExamples: Story = {
|
|
|
321
321
|
},
|
|
322
322
|
},
|
|
323
323
|
render: () => (
|
|
324
|
-
<div className="u-
|
|
324
|
+
<div className="u-flex u-flex-column u-gap-6 u-max-width-80">
|
|
325
325
|
<div>
|
|
326
326
|
<h3 className="u-mt-0 u-mb-2">In navigation</h3>
|
|
327
|
-
<div className="u-
|
|
328
|
-
<div className="u-
|
|
327
|
+
<div className="u-flex u-gap-4">
|
|
328
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
329
329
|
<span>Inbox</span>
|
|
330
330
|
<Badge label="24" variant="error" size="sm" />
|
|
331
331
|
</div>
|
|
332
|
-
<div className="u-
|
|
332
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
333
333
|
<span>Notifications</span>
|
|
334
334
|
<Badge label="3" variant="primary" size="sm" />
|
|
335
335
|
</div>
|
|
336
|
-
<div className="u-
|
|
336
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
337
337
|
<span>Messages</span>
|
|
338
338
|
<Badge label="New" variant="success" size="sm" />
|
|
339
339
|
</div>
|
|
@@ -342,13 +342,13 @@ export const UsageExamples: Story = {
|
|
|
342
342
|
|
|
343
343
|
<div>
|
|
344
344
|
<h3 className="u-mt-0 u-mb-2">In cards</h3>
|
|
345
|
-
<div className="u-p-4 u-shadow u-
|
|
346
|
-
<div className="u-
|
|
345
|
+
<div className="u-p-4 u-shadow u-flex u-flex-column u-gap-2">
|
|
346
|
+
<div className="u-flex u-justify-between">
|
|
347
347
|
<h4 className="u-m-0">Product Title</h4>
|
|
348
348
|
<Badge label="Sale" variant="error" />
|
|
349
349
|
</div>
|
|
350
350
|
<p className="u-my-2">This is a sample product description.</p>
|
|
351
|
-
<div className="u-
|
|
351
|
+
<div className="u-flex u-gap-2">
|
|
352
352
|
<Badge label="In Stock" variant="success" size="sm" />
|
|
353
353
|
<Badge label="Free Shipping" variant="info" size="sm" />
|
|
354
354
|
</div>
|
|
@@ -359,20 +359,20 @@ export const UsageExamples: Story = {
|
|
|
359
359
|
<h3 className="u-mt-0 u-mb-2">In lists</h3>
|
|
360
360
|
<ul className="u-p-0 u-m-0" style={{ listStyle: 'none' }}>
|
|
361
361
|
<li
|
|
362
|
-
className="u-py-2 u-
|
|
362
|
+
className="u-py-2 u-flex u-justify-between"
|
|
363
363
|
style={{ borderBottom: '1px solid #e0e0e0' }}
|
|
364
364
|
>
|
|
365
365
|
<span>Task 1</span>
|
|
366
366
|
<Badge label="Completed" variant="success" size="sm" />
|
|
367
367
|
</li>
|
|
368
368
|
<li
|
|
369
|
-
className="u-py-2 u-
|
|
369
|
+
className="u-py-2 u-flex u-justify-between"
|
|
370
370
|
style={{ borderBottom: '1px solid #e0e0e0' }}
|
|
371
371
|
>
|
|
372
372
|
<span>Task 2</span>
|
|
373
373
|
<Badge label="In Progress" variant="warning" size="sm" />
|
|
374
374
|
</li>
|
|
375
|
-
<li className="u-py-2 u-
|
|
375
|
+
<li className="u-py-2 u-flex u-justify-between">
|
|
376
376
|
<span>Task 3</span>
|
|
377
377
|
<Badge label="Not Started" variant="secondary" size="sm" />
|
|
378
378
|
</li>
|
|
@@ -391,16 +391,16 @@ export const ThemeAwareBadges: Story = {
|
|
|
391
391
|
variant: 'primary',
|
|
392
392
|
},
|
|
393
393
|
render: () => (
|
|
394
|
-
<div className="u-
|
|
394
|
+
<div className="u-flex u-flex-column u-gap-6">
|
|
395
395
|
<div>
|
|
396
396
|
<h3 className="u-mt-0 u-mb-2">Theme Aware Badges</h3>
|
|
397
397
|
<p className="u-mb-4">
|
|
398
398
|
The badges below demonstrate how they adapt to different theme modes.
|
|
399
399
|
</p>
|
|
400
|
-
<div className="u-
|
|
400
|
+
<div className="u-flex u-gap-5 u-mt-4">
|
|
401
401
|
<div className="u-p-5 u-shadow u-flex-1">
|
|
402
402
|
<h4 className="u-mt-0">Current Theme</h4>
|
|
403
|
-
<div className="u-
|
|
403
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
404
404
|
{THEME_COLORS.map(color => (
|
|
405
405
|
<Badge key={color} label={color} variant={color} />
|
|
406
406
|
))}
|
|
@@ -414,27 +414,27 @@ export const ThemeAwareBadges: Story = {
|
|
|
414
414
|
<p className="u-mb-2">
|
|
415
415
|
Our badges are designed to maintain proper contrast in both light and dark modes.
|
|
416
416
|
</p>
|
|
417
|
-
<div className="u-
|
|
418
|
-
<div className="u-
|
|
419
|
-
<span className="u-
|
|
417
|
+
<div className="u-flex u-flex-column u-gap-2 u-mt-2">
|
|
418
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
419
|
+
<span className="u-inline-block" style={{ width: '120px' }}>
|
|
420
420
|
Primary:
|
|
421
421
|
</span>
|
|
422
422
|
<Badge label="New Feature" variant="primary" />
|
|
423
423
|
</div>
|
|
424
|
-
<div className="u-
|
|
425
|
-
<span className="u-
|
|
424
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
425
|
+
<span className="u-inline-block" style={{ width: '120px' }}>
|
|
426
426
|
Success:
|
|
427
427
|
</span>
|
|
428
428
|
<Badge label="Completed" variant="success" />
|
|
429
429
|
</div>
|
|
430
|
-
<div className="u-
|
|
431
|
-
<span className="u-
|
|
430
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
431
|
+
<span className="u-inline-block" style={{ width: '120px' }}>
|
|
432
432
|
Warning:
|
|
433
433
|
</span>
|
|
434
434
|
<Badge label="In Progress" variant="warning" />
|
|
435
435
|
</div>
|
|
436
|
-
<div className="u-
|
|
437
|
-
<span className="u-
|
|
436
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
437
|
+
<span className="u-inline-block" style={{ width: '120px' }}>
|
|
438
438
|
Error:
|
|
439
439
|
</span>
|
|
440
440
|
<Badge label="Failed" variant="error" />
|
|
@@ -571,7 +571,7 @@ export const GlassAllVariants: Story = {
|
|
|
571
571
|
borderRadius: '8px',
|
|
572
572
|
}}
|
|
573
573
|
>
|
|
574
|
-
<div className="u-
|
|
574
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
575
575
|
{THEME_COLORS.map(color => (
|
|
576
576
|
<Badge key={color} label={color} variant={color} glass={true} />
|
|
577
577
|
))}
|
|
@@ -597,7 +597,7 @@ export const GlassAllSizes: Story = {
|
|
|
597
597
|
borderRadius: '8px',
|
|
598
598
|
}}
|
|
599
599
|
>
|
|
600
|
-
<div className="u-
|
|
600
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
601
601
|
<Badge label="Small" variant="primary" size="sm" glass={true} />
|
|
602
602
|
<Badge label="Medium" variant="primary" size="md" glass={true} />
|
|
603
603
|
<Badge label="Large" variant="primary" size="lg" glass={true} />
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
import { Badge } from './Badge';
|
|
4
|
+
|
|
5
|
+
// Mock AtomixGlass component
|
|
6
|
+
vi.mock('../AtomixGlass/AtomixGlass', () => ({
|
|
7
|
+
AtomixGlass: ({ children, ...props }: any) => (
|
|
8
|
+
<div data-testid="atomix-glass" data-glass-props={JSON.stringify(props)}>
|
|
9
|
+
{children}
|
|
10
|
+
</div>
|
|
11
|
+
),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
describe('Badge Component', () => {
|
|
15
|
+
it('renders correctly', () => {
|
|
16
|
+
render(<Badge label="Test Badge" />);
|
|
17
|
+
expect(screen.getByText('Test Badge')).toBeInTheDocument();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders with aria-label', () => {
|
|
21
|
+
render(<Badge label="Badge" aria-label="Accessible Badge" />);
|
|
22
|
+
expect(screen.getByLabelText('Accessible Badge')).toBeInTheDocument();
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('renders close button when onRemove is provided', () => {
|
|
26
|
+
const handleRemove = vi.fn();
|
|
27
|
+
render(<Badge label="Removable" onRemove={handleRemove} />);
|
|
28
|
+
|
|
29
|
+
const closeButton = screen.getByRole('button', { name: 'Remove badge' });
|
|
30
|
+
expect(closeButton).toBeInTheDocument();
|
|
31
|
+
|
|
32
|
+
fireEvent.click(closeButton);
|
|
33
|
+
expect(handleRemove).toHaveBeenCalledTimes(1);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('does not render close button when onRemove is not provided', () => {
|
|
37
|
+
render(<Badge label="Static" />);
|
|
38
|
+
expect(screen.queryByRole('button')).not.toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('disables close button when badge is disabled', () => {
|
|
42
|
+
const handleRemove = vi.fn();
|
|
43
|
+
render(<Badge label="Disabled" onRemove={handleRemove} disabled />);
|
|
44
|
+
|
|
45
|
+
const closeButton = screen.getByRole('button', { name: 'Remove badge' });
|
|
46
|
+
expect(closeButton).toBeDisabled();
|
|
47
|
+
|
|
48
|
+
fireEvent.click(closeButton);
|
|
49
|
+
expect(handleRemove).not.toHaveBeenCalled();
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -10,6 +10,8 @@ export const Badge: React.FC<BadgeProps> = memo(({
|
|
|
10
10
|
size = 'md',
|
|
11
11
|
disabled = false,
|
|
12
12
|
icon,
|
|
13
|
+
onRemove,
|
|
14
|
+
'aria-label': ariaLabel,
|
|
13
15
|
className = '',
|
|
14
16
|
glass,
|
|
15
17
|
style,
|
|
@@ -30,9 +32,26 @@ export const Badge: React.FC<BadgeProps> = memo(({
|
|
|
30
32
|
});
|
|
31
33
|
|
|
32
34
|
const badgeElement = (
|
|
33
|
-
<span
|
|
35
|
+
<span
|
|
36
|
+
className={badgeClass}
|
|
37
|
+
aria-disabled={disabled}
|
|
38
|
+
aria-label={ariaLabel}
|
|
39
|
+
ref={ref}
|
|
40
|
+
style={style}
|
|
41
|
+
>
|
|
34
42
|
{icon && <span className={BADGE.ICON_CLASS}>{icon}</span>}
|
|
35
43
|
<span>{label}</span>
|
|
44
|
+
{onRemove && (
|
|
45
|
+
<button
|
|
46
|
+
type="button"
|
|
47
|
+
className="c-badge__close"
|
|
48
|
+
onClick={onRemove}
|
|
49
|
+
aria-label="Remove badge"
|
|
50
|
+
disabled={disabled}
|
|
51
|
+
>
|
|
52
|
+
×
|
|
53
|
+
</button>
|
|
54
|
+
)}
|
|
36
55
|
</span>
|
|
37
56
|
);
|
|
38
57
|
|
|
@@ -346,25 +346,25 @@ export const ContentPreview: Story = {
|
|
|
346
346
|
<Grid>
|
|
347
347
|
<GridCol xs={12} md={6} lg={3}>
|
|
348
348
|
<div className="u-text-center u-p-3">
|
|
349
|
-
<h3 className="u-
|
|
349
|
+
<h3 className="u-text-h4">Consistency</h3>
|
|
350
350
|
<p className="u-mb-0">Unified design language across all products</p>
|
|
351
351
|
</div>
|
|
352
352
|
</GridCol>
|
|
353
353
|
<GridCol xs={12} md={6} lg={3}>
|
|
354
354
|
<div className="u-text-center u-p-3">
|
|
355
|
-
<h3 className="u-
|
|
355
|
+
<h3 className="u-text-h4">Accessibility</h3>
|
|
356
356
|
<p className="u-mb-0">WCAG 2.1 AA compliant components</p>
|
|
357
357
|
</div>
|
|
358
358
|
</GridCol>
|
|
359
359
|
<GridCol xs={12} md={6} lg={3}>
|
|
360
360
|
<div className="u-text-center u-p-3">
|
|
361
|
-
<h3 className="u-
|
|
361
|
+
<h3 className="u-text-h4">Responsive</h3>
|
|
362
362
|
<p className="u-mb-0">Mobile-first approach for all devices</p>
|
|
363
363
|
</div>
|
|
364
364
|
</GridCol>
|
|
365
365
|
<GridCol xs={12} md={6} lg={3}>
|
|
366
366
|
<div className="u-text-center u-p-3">
|
|
367
|
-
<h3 className="u-
|
|
367
|
+
<h3 className="u-text-h4">Customizable</h3>
|
|
368
368
|
<p className="u-mb-0">Easily extend and modify components</p>
|
|
369
369
|
</div>
|
|
370
370
|
</GridCol>
|
|
@@ -372,7 +372,7 @@ export const ContentPreview: Story = {
|
|
|
372
372
|
</Block>
|
|
373
373
|
|
|
374
374
|
<Block spacing="xl">
|
|
375
|
-
<div className="u-
|
|
375
|
+
<div className="u-flex u-flex-column u-items-center u-text-center">
|
|
376
376
|
<h2 className="u-mb-3">Ready to Get Started?</h2>
|
|
377
377
|
<p className="u-mb-4" style={{ maxWidth: '600px' }}>
|
|
378
378
|
Join thousands of developers and designers building with Atomix Design System
|
|
@@ -57,7 +57,7 @@ export interface BreadcrumbProps {
|
|
|
57
57
|
/**
|
|
58
58
|
* Aria label for the navigation
|
|
59
59
|
*/
|
|
60
|
-
|
|
60
|
+
'aria-label'?: string;
|
|
61
61
|
|
|
62
62
|
/**
|
|
63
63
|
* Optional custom link component
|
|
@@ -73,7 +73,7 @@ export const Breadcrumb: React.FC<BreadcrumbProps> = memo(({
|
|
|
73
73
|
items,
|
|
74
74
|
divider,
|
|
75
75
|
className = '',
|
|
76
|
-
ariaLabel = 'Breadcrumb',
|
|
76
|
+
'aria-label': ariaLabel = 'Breadcrumb',
|
|
77
77
|
LinkComponent,
|
|
78
78
|
style,
|
|
79
79
|
}) => {
|
|
@@ -303,7 +303,7 @@ export const AllVariants: Story = {
|
|
|
303
303
|
},
|
|
304
304
|
},
|
|
305
305
|
render: () => (
|
|
306
|
-
<div className="u-
|
|
306
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
307
307
|
<Button label="Primary" variant="primary" />
|
|
308
308
|
<Button label="Secondary" variant="secondary" />
|
|
309
309
|
<Button label="Success" variant="success" />
|
|
@@ -332,7 +332,7 @@ export const AllOutlineVariants: Story = {
|
|
|
332
332
|
},
|
|
333
333
|
},
|
|
334
334
|
render: () => (
|
|
335
|
-
<div className="u-
|
|
335
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
336
336
|
<Button label="Outline Primary" variant="outline-primary" />
|
|
337
337
|
<Button label="Outline Secondary" variant="outline-secondary" />
|
|
338
338
|
<Button label="Outline Success" variant="outline-success" />
|
|
@@ -361,7 +361,7 @@ export const AllSizes: Story = {
|
|
|
361
361
|
},
|
|
362
362
|
},
|
|
363
363
|
render: () => (
|
|
364
|
-
<div className="u-
|
|
364
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
365
365
|
<Button label="Small" variant="primary" size="sm" />
|
|
366
366
|
<Button label="Medium" variant="primary" size="md" />
|
|
367
367
|
<Button label="Large" variant="primary" size="lg" />
|
|
@@ -380,7 +380,7 @@ export const IconButtonVariants: Story = {
|
|
|
380
380
|
iconOnly: true,
|
|
381
381
|
},
|
|
382
382
|
render: () => (
|
|
383
|
-
<div className="u-
|
|
383
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
384
384
|
<Button label="Add" variant="primary" icon={<Icon />} />
|
|
385
385
|
<Button label="Add" variant="secondary" icon={<Icon />} />
|
|
386
386
|
<Button label="Add" variant="success" icon={<Icon />} />
|
|
@@ -413,7 +413,7 @@ export const RoundedVariants: Story = {
|
|
|
413
413
|
rounded: true,
|
|
414
414
|
},
|
|
415
415
|
render: () => (
|
|
416
|
-
<div className="u-
|
|
416
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
417
417
|
<Button label="Primary" variant="primary" rounded />
|
|
418
418
|
<Button label="Secondary" variant="secondary" rounded />
|
|
419
419
|
<Button label="Success" variant="success" rounded />
|
|
@@ -535,7 +535,7 @@ export const GlassVariants: Story = {
|
|
|
535
535
|
borderRadius: '12px',
|
|
536
536
|
}}
|
|
537
537
|
>
|
|
538
|
-
<div className="u-
|
|
538
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
539
539
|
<Button label="Primary" variant="primary" glass />
|
|
540
540
|
<Button label="Secondary" variant="secondary" glass />
|
|
541
541
|
<Button label="Success" variant="success" glass />
|
|
@@ -566,7 +566,7 @@ export const GlassOutlineVariants: Story = {
|
|
|
566
566
|
borderRadius: '12px',
|
|
567
567
|
}}
|
|
568
568
|
>
|
|
569
|
-
<div className="u-
|
|
569
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
570
570
|
<Button label="Outline Primary" variant="outline-primary" glass />
|
|
571
571
|
<Button label="Outline Secondary" variant="outline-secondary" glass />
|
|
572
572
|
<Button label="Outline Success" variant="outline-success" glass />
|
|
@@ -596,7 +596,7 @@ export const GlassSizes: Story = {
|
|
|
596
596
|
borderRadius: '12px',
|
|
597
597
|
}}
|
|
598
598
|
>
|
|
599
|
-
<div className="u-
|
|
599
|
+
<div className="u-flex u-items-center u-gap-2">
|
|
600
600
|
<Button label="Small Glass" variant="primary" size="sm" glass={{ cornerRadius: 8 }} />
|
|
601
601
|
<Button label="Medium Glass" variant="primary" size="md" glass />
|
|
602
602
|
<Button label="Large Glass" variant="primary" size="lg" glass />
|
|
@@ -622,7 +622,7 @@ export const GlassWithIcons: Story = {
|
|
|
622
622
|
borderRadius: '12px',
|
|
623
623
|
}}
|
|
624
624
|
>
|
|
625
|
-
<div className="u-
|
|
625
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
626
626
|
<Button label="With Icon" variant="primary" icon={<Icon />} glass={{ cornerRadius: 12 }} />
|
|
627
627
|
<Button
|
|
628
628
|
label="Icon Only"
|
|
@@ -699,7 +699,7 @@ export const GlassShowcase: Story = {
|
|
|
699
699
|
<h3 style={{ color: 'white', marginBottom: '1rem', fontSize: '1.2rem' }}>
|
|
700
700
|
Primary Glass Variants
|
|
701
701
|
</h3>
|
|
702
|
-
<div className="u-
|
|
702
|
+
<div className="u-flex u-flex-wrap u-gap-2 u-items-center">
|
|
703
703
|
<Button label="Small Glass" variant="primary" size="sm" glass={{ cornerRadius: 8 }} />
|
|
704
704
|
<Button label="Medium Glass" variant="primary" size="md" glass />
|
|
705
705
|
<Button label="Large Glass" variant="primary" size="lg" glass />
|
|
@@ -723,7 +723,7 @@ export const GlassShowcase: Story = {
|
|
|
723
723
|
<h3 style={{ color: 'white', marginBottom: '1rem', fontSize: '1.2rem' }}>
|
|
724
724
|
Outline Glass Variants
|
|
725
725
|
</h3>
|
|
726
|
-
<div className="u-
|
|
726
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
727
727
|
<Button label="Outline Primary" variant="outline-primary" glass />
|
|
728
728
|
<Button label="Outline Success" variant="outline-success" glass />
|
|
729
729
|
<Button label="Outline Warning" variant="outline-warning" glass />
|
|
@@ -744,7 +744,7 @@ export const GlassShowcase: Story = {
|
|
|
744
744
|
<h3 style={{ color: 'white', marginBottom: '1rem', fontSize: '1.2rem' }}>
|
|
745
745
|
Custom Glass Effects
|
|
746
746
|
</h3>
|
|
747
|
-
<div className="u-
|
|
747
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
748
748
|
<Button
|
|
749
749
|
label="Polar Mode"
|
|
750
750
|
variant="secondary"
|
|
@@ -797,7 +797,7 @@ export const GlassShowcase: Story = {
|
|
|
797
797
|
<h3 style={{ color: '#333', marginBottom: '1rem', fontSize: '1.2rem' }}>
|
|
798
798
|
Light Background
|
|
799
799
|
</h3>
|
|
800
|
-
<div className="u-
|
|
800
|
+
<div className="u-flex u-flex-wrap u-gap-2">
|
|
801
801
|
<Button label="Light Variant" variant="light" glass />
|
|
802
802
|
<Button label="Outline Light" variant="outline-light" glass />
|
|
803
803
|
<Button label="Dark on Light" variant="dark" glass />
|
|
@@ -46,10 +46,10 @@ export const Button = React.memo(
|
|
|
46
46
|
onHover,
|
|
47
47
|
onFocus,
|
|
48
48
|
onBlur,
|
|
49
|
-
ariaLabel,
|
|
50
|
-
ariaDescribedBy,
|
|
51
|
-
ariaExpanded,
|
|
52
|
-
ariaControls,
|
|
49
|
+
'aria-label': ariaLabel,
|
|
50
|
+
'aria-describedby': ariaDescribedBy,
|
|
51
|
+
'aria-expanded': ariaExpanded,
|
|
52
|
+
'aria-controls': ariaControls,
|
|
53
53
|
tabIndex,
|
|
54
54
|
style,
|
|
55
55
|
LinkComponent,
|
|
@@ -150,8 +150,8 @@ export const WithIcons: Story = {
|
|
|
150
150
|
export const IconOnly: Story = {
|
|
151
151
|
render: () => (
|
|
152
152
|
<ButtonGroup>
|
|
153
|
-
<Button iconName="CaretLeft" iconOnly
|
|
154
|
-
<Button iconName="CaretRight" iconOnly
|
|
153
|
+
<Button iconName="CaretLeft" iconOnly aria-label="Previous" />
|
|
154
|
+
<Button iconName="CaretRight" iconOnly aria-label="Next" />
|
|
155
155
|
</ButtonGroup>
|
|
156
156
|
),
|
|
157
157
|
};
|
|
@@ -97,6 +97,11 @@ const GlassVariantsExample = () => (
|
|
|
97
97
|
| `className` | `string` | - | Additional CSS classes |
|
|
98
98
|
| `as` | `ElementType` | `'button'` | HTML element or component to render as |
|
|
99
99
|
| `glass` | `boolean \| AtomixGlassProps` | `false` | Glass morphism effect |
|
|
100
|
+
| `aria-label` | `string` | - | Accessible label for the button |
|
|
101
|
+
| `aria-describedby` | `string` | - | ID of the element that describes the button |
|
|
102
|
+
| `aria-expanded` | `boolean` | - | Indicates if the button controls an expandable element |
|
|
103
|
+
| `aria-controls` | `string` | - | ID of the element controlled by the button |
|
|
104
|
+
| `tabIndex` | `number` | `0` | Tab index for keyboard navigation |
|
|
100
105
|
|
|
101
106
|
### Glass Props
|
|
102
107
|
|