@shohojdhara/atomix 0.3.15 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (245) hide show
  1. package/build-tools/index.d.ts +31 -30
  2. package/build-tools/package.json +4 -21
  3. package/dist/atomix.css +20924 -2611
  4. package/dist/atomix.css.map +1 -1
  5. package/dist/atomix.min.css +76 -2
  6. package/dist/atomix.min.css.map +1 -1
  7. package/dist/build-tools/index.d.ts +31 -30
  8. package/dist/build-tools/package.json +4 -21
  9. package/dist/charts.js.map +1 -1
  10. package/dist/core.js.map +1 -1
  11. package/dist/forms.js.map +1 -1
  12. package/dist/heavy.js.map +1 -1
  13. package/dist/index.d.ts +144 -18
  14. package/dist/index.esm.js +110 -55
  15. package/dist/index.esm.js.map +1 -1
  16. package/dist/index.js +110 -55
  17. package/dist/index.js.map +1 -1
  18. package/dist/index.min.js +1 -1
  19. package/dist/index.min.js.map +1 -1
  20. package/dist/layout.js.map +1 -1
  21. package/dist/theme.d.ts +9 -9
  22. package/dist/theme.js.map +1 -1
  23. package/package.json +1 -1
  24. package/src/components/Accordion/Accordion.stories.tsx +32 -23
  25. package/src/components/Accordion/Accordion.test.tsx +70 -50
  26. package/src/components/Accordion/Accordion.tsx +99 -94
  27. package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
  28. package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
  29. package/src/components/AtomixGlass/glass-utils.ts +4 -3
  30. package/src/components/AtomixGlass/shader-utils.ts +128 -52
  31. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
  32. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
  33. package/src/components/Avatar/Avatar.stories.tsx +45 -62
  34. package/src/components/Avatar/Avatar.tsx +58 -56
  35. package/src/components/Badge/Badge.stories.tsx +20 -9
  36. package/src/components/Badge/Badge.test.tsx +41 -41
  37. package/src/components/Badge/Badge.tsx +64 -62
  38. package/src/components/Block/Block.stories.tsx +14 -4
  39. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
  40. package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
  41. package/src/components/Button/Button.stories.tsx +13 -22
  42. package/src/components/Button/Button.test.tsx +97 -81
  43. package/src/components/Button/Button.tsx +46 -14
  44. package/src/components/Button/ButtonGroup.stories.tsx +37 -32
  45. package/src/components/Button/ButtonGroup.tsx +4 -15
  46. package/src/components/Callout/Callout.stories.tsx +109 -16
  47. package/src/components/Card/Card.stories.tsx +67 -36
  48. package/src/components/Card/Card.tsx +30 -14
  49. package/src/components/Chart/AreaChart.tsx +1 -1
  50. package/src/components/Chart/CandlestickChart.tsx +23 -16
  51. package/src/components/Chart/Chart.stories.tsx +4 -9
  52. package/src/components/Chart/Chart.tsx +40 -44
  53. package/src/components/Chart/ChartRenderer.tsx +39 -12
  54. package/src/components/Chart/ChartToolbar.tsx +21 -5
  55. package/src/components/Chart/DonutChart.tsx +1 -1
  56. package/src/components/Chart/FunnelChart.tsx +4 -1
  57. package/src/components/Chart/GaugeChart.tsx +3 -1
  58. package/src/components/Chart/HeatmapChart.tsx +50 -37
  59. package/src/components/Chart/LineChart.tsx +3 -2
  60. package/src/components/Chart/MultiAxisChart.tsx +24 -16
  61. package/src/components/Chart/RadarChart.tsx +19 -17
  62. package/src/components/Chart/ScatterChart.tsx +29 -21
  63. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
  64. package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
  65. package/src/components/Countdown/Countdown.stories.tsx +7 -7
  66. package/src/components/DataTable/DataTable.stories.tsx +43 -38
  67. package/src/components/DataTable/DataTable.test.tsx +26 -148
  68. package/src/components/DataTable/DataTable.tsx +485 -456
  69. package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
  70. package/src/components/DatePicker/DatePicker.tsx +31 -26
  71. package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
  72. package/src/components/Dropdown/Dropdown.tsx +313 -299
  73. package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
  74. package/src/components/EdgePanel/EdgePanel.tsx +1 -3
  75. package/src/components/Footer/Footer.stories.tsx +21 -16
  76. package/src/components/Footer/Footer.tsx +130 -128
  77. package/src/components/Footer/FooterLink.tsx +2 -2
  78. package/src/components/Form/Checkbox.test.tsx +49 -49
  79. package/src/components/Form/Checkbox.tsx +108 -100
  80. package/src/components/Form/Form.stories.tsx +2 -10
  81. package/src/components/Form/Input.stories.tsx +22 -39
  82. package/src/components/Form/Input.test.tsx +38 -44
  83. package/src/components/Form/Radio.stories.tsx +6 -12
  84. package/src/components/Form/Radio.tsx +68 -66
  85. package/src/components/Form/Select.tsx +184 -182
  86. package/src/components/Form/Textarea.test.tsx +27 -32
  87. package/src/components/Hero/Hero.stories.tsx +56 -23
  88. package/src/components/Hero/Hero.tsx +201 -55
  89. package/src/components/Icon/index.ts +7 -1
  90. package/src/components/List/List.tsx +19 -23
  91. package/src/components/Modal/Modal.stories.tsx +2 -1
  92. package/src/components/Modal/Modal.tsx +130 -127
  93. package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
  94. package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
  95. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
  96. package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
  97. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
  98. package/src/components/Pagination/Pagination.stories.tsx +7 -4
  99. package/src/components/Pagination/Pagination.tsx +199 -202
  100. package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
  101. package/src/components/Popover/Popover.stories.tsx +99 -192
  102. package/src/components/Popover/Popover.tsx +41 -37
  103. package/src/components/Progress/Progress.stories.tsx +35 -44
  104. package/src/components/River/River.stories.tsx +2 -1
  105. package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
  106. package/src/components/Slider/Slider.stories.tsx +12 -4
  107. package/src/components/Spinner/Spinner.stories.tsx +3 -1
  108. package/src/components/Spinner/Spinner.test.tsx +23 -23
  109. package/src/components/Spinner/Spinner.tsx +43 -46
  110. package/src/components/Steps/Steps.stories.tsx +8 -6
  111. package/src/components/Tabs/Tabs.stories.tsx +12 -9
  112. package/src/components/Tabs/Tabs.tsx +74 -72
  113. package/src/components/Toggle/Toggle.stories.tsx +27 -13
  114. package/src/components/Toggle/Toggle.test.tsx +65 -70
  115. package/src/components/Toggle/Toggle.tsx +4 -1
  116. package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
  117. package/src/components/Tooltip/Tooltip.tsx +104 -106
  118. package/src/components/Upload/Upload.stories.tsx +129 -127
  119. package/src/components/Upload/Upload.tsx +287 -283
  120. package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
  121. package/src/components/index.ts +13 -2
  122. package/src/layouts/Grid/Grid.stories.tsx +9 -3
  123. package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
  124. package/src/lib/__tests__/theme-tools.test.ts +32 -6
  125. package/src/lib/composables/shared-mouse-tracker.ts +13 -14
  126. package/src/lib/composables/useAtomixGlass.ts +106 -49
  127. package/src/lib/composables/useChartExport.ts +1 -1
  128. package/src/lib/composables/useDataTable.ts +29 -17
  129. package/src/lib/composables/useHero.ts +58 -14
  130. package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
  131. package/src/lib/composables/useInput.ts +10 -8
  132. package/src/lib/composables/useSideMenu.ts +6 -5
  133. package/src/lib/composables/useTooltip.ts +1 -2
  134. package/src/lib/composables/useVideoPlayer.ts +44 -35
  135. package/src/lib/config/index.ts +154 -154
  136. package/src/lib/constants/cssVariables.ts +29 -29
  137. package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
  138. package/src/lib/hooks/index.ts +1 -1
  139. package/src/lib/hooks/useComponentCustomization.ts +11 -17
  140. package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
  141. package/src/lib/patterns/__tests__/slots.test.ts +1 -1
  142. package/src/lib/patterns/index.ts +1 -1
  143. package/src/lib/patterns/slots.tsx +8 -13
  144. package/src/lib/storybook/InteractiveDemo.tsx +13 -18
  145. package/src/lib/storybook/PreviewContainer.tsx +1 -1
  146. package/src/lib/storybook/VariantsGrid.tsx +3 -7
  147. package/src/lib/storybook/index.ts +1 -1
  148. package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
  149. package/src/lib/theme/adapters/index.ts +3 -9
  150. package/src/lib/theme/adapters/themeAdapter.ts +41 -26
  151. package/src/lib/theme/config/index.ts +1 -1
  152. package/src/lib/theme/config/types.ts +2 -2
  153. package/src/lib/theme/config/validator.ts +10 -5
  154. package/src/lib/theme/constants/constants.ts +2 -2
  155. package/src/lib/theme/constants/index.ts +1 -2
  156. package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
  157. package/src/lib/theme/core/composeTheme.ts +32 -26
  158. package/src/lib/theme/core/createTheme.ts +1 -1
  159. package/src/lib/theme/core/createThemeObject.ts +308 -301
  160. package/src/lib/theme/core/index.ts +3 -3
  161. package/src/lib/theme/devtools/CLI.ts +106 -104
  162. package/src/lib/theme/devtools/Comparator.tsx +50 -32
  163. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
  164. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
  165. package/src/lib/theme/devtools/Inspector.tsx +75 -60
  166. package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
  167. package/src/lib/theme/devtools/Preview.tsx +150 -106
  168. package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
  169. package/src/lib/theme/devtools/index.ts +3 -9
  170. package/src/lib/theme/devtools/useHistory.ts +23 -21
  171. package/src/lib/theme/errors/errors.ts +12 -11
  172. package/src/lib/theme/errors/index.ts +2 -7
  173. package/src/lib/theme/generators/generateCSS.ts +9 -13
  174. package/src/lib/theme/generators/generateCSSNested.ts +1 -6
  175. package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
  176. package/src/lib/theme/generators/index.ts +1 -4
  177. package/src/lib/theme/i18n/index.ts +1 -1
  178. package/src/lib/theme/i18n/rtl.ts +13 -13
  179. package/src/lib/theme/index.ts +7 -16
  180. package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
  181. package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
  182. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
  183. package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
  184. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
  185. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
  186. package/src/lib/theme/runtime/index.ts +2 -5
  187. package/src/lib/theme/runtime/useTheme.ts +18 -18
  188. package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
  189. package/src/lib/theme/test/testTheme.ts +15 -16
  190. package/src/lib/theme/tokens/index.ts +2 -7
  191. package/src/lib/theme/tokens/tokens.ts +25 -24
  192. package/src/lib/theme/types.ts +428 -411
  193. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
  194. package/src/lib/theme/utils/componentTheming.ts +18 -18
  195. package/src/lib/theme/utils/domUtils.ts +277 -289
  196. package/src/lib/theme/utils/index.ts +1 -2
  197. package/src/lib/theme/utils/injectCSS.ts +10 -14
  198. package/src/lib/theme/utils/naming.ts +20 -16
  199. package/src/lib/theme/utils/themeHelpers.ts +10 -12
  200. package/src/lib/theme/utils/themeUtils.ts +85 -86
  201. package/src/lib/theme/utils/themeValidation.ts +82 -33
  202. package/src/lib/theme-tools.ts +8 -6
  203. package/src/lib/types/components.ts +172 -71
  204. package/src/lib/types/partProps.ts +1 -1
  205. package/src/lib/utils/__tests__/csv.test.ts +1 -1
  206. package/src/lib/utils/componentUtils.ts +8 -12
  207. package/src/lib/utils/csv.ts +3 -1
  208. package/src/lib/utils/dataTableExport.ts +1 -5
  209. package/src/lib/utils/fontPreloader.ts +10 -19
  210. package/src/lib/utils/icons.ts +4 -1
  211. package/src/lib/utils/index.ts +2 -6
  212. package/src/lib/utils/memoryMonitor.ts +10 -8
  213. package/src/lib/utils/themeNaming.ts +2 -2
  214. package/src/styles/01-settings/_index.scss +0 -1
  215. package/src/styles/01-settings/_settings.colors.scss +8 -8
  216. package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
  217. package/src/styles/01-settings/_settings.navbar.scss +1 -1
  218. package/src/styles/01-settings/_settings.spacing.scss +3 -4
  219. package/src/styles/01-settings/_settings.tooltip.scss +1 -1
  220. package/src/styles/01-settings/_settings.typography.scss +1 -1
  221. package/src/styles/02-tools/_tools.button.scss +51 -21
  222. package/src/styles/02-tools/_tools.utility-api.scss +30 -18
  223. package/src/styles/03-generic/_generic.root.scss +4 -3
  224. package/src/styles/06-components/_components.atomix-glass.scss +13 -9
  225. package/src/styles/06-components/_components.button.scss +16 -4
  226. package/src/styles/06-components/_components.callout.scss +27 -21
  227. package/src/styles/06-components/_components.card.scss +5 -14
  228. package/src/styles/06-components/_components.chart.scss +22 -19
  229. package/src/styles/06-components/_components.checkbox.scss +3 -1
  230. package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
  231. package/src/styles/06-components/_components.edge-panel.scss +9 -2
  232. package/src/styles/06-components/_components.footer.scss +1 -1
  233. package/src/styles/06-components/_components.side-menu.scss +5 -5
  234. package/src/styles/06-components/_components.toggle.scss +18 -0
  235. package/src/styles/06-components/_index.scss +1 -1
  236. package/src/styles/06-components/old.chart.styles.scss +0 -2
  237. package/src/styles/99-utilities/_utilities.border.scss +69 -27
  238. package/src/styles/99-utilities/_utilities.display.scss +1 -1
  239. package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
  240. package/src/styles/99-utilities/_utilities.position.scss +16 -9
  241. package/src/styles/99-utilities/_utilities.scss +1 -1
  242. package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
  243. package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
  244. package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
  245. package/src/styles/99-utilities/_utilities.text.scss +67 -46
@@ -230,18 +230,13 @@ const DemoPanelContent = ({
230
230
  );
231
231
 
232
232
  export const BasicUsage: Story = {
233
- render: (args) => {
233
+ render: args => {
234
234
  const [isOpen, setIsOpen] = useState(false);
235
235
 
236
236
  return (
237
237
  <>
238
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
- >
239
+ <EdgePanel {...args} isOpen={isOpen} onOpenChange={setIsOpen} title="Basic Edge Panel">
245
240
  <DemoPanelContent {...args} />
246
241
  </EdgePanel>
247
242
  </>
@@ -271,7 +266,7 @@ export const AllPositions: Story = {
271
266
  return (
272
267
  <>
273
268
  <div className="u-flex u-gap-2 u-flex-wrap">
274
- {(['start', 'end', 'top', 'bottom'] as const).map((pos) => (
269
+ {(['start', 'end', 'top', 'bottom'] as const).map(pos => (
275
270
  <Button
276
271
  key={pos}
277
272
  variant={position === pos ? 'primary' : 'secondary'}
@@ -306,18 +301,13 @@ export const AllPositions: Story = {
306
301
  };
307
302
 
308
303
  export const WithSlideMode: Story = {
309
- render: (args) => {
304
+ render: args => {
310
305
  const [isOpen, setIsOpen] = useState(false);
311
306
 
312
307
  return (
313
308
  <>
314
309
  <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
- >
310
+ <EdgePanel {...args} isOpen={isOpen} onOpenChange={setIsOpen} title="Slide Mode Panel">
321
311
  <DemoPanelContent {...args} />
322
312
  </EdgePanel>
323
313
  </>
@@ -834,10 +824,7 @@ export const GlassShowcase: Story = {
834
824
  <p className="u-mb-4">
835
825
  Enhanced polar distortion creates unique radial patterns from center.
836
826
  </p>
837
- <Card
838
- title="Radial Distortion"
839
- text="Creates circular displacement patterns."
840
- />
827
+ <Card title="Radial Distortion" text="Creates circular displacement patterns." />
841
828
  </div>
842
829
  </EdgePanel>
843
830
 
@@ -125,9 +125,7 @@ export const EdgePanel: React.FC<EdgePanelProps> = ({
125
125
  )}
126
126
  <div ref={containerRef} className="c-edge-panel__container">
127
127
  {glass ? (
128
- <AtomixGlass
129
- {...glassProps}
130
- >
128
+ <AtomixGlass {...glassProps}>
131
129
  <div
132
130
  ref={glassContentRef}
133
131
  className="c-edge-panel__glass-content"
@@ -97,7 +97,10 @@ Footer provides a comprehensive footer section for websites with multiple layout
97
97
  options: ['columns', 'centered', 'minimal', 'stacked', 'flexible', 'sidebar', 'wide'],
98
98
  description: 'Footer layout variant',
99
99
  table: {
100
- type: { summary: '"columns" | "centered" | "minimal" | "stacked" | "flexible" | "sidebar" | "wide"' },
100
+ type: {
101
+ summary:
102
+ '"columns" | "centered" | "minimal" | "stacked" | "flexible" | "sidebar" | "wide"',
103
+ },
101
104
  defaultValue: { summary: 'columns' },
102
105
  },
103
106
  },
@@ -289,7 +292,7 @@ export const BasicUsage: Story = {
289
292
  copyright: '© 2024 Atomix. All rights reserved.',
290
293
  socialLinks: sampleSocialLinks,
291
294
  },
292
- render: (args) => (
295
+ render: args => (
293
296
  <Footer {...args}>
294
297
  <SampleFooterContent />
295
298
  </Footer>
@@ -316,7 +319,7 @@ export const WithNewsletter: Story = {
316
319
  onNewsletterSubmit: fn(),
317
320
  socialLinks: sampleSocialLinks,
318
321
  },
319
- render: (args) => (
322
+ render: args => (
320
323
  <Footer {...args}>
321
324
  <SampleFooterContent />
322
325
  </Footer>
@@ -340,7 +343,7 @@ export const WithBackToTop: Story = {
340
343
  onBackToTop: fn(),
341
344
  socialLinks: sampleSocialLinks,
342
345
  },
343
- render: (args) => (
346
+ render: args => (
344
347
  <Footer {...args}>
345
348
  <SampleFooterContent />
346
349
  </Footer>
@@ -362,7 +365,7 @@ export const CenteredLayout: Story = {
362
365
  copyright: '© 2024 Atomix. All rights reserved.',
363
366
  socialLinks: sampleSocialLinks,
364
367
  },
365
- render: (args) => (
368
+ render: args => (
366
369
  <Footer {...args}>
367
370
  <SampleFooterContent />
368
371
  </Footer>
@@ -384,7 +387,7 @@ export const MinimalLayout: Story = {
384
387
  copyright: '© 2024 Atomix. All rights reserved.',
385
388
  socialLinks: sampleSocialLinks,
386
389
  },
387
- render: (args) => (
390
+ render: args => (
388
391
  <Footer {...args}>
389
392
  <SampleFooterContent />
390
393
  </Footer>
@@ -406,7 +409,7 @@ export const StackedLayout: Story = {
406
409
  copyright: '© 2024 Atomix. All rights reserved.',
407
410
  socialLinks: sampleSocialLinks,
408
411
  },
409
- render: (args) => (
412
+ render: args => (
410
413
  <Footer {...args}>
411
414
  <SampleFooterContent />
412
415
  </Footer>
@@ -428,7 +431,7 @@ export const FlexibleLayout: Story = {
428
431
  copyright: '© 2024 Atomix. All rights reserved.',
429
432
  socialLinks: sampleSocialLinks,
430
433
  },
431
- render: (args) => (
434
+ render: args => (
432
435
  <Footer {...args}>
433
436
  <SampleFooterContent />
434
437
  </Footer>
@@ -450,7 +453,7 @@ export const SidebarLayout: Story = {
450
453
  copyright: '© 2024 Atomix. All rights reserved.',
451
454
  socialLinks: sampleSocialLinks,
452
455
  },
453
- render: (args) => (
456
+ render: args => (
454
457
  <Footer {...args}>
455
458
  <SampleFooterContent />
456
459
  </Footer>
@@ -472,7 +475,7 @@ export const WideLayout: Story = {
472
475
  copyright: '© 2024 Atomix. All rights reserved.',
473
476
  socialLinks: sampleSocialLinks,
474
477
  },
475
- render: (args) => (
478
+ render: args => (
476
479
  <Footer {...args}>
477
480
  <SampleFooterContent />
478
481
  </Footer>
@@ -494,7 +497,7 @@ export const DarkVariant: Story = {
494
497
  copyright: '© 2024 Atomix. All rights reserved.',
495
498
  socialLinks: sampleSocialLinks,
496
499
  },
497
- render: (args) => (
500
+ render: args => (
498
501
  <Footer {...args}>
499
502
  <SampleFooterContent />
500
503
  </Footer>
@@ -516,7 +519,7 @@ export const LargeSize: Story = {
516
519
  copyright: '© 2024 Atomix. All rights reserved.',
517
520
  socialLinks: sampleSocialLinks,
518
521
  },
519
- render: (args) => (
522
+ render: args => (
520
523
  <Footer {...args}>
521
524
  <SampleFooterContent />
522
525
  </Footer>
@@ -538,7 +541,7 @@ export const WithGlassEffect: Story = {
538
541
  socialLinks: sampleSocialLinks,
539
542
  glass: true,
540
543
  },
541
- render: (args) => (
544
+ render: args => (
542
545
  <Footer {...args}>
543
546
  <SampleFooterContent />
544
547
  </Footer>
@@ -560,9 +563,11 @@ export const StickyFooter: Story = {
560
563
  copyright: '© 2024 Atomix. All rights reserved.',
561
564
  socialLinks: sampleSocialLinks,
562
565
  },
563
- render: (args) => (
566
+ render: args => (
564
567
  <div style={{ minHeight: '200vh' }}>
565
- <div style={{ height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
568
+ <div
569
+ style={{ height: '100vh', display: 'flex', alignItems: 'center', justifyContent: 'center' }}
570
+ >
566
571
  <p>Scroll down to see the sticky footer</p>
567
572
  </div>
568
573
  <Footer {...args}>
@@ -577,4 +582,4 @@ export const StickyFooter: Story = {
577
582
  },
578
583
  },
579
584
  },
580
- };
585
+ };
@@ -149,143 +149,145 @@ export const Footer = forwardRef<HTMLElement, FooterProps>(
149
149
 
150
150
  const footerContent = (
151
151
  <div className={containerClass}>
152
- {/* Main Footer Content */}
153
- <Grid
154
- className={sectionsClass}
155
- alignItems="start"
156
- justifyContent={layout === 'centered' ? 'center' : undefined}
157
- >
158
- {/* Brand Section */}
159
- {(brand || brandLogo || brandDescription) && (
160
- <GridCol {...(getResponsiveColumnProps('brand') as any)} className={brandClass}>
161
- {brandLogo && (
162
- <div className="c-footer__brand-logo">
163
- {typeof brandLogo === 'string' ? (
164
- <img src={brandLogo} alt={'Brand Logo'} />
165
- ) : (
166
- brandLogo
167
- )}
168
- </div>
169
- )}
170
- {brand && (
171
- <div className="c-footer__brand-name">
172
- {typeof brand === 'string' ? <h3>{brand}</h3> : brand}
173
- </div>
174
- )}
175
- {brandDescription && (
176
- <div className="c-footer__brand-description">{brandDescription}</div>
177
- )}
178
- {socialLinks.length > 0 && (
179
- <div className="c-footer__social" data-testid="footer-social-links">
180
- {socialLinks.map((link, index) => (
181
- <FooterSocialLink
182
- key={`${link.platform}-${index}`}
183
- platform={link.platform}
184
- url={link.url}
185
- icon={link.icon}
186
- label={link.label}
187
- size={size}
188
- />
189
- ))}
190
- </div>
191
- )}
192
- </GridCol>
193
- )}
194
-
195
- {/* Footer Sections */}
196
- {children && (
197
- <GridCol
198
- {...(getResponsiveColumnProps('content') as any)}
199
- className="c-footer__content"
200
- >
201
- <Grid
202
- className="c-footer__sections"
203
- alignItems={layout === 'centered' || layout === 'stacked' ? 'center' : undefined}
204
- >
205
- {React.Children.map(children, child => {
206
- // Check if the child is a valid React element
207
- if (React.isValidElement(child)) {
208
- // Clone the element and pass the showNewsletter prop
209
- return React.cloneElement(child, { showNewsletter } as any);
210
- }
211
- return child;
212
- })}
213
- </Grid>
214
- </GridCol>
215
- )}
152
+ {/* Main Footer Content */}
153
+ <Grid
154
+ className={sectionsClass}
155
+ alignItems="start"
156
+ justifyContent={layout === 'centered' ? 'center' : undefined}
157
+ >
158
+ {/* Brand Section */}
159
+ {(brand || brandLogo || brandDescription) && (
160
+ <GridCol {...(getResponsiveColumnProps('brand') as any)} className={brandClass}>
161
+ {brandLogo && (
162
+ <div className="c-footer__brand-logo">
163
+ {typeof brandLogo === 'string' ? (
164
+ <img src={brandLogo} alt={'Brand Logo'} />
165
+ ) : (
166
+ brandLogo
167
+ )}
168
+ </div>
169
+ )}
170
+ {brand && (
171
+ <div className="c-footer__brand-name">
172
+ {typeof brand === 'string' ? <h3>{brand}</h3> : brand}
173
+ </div>
174
+ )}
175
+ {brandDescription && (
176
+ <div className="c-footer__brand-description">{brandDescription}</div>
177
+ )}
178
+ {socialLinks.length > 0 && (
179
+ <div className="c-footer__social" data-testid="footer-social-links">
180
+ {socialLinks.map((link, index) => (
181
+ <FooterSocialLink
182
+ key={`${link.platform}-${index}`}
183
+ platform={link.platform}
184
+ url={link.url}
185
+ icon={link.icon}
186
+ label={link.label}
187
+ size={size}
188
+ />
189
+ ))}
190
+ </div>
191
+ )}
192
+ </GridCol>
193
+ )}
216
194
 
217
- {/* Newsletter Section */}
218
- {showNewsletter && (
219
- <GridCol
220
- {...(getResponsiveColumnProps('newsletter') as any)}
221
- className="c-footer__newsletter"
195
+ {/* Footer Sections */}
196
+ {children && (
197
+ <GridCol
198
+ {...(getResponsiveColumnProps('content') as any)}
199
+ className="c-footer__content"
200
+ >
201
+ <Grid
202
+ className="c-footer__sections"
203
+ alignItems={layout === 'centered' || layout === 'stacked' ? 'center' : undefined}
222
204
  >
223
- <h4 className="c-footer__newsletter-title">{newsletterTitle}</h4>
224
- {newsletterDescription && (
225
- <p className="c-footer__newsletter-description">{newsletterDescription}</p>
226
- )}
227
- <Form
228
- className="c-footer__newsletter-form"
229
- onSubmit={e => {
230
- e.preventDefault();
231
- const formData = new FormData(e.currentTarget);
232
- const email = formData.get('email') as string;
233
- if (email) handleNewsletterSubmit(email);
234
- }}
235
- >
236
- <div className="c-footer__newsletter-input-group">
237
- <Input
238
- type="email"
239
- name="email"
240
- className="c-footer__newsletter-input"
241
- placeholder={newsletterPlaceholder}
242
- required
243
- />
244
- <Button type="submit" className="c-footer__newsletter-button">
245
- {newsletterButtonText}
246
- </Button>
247
- </div>
248
- </Form>
249
- </GridCol>
250
- )}
251
- </Grid>
205
+ {React.Children.map(children, child => {
206
+ // Check if the child is a valid React element
207
+ if (React.isValidElement(child)) {
208
+ // Clone the element and pass the showNewsletter prop
209
+ return React.cloneElement(child, { showNewsletter } as any);
210
+ }
211
+ return child;
212
+ })}
213
+ </Grid>
214
+ </GridCol>
215
+ )}
252
216
 
253
- {(copyright || showBackToTop) && (
254
- <div className={bottomClass}>
255
- {copyright && <div className="c-footer__copyright">{copyright}</div>}
256
- {showBackToTop && (
257
- <Button
258
- variant="ghost"
259
- className="c-footer__back-to-top"
260
- onClick={handleBackToTop}
261
- disabled={disabled}
262
- aria-label={backToTopText}
263
- >
264
- <span className="c-footer__back-to-top-icon">↑</span>
265
- <span className="c-footer__back-to-top-text">{backToTopText}</span>
266
- </Button>
217
+ {/* Newsletter Section */}
218
+ {showNewsletter && (
219
+ <GridCol
220
+ {...(getResponsiveColumnProps('newsletter') as any)}
221
+ className="c-footer__newsletter"
222
+ >
223
+ <h4 className="c-footer__newsletter-title">{newsletterTitle}</h4>
224
+ {newsletterDescription && (
225
+ <p className="c-footer__newsletter-description">{newsletterDescription}</p>
267
226
  )}
268
- </div>
227
+ <Form
228
+ className="c-footer__newsletter-form"
229
+ onSubmit={e => {
230
+ e.preventDefault();
231
+ const formData = new FormData(e.currentTarget);
232
+ const email = formData.get('email') as string;
233
+ if (email) handleNewsletterSubmit(email);
234
+ }}
235
+ >
236
+ <div className="c-footer__newsletter-input-group">
237
+ <Input
238
+ type="email"
239
+ name="email"
240
+ className="c-footer__newsletter-input"
241
+ placeholder={newsletterPlaceholder}
242
+ required
243
+ />
244
+ <Button type="submit" className="c-footer__newsletter-button">
245
+ {newsletterButtonText}
246
+ </Button>
247
+ </div>
248
+ </Form>
249
+ </GridCol>
269
250
  )}
270
- </div>
251
+ </Grid>
252
+
253
+ {(copyright || showBackToTop) && (
254
+ <div className={bottomClass}>
255
+ {copyright && <div className="c-footer__copyright">{copyright}</div>}
256
+ {showBackToTop && (
257
+ <Button
258
+ variant="ghost"
259
+ className="c-footer__back-to-top"
260
+ onClick={handleBackToTop}
261
+ disabled={disabled}
262
+ aria-label={backToTopText}
263
+ >
264
+ <span className="c-footer__back-to-top-icon">↑</span>
265
+ <span className="c-footer__back-to-top-text">{backToTopText}</span>
266
+ </Button>
267
+ )}
268
+ </div>
269
+ )}
270
+ </div>
271
271
  );
272
272
 
273
273
  return (
274
- <footer ref={ref} className={footerClass + ` c-footer ${glass ? 'c-footer--glass' : ''}`} {...props}>
275
- {glass ? (
276
- <AtomixGlass {...(glass as unknown as AtomixGlassProps)} elasticity={0}>
277
- <div className="c-footer__glass">
278
- {footerContent}
279
- </div>
280
- </AtomixGlass>
281
- ) : (
282
- footerContent
283
- )}
284
- </footer>
285
- );
286
- }
274
+ <footer
275
+ ref={ref}
276
+ className={footerClass + ` c-footer ${glass ? 'c-footer--glass' : ''}`}
277
+ {...props}
278
+ >
279
+ {glass ? (
280
+ <AtomixGlass {...(glass as unknown as AtomixGlassProps)} elasticity={0}>
281
+ <div className="c-footer__glass">{footerContent}</div>
282
+ </AtomixGlass>
283
+ ) : (
284
+ footerContent
285
+ )}
286
+ </footer>
287
+ );
288
+ }
287
289
  );
288
290
 
289
291
  Footer.displayName = 'Footer';
290
292
 
291
- export default Footer;
293
+ export default Footer;
@@ -55,7 +55,7 @@ export const FooterLink = forwardRef<HTMLAnchorElement, FooterLinkProps>(
55
55
  ...(href && !disabled ? { to: href } : {}),
56
56
  ...linkProps,
57
57
  };
58
-
58
+
59
59
  return (
60
60
  <Component {...componentProps}>
61
61
  {icon && <span className="c-footer__link-icon">{icon}</span>}
@@ -77,4 +77,4 @@ export const FooterLink = forwardRef<HTMLAnchorElement, FooterLinkProps>(
77
77
 
78
78
  FooterLink.displayName = 'FooterLink';
79
79
 
80
- export default FooterLink;
80
+ export default FooterLink;
@@ -8,56 +8,56 @@ expect.extend(toHaveNoViolations);
8
8
 
9
9
  // Mock AtomixGlass
10
10
  vi.mock('../AtomixGlass/AtomixGlass', () => ({
11
- AtomixGlass: ({ children }: any) => <div>{children}</div>,
11
+ AtomixGlass: ({ children }: any) => <div>{children}</div>,
12
12
  }));
13
13
 
14
14
  describe('Checkbox Component', () => {
15
- it('renders correctly with label', () => {
16
- render(<Checkbox label="Accept Terms" />);
17
- // In current implementation, if no ID is provided, htmlFor is undefined, so label is not associated.
18
- // screen.getByLabelText might fail or might not find the input.
19
- // Let's see.
20
- expect(screen.getByText('Accept Terms')).toBeInTheDocument();
21
- });
22
-
23
- it('associates label with input when ID is provided', () => {
24
- render(<Checkbox label="Subscribe" id="subscribe-check" />);
25
- expect(screen.getByLabelText('Subscribe')).toBeInTheDocument();
26
- });
27
-
28
- it('associates label with input WITHOUT ID', () => {
29
- // This tests my proposed improvement: wrapping input in label or auto-ID
30
- render(<Checkbox label="No ID Checkbox" />);
31
- // If not associated, this throws
32
- expect(screen.getByLabelText('No ID Checkbox')).toBeInTheDocument();
33
- });
34
-
35
- it('handles checked state', () => {
36
- const handleChange = vi.fn();
37
- render(<Checkbox checked onChange={handleChange} label="Checked" id="checked-id" />);
38
- const input = screen.getByLabelText('Checked');
39
- expect(input).toBeChecked();
40
-
41
- fireEvent.click(input);
42
- expect(handleChange).toHaveBeenCalledTimes(1);
43
- });
44
-
45
- it('forwards ref', () => {
46
- const ref = React.createRef<HTMLInputElement>();
47
- render(<Checkbox ref={ref} label="Ref Checkbox" />);
48
- expect(ref.current).toBeInstanceOf(HTMLInputElement);
49
- });
50
-
51
- it('handles indeterminate state', () => {
52
- // This might need manual DOM check as indeterminate is a property, not attribute
53
- const { getByRole } = render(<Checkbox indeterminate label="Indeterminate" id="indet" />);
54
- const input = getByRole('checkbox') as HTMLInputElement;
55
- expect(input.indeterminate).toBe(true);
56
- });
57
-
58
- it('should have no accessibility violations', async () => {
59
- const { container } = render(<Checkbox label="Accessible Checkbox" id="a11y-check" />);
60
- const results = await axe(container);
61
- expect(results).toHaveNoViolations();
62
- });
15
+ it('renders correctly with label', () => {
16
+ render(<Checkbox label="Accept Terms" />);
17
+ // In current implementation, if no ID is provided, htmlFor is undefined, so label is not associated.
18
+ // screen.getByLabelText might fail or might not find the input.
19
+ // Let's see.
20
+ expect(screen.getByText('Accept Terms')).toBeInTheDocument();
21
+ });
22
+
23
+ it('associates label with input when ID is provided', () => {
24
+ render(<Checkbox label="Subscribe" id="subscribe-check" />);
25
+ expect(screen.getByLabelText('Subscribe')).toBeInTheDocument();
26
+ });
27
+
28
+ it('associates label with input WITHOUT ID', () => {
29
+ // This tests my proposed improvement: wrapping input in label or auto-ID
30
+ render(<Checkbox label="No ID Checkbox" />);
31
+ // If not associated, this throws
32
+ expect(screen.getByLabelText('No ID Checkbox')).toBeInTheDocument();
33
+ });
34
+
35
+ it('handles checked state', () => {
36
+ const handleChange = vi.fn();
37
+ render(<Checkbox checked onChange={handleChange} label="Checked" id="checked-id" />);
38
+ const input = screen.getByLabelText('Checked');
39
+ expect(input).toBeChecked();
40
+
41
+ fireEvent.click(input);
42
+ expect(handleChange).toHaveBeenCalledTimes(1);
43
+ });
44
+
45
+ it('forwards ref', () => {
46
+ const ref = React.createRef<HTMLInputElement>();
47
+ render(<Checkbox ref={ref} label="Ref Checkbox" />);
48
+ expect(ref.current).toBeInstanceOf(HTMLInputElement);
49
+ });
50
+
51
+ it('handles indeterminate state', () => {
52
+ // This might need manual DOM check as indeterminate is a property, not attribute
53
+ const { getByRole } = render(<Checkbox indeterminate label="Indeterminate" id="indet" />);
54
+ const input = getByRole('checkbox') as HTMLInputElement;
55
+ expect(input.indeterminate).toBe(true);
56
+ });
57
+
58
+ it('should have no accessibility violations', async () => {
59
+ const { container } = render(<Checkbox label="Accessible Checkbox" id="a11y-check" />);
60
+ const results = await axe(container);
61
+ expect(results).toHaveNoViolations();
62
+ });
63
63
  });