@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.
Files changed (155) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -0
  3. package/dist/atomix.css +101 -88
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +5 -15258
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/charts.d.ts +1 -1
  8. package/dist/charts.js +17 -19
  9. package/dist/charts.js.map +1 -1
  10. package/dist/core.d.ts +41 -11
  11. package/dist/core.js +55 -41
  12. package/dist/core.js.map +1 -1
  13. package/dist/forms.d.ts +28 -11
  14. package/dist/forms.js +25 -24
  15. package/dist/forms.js.map +1 -1
  16. package/dist/heavy.d.ts +1 -1
  17. package/dist/heavy.js +32 -25
  18. package/dist/heavy.js.map +1 -1
  19. package/dist/index.d.ts +122 -46
  20. package/dist/index.esm.js +865 -200
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +870 -204
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/theme.d.ts +27 -2
  27. package/dist/theme.js +721 -108
  28. package/dist/theme.js.map +1 -1
  29. package/package.json +1 -1
  30. package/scripts/atomix-cli.js +610 -1111
  31. package/scripts/cli/component-generator.js +610 -0
  32. package/scripts/cli/documentation-sync.js +542 -0
  33. package/scripts/cli/interactive-init.js +84 -288
  34. package/scripts/cli/mappings.js +211 -0
  35. package/scripts/cli/migration-tools.js +95 -288
  36. package/scripts/cli/template-manager.js +107 -0
  37. package/scripts/cli/templates/README.md +123 -0
  38. package/scripts/cli/templates/composable-templates.js +149 -0
  39. package/scripts/cli/templates/config-templates.js +126 -0
  40. package/scripts/cli/templates/index.js +95 -0
  41. package/scripts/cli/templates/project-templates.js +214 -0
  42. package/scripts/cli/templates/react-templates.js +261 -0
  43. package/scripts/cli/templates/scss-templates.js +156 -0
  44. package/scripts/cli/templates/storybook-templates.js +236 -0
  45. package/scripts/cli/templates/testing-templates.js +45 -0
  46. package/scripts/cli/templates/token-templates.js +447 -0
  47. package/scripts/cli/templates/types-templates.js +133 -0
  48. package/scripts/cli/templates-original-backup.js +1655 -0
  49. package/scripts/cli/templates.js +35 -0
  50. package/scripts/cli/templates_backup.js +684 -0
  51. package/scripts/cli/theme-bridge.js +20 -14
  52. package/scripts/cli/token-manager.js +150 -77
  53. package/scripts/cli/utils.js +37 -25
  54. package/src/components/Accordion/Accordion.stories.tsx +5 -5
  55. package/src/components/Accordion/Accordion.test.tsx +57 -0
  56. package/src/components/Accordion/Accordion.tsx +4 -0
  57. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +41 -44
  58. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +1 -1
  59. package/src/components/AtomixGlass/stories/Examples.stories.tsx +37 -37
  60. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -2
  61. package/src/components/AtomixGlass/stories/Playground.stories.tsx +50 -51
  62. package/src/components/Avatar/Avatar.stories.tsx +26 -26
  63. package/src/components/Badge/Badge.stories.tsx +31 -31
  64. package/src/components/Badge/Badge.test.tsx +51 -0
  65. package/src/components/Badge/Badge.tsx +20 -1
  66. package/src/components/Block/Block.stories.tsx +5 -5
  67. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +1 -1
  68. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  69. package/src/components/Button/Button.stories.tsx +13 -13
  70. package/src/components/Button/Button.tsx +4 -4
  71. package/src/components/Button/ButtonGroup.stories.tsx +2 -2
  72. package/src/components/Button/README.md +5 -0
  73. package/src/components/Callout/Callout.stories.tsx +11 -11
  74. package/src/components/Callout/Callout.test.tsx +10 -10
  75. package/src/components/Callout/Callout.tsx +7 -7
  76. package/src/components/Callout/README.md +9 -8
  77. package/src/components/Card/Card.tsx +2 -2
  78. package/src/components/Chart/Chart.stories.tsx +6 -6
  79. package/src/components/Chart/Chart.tsx +1 -1
  80. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +1 -1
  81. package/src/components/DataTable/DataTable.tsx +14 -12
  82. package/src/components/DatePicker/DatePicker.stories.tsx +6 -6
  83. package/src/components/Dropdown/Dropdown.stories.tsx +4 -4
  84. package/src/components/Form/Checkbox.stories.tsx +3 -3
  85. package/src/components/Form/Checkbox.tsx +4 -2
  86. package/src/components/Form/Form.stories.tsx +3 -3
  87. package/src/components/Form/FormGroup.stories.tsx +1 -1
  88. package/src/components/Form/Input.stories.tsx +28 -16
  89. package/src/components/Form/Input.test.tsx +59 -0
  90. package/src/components/Form/Input.tsx +97 -95
  91. package/src/components/Form/Radio.stories.tsx +94 -94
  92. package/src/components/Form/Radio.tsx +2 -2
  93. package/src/components/Form/Select.stories.tsx +4 -4
  94. package/src/components/Form/Select.tsx +2 -2
  95. package/src/components/Form/Textarea.stories.tsx +22 -7
  96. package/src/components/Form/Textarea.test.tsx +45 -0
  97. package/src/components/Form/Textarea.tsx +88 -86
  98. package/src/components/List/List.stories.tsx +2 -2
  99. package/src/components/Modal/Modal.stories.tsx +4 -4
  100. package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
  101. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  102. package/src/components/Navigation/README.md +1 -1
  103. package/src/components/Pagination/Pagination.stories.tsx +5 -2
  104. package/src/components/Pagination/Pagination.tsx +1 -1
  105. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
  106. package/src/components/Popover/Popover.stories.tsx +1 -1
  107. package/src/components/ProductReview/ProductReview.tsx +1 -1
  108. package/src/components/Progress/Progress.tsx +46 -46
  109. package/src/components/Rating/Rating.stories.tsx +4 -4
  110. package/src/components/Rating/Rating.tsx +8 -8
  111. package/src/components/Slider/Slider.stories.tsx +63 -63
  112. package/src/components/Spinner/Spinner.stories.tsx +2 -2
  113. package/src/components/Spinner/Spinner.test.tsx +35 -0
  114. package/src/components/Spinner/Spinner.tsx +9 -2
  115. package/src/components/Testimonial/Testimonial.stories.tsx +1 -1
  116. package/src/components/Toggle/Toggle.stories.tsx +32 -9
  117. package/src/components/Toggle/Toggle.test.tsx +91 -0
  118. package/src/components/Toggle/Toggle.tsx +44 -27
  119. package/src/components/Tooltip/Tooltip.tsx +1 -1
  120. package/src/layouts/Grid/Grid.stories.tsx +49 -49
  121. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
  122. package/src/lib/composables/useAccordion.ts +12 -3
  123. package/src/lib/composables/useBreadcrumb.ts +2 -2
  124. package/src/lib/composables/useCallout.ts +7 -7
  125. package/src/lib/composables/useNavbar.ts +1 -1
  126. package/src/lib/constants/components.ts +1 -1
  127. package/src/lib/storybook/InteractiveDemo.tsx +113 -0
  128. package/src/lib/storybook/PreviewContainer.tsx +36 -0
  129. package/src/lib/storybook/VariantsGrid.tsx +21 -0
  130. package/src/lib/storybook/index.ts +3 -0
  131. package/src/lib/theme/core/createThemeObject.ts +9 -5
  132. package/src/lib/theme/devtools/CLI.ts +155 -0
  133. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
  134. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
  135. package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
  136. package/src/lib/theme/devtools/index.ts +3 -0
  137. package/src/lib/theme/errors/errors.ts +8 -0
  138. package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
  139. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
  140. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
  141. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
  142. package/src/lib/theme/utils/index.ts +1 -0
  143. package/src/lib/theme/utils/themeValidation.ts +501 -0
  144. package/src/lib/theme-tools.ts +32 -3
  145. package/src/lib/types/components.ts +81 -26
  146. package/src/lib/utils/themeNaming.ts +1 -1
  147. package/src/styles/06-components/_components.atomix-glass.scss +14 -15
  148. package/src/styles/06-components/_components.callout.scss +29 -33
  149. package/src/styles/06-components/_index.scss +1 -1
  150. package/src/styles/99-utilities/_utilities.display.scss +14 -3
  151. package/src/styles/99-utilities/_utilities.flex.scss +10 -10
  152. package/src/styles/99-utilities/_utilities.text.scss +28 -8
  153. package/scripts/cli/__tests__/cli-commands.test.js +0 -204
  154. package/scripts/cli/__tests__/utils.test.js +0 -201
  155. 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-d-grid u-gap-6" style={{ gridTemplateColumns: 'auto 1fr 1fr 1fr 1fr 1fr' }}>
78
+ <div className="u-grid u-gap-6" style={{ gridTemplateColumns: 'auto 1fr 1fr 1fr 1fr 1fr' }}>
79
79
  {/* Header Row */}
80
- <div className="u-fw-bold">Type</div>
80
+ <div className="u-font-bold">Type</div>
81
81
  {sizeOptions.map(size => (
82
- <div key={size} className="u-fw-bold u-text-center">
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-d-flex u-justify-content-center">
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-d-flex u-justify-content-center">
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-d-flex u-justify-content-center">
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-d-flex u-justify-content-center">
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-d-flex u-justify-content-center">
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-d-flex u-justify-content-center">
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-d-flex u-justify-content-center">
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-d-flex u-flex-column u-gap-8">
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-d-flex u-gap-12">
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-fw-normal">Standard Avatar Groups</h3>
173
- <div className="u-d-flex u-flex-column u-gap-4">
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-d-flex u-align-items-center u-gap-4">
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-fw-normal">Stacked Avatar Groups</h3>
192
- <div className="u-d-flex u-flex-column u-gap-4">
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-d-flex u-align-items-center u-gap-4">
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-d-flex u-gap-12">
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-fw-normal">Avatar Groups with Max Limit</h3>
214
- <div className="u-d-flex u-flex-column u-gap-4">
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-d-flex u-align-items-center u-gap-4">
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-fw-normal">Stacked Groups with Max Limit</h3>
233
- <div className="u-d-flex u-flex-column u-gap-4">
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-d-flex u-align-items-center u-gap-4">
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-fw-normal">Mixed Content Avatar Groups</h3>
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-align-items-center u-gap-2">
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-d-flex u-flex-column u-gap-4">
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-d-flex u-gap-2">
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-d-flex u-gap-2">
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-d-flex u-gap-2">
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-d-flex u-flex-column u-gap-6 u-max-width-80">
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-d-flex u-gap-4">
328
- <div className="u-d-flex u-align-items-center u-gap-2">
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-d-flex u-align-items-center u-gap-2">
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-d-flex u-align-items-center u-gap-2">
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-d-flex u-flex-column u-gap-2">
346
- <div className="u-d-flex u-justify-content-between">
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-d-flex u-gap-2">
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-d-flex u-justify-content-between"
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-d-flex u-justify-content-between"
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-d-flex u-justify-content-between">
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-d-flex u-flex-column u-gap-6">
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-d-flex u-gap-5 u-mt-4">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-column u-gap-2 u-mt-2">
418
- <div className="u-d-flex u-align-items-center u-gap-2">
419
- <span className="u-d-inline-block" style={{ width: '120px' }}>
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-d-flex u-align-items-center u-gap-2">
425
- <span className="u-d-inline-block" style={{ width: '120px' }}>
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-d-flex u-align-items-center u-gap-2">
431
- <span className="u-d-inline-block" style={{ width: '120px' }}>
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-d-flex u-align-items-center u-gap-2">
437
- <span className="u-d-inline-block" style={{ width: '120px' }}>
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-align-items-center u-gap-2">
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 className={badgeClass} aria-disabled={disabled} ref={ref} style={style}>
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-fs-h4">Consistency</h3>
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-fs-h4">Accessibility</h3>
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-fs-h4">Responsive</h3>
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-fs-h4">Customizable</h3>
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-d-flex u-flex-column u-align-items-center u-text-center">
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
@@ -19,7 +19,7 @@ const meta = {
19
19
  items: { control: 'object' },
20
20
  divider: { control: 'text' },
21
21
  className: { control: 'text' },
22
- ariaLabel: { control: 'text' },
22
+ 'aria-label': { control: 'text' },
23
23
  },
24
24
  } satisfies Meta<typeof Breadcrumb>;
25
25
 
@@ -57,7 +57,7 @@ export interface BreadcrumbProps {
57
57
  /**
58
58
  * Aria label for the navigation
59
59
  */
60
- ariaLabel?: string;
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-align-items-center u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-align-items-center u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2 u-align-items-center">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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-d-flex u-flex-wrap u-gap-2">
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 ariaLabel="Previous" />
154
- <Button iconName="CaretRight" iconOnly ariaLabel="Next" />
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