@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.
- package/build-tools/index.d.ts +31 -30
- package/build-tools/package.json +4 -21
- package/dist/atomix.css +20924 -2611
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +76 -2
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/index.d.ts +31 -30
- package/dist/build-tools/package.json +4 -21
- package/dist/charts.js.map +1 -1
- package/dist/core.js.map +1 -1
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +144 -18
- package/dist/index.esm.js +110 -55
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +110 -55
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +9 -9
- package/dist/theme.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Accordion/Accordion.stories.tsx +32 -23
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +99 -94
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/glass-utils.ts +4 -3
- package/src/components/AtomixGlass/shader-utils.ts +128 -52
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
- package/src/components/Avatar/Avatar.stories.tsx +45 -62
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +20 -9
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +14 -4
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
- package/src/components/Button/Button.stories.tsx +13 -22
- package/src/components/Button/Button.test.tsx +97 -81
- package/src/components/Button/Button.tsx +46 -14
- package/src/components/Button/ButtonGroup.stories.tsx +37 -32
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +109 -16
- package/src/components/Card/Card.stories.tsx +67 -36
- package/src/components/Card/Card.tsx +30 -14
- package/src/components/Chart/AreaChart.tsx +1 -1
- package/src/components/Chart/CandlestickChart.tsx +23 -16
- package/src/components/Chart/Chart.stories.tsx +4 -9
- package/src/components/Chart/Chart.tsx +40 -44
- package/src/components/Chart/ChartRenderer.tsx +39 -12
- package/src/components/Chart/ChartToolbar.tsx +21 -5
- package/src/components/Chart/DonutChart.tsx +1 -1
- package/src/components/Chart/FunnelChart.tsx +4 -1
- package/src/components/Chart/GaugeChart.tsx +3 -1
- package/src/components/Chart/HeatmapChart.tsx +50 -37
- package/src/components/Chart/LineChart.tsx +3 -2
- package/src/components/Chart/MultiAxisChart.tsx +24 -16
- package/src/components/Chart/RadarChart.tsx +19 -17
- package/src/components/Chart/ScatterChart.tsx +29 -21
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +7 -7
- package/src/components/DataTable/DataTable.stories.tsx +43 -38
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +313 -299
- package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Footer/Footer.stories.tsx +21 -16
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.test.tsx +49 -49
- package/src/components/Form/Checkbox.tsx +108 -100
- package/src/components/Form/Form.stories.tsx +2 -10
- package/src/components/Form/Input.stories.tsx +22 -39
- package/src/components/Form/Input.test.tsx +38 -44
- package/src/components/Form/Radio.stories.tsx +6 -12
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.tsx +184 -182
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +56 -23
- package/src/components/Hero/Hero.tsx +201 -55
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.tsx +19 -23
- package/src/components/Modal/Modal.stories.tsx +2 -1
- package/src/components/Modal/Modal.tsx +130 -127
- package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
- package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
- package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
- package/src/components/Pagination/Pagination.stories.tsx +7 -4
- package/src/components/Pagination/Pagination.tsx +199 -202
- package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
- package/src/components/Popover/Popover.stories.tsx +99 -192
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +35 -44
- package/src/components/River/River.stories.tsx +2 -1
- package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +3 -1
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +8 -6
- package/src/components/Tabs/Tabs.stories.tsx +12 -9
- package/src/components/Tabs/Tabs.tsx +74 -72
- package/src/components/Toggle/Toggle.stories.tsx +27 -13
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +129 -127
- package/src/components/Upload/Upload.tsx +287 -283
- package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
- package/src/components/index.ts +13 -2
- package/src/layouts/Grid/Grid.stories.tsx +9 -3
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
- package/src/lib/__tests__/theme-tools.test.ts +32 -6
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +106 -49
- package/src/lib/composables/useChartExport.ts +1 -1
- package/src/lib/composables/useDataTable.ts +29 -17
- package/src/lib/composables/useHero.ts +58 -14
- package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
- package/src/lib/composables/useInput.ts +10 -8
- package/src/lib/composables/useSideMenu.ts +6 -5
- package/src/lib/composables/useTooltip.ts +1 -2
- package/src/lib/composables/useVideoPlayer.ts +44 -35
- package/src/lib/config/index.ts +154 -154
- package/src/lib/constants/cssVariables.ts +29 -29
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
- package/src/lib/hooks/index.ts +1 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -17
- package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
- package/src/lib/patterns/__tests__/slots.test.ts +1 -1
- package/src/lib/patterns/index.ts +1 -1
- package/src/lib/patterns/slots.tsx +8 -13
- package/src/lib/storybook/InteractiveDemo.tsx +13 -18
- package/src/lib/storybook/PreviewContainer.tsx +1 -1
- package/src/lib/storybook/VariantsGrid.tsx +3 -7
- package/src/lib/storybook/index.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
- package/src/lib/theme/adapters/index.ts +3 -9
- package/src/lib/theme/adapters/themeAdapter.ts +41 -26
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +10 -5
- package/src/lib/theme/constants/constants.ts +2 -2
- package/src/lib/theme/constants/index.ts +1 -2
- package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
- package/src/lib/theme/core/composeTheme.ts +32 -26
- package/src/lib/theme/core/createTheme.ts +1 -1
- package/src/lib/theme/core/createThemeObject.ts +308 -301
- package/src/lib/theme/core/index.ts +3 -3
- package/src/lib/theme/devtools/CLI.ts +106 -104
- package/src/lib/theme/devtools/Comparator.tsx +50 -32
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
- package/src/lib/theme/devtools/Inspector.tsx +75 -60
- package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
- package/src/lib/theme/devtools/Preview.tsx +150 -106
- package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
- package/src/lib/theme/devtools/index.ts +3 -9
- package/src/lib/theme/devtools/useHistory.ts +23 -21
- package/src/lib/theme/errors/errors.ts +12 -11
- package/src/lib/theme/errors/index.ts +2 -7
- package/src/lib/theme/generators/generateCSS.ts +9 -13
- package/src/lib/theme/generators/generateCSSNested.ts +1 -6
- package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/i18n/index.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +13 -13
- package/src/lib/theme/index.ts +7 -16
- package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
- package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
- package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
- package/src/lib/theme/runtime/index.ts +2 -5
- package/src/lib/theme/runtime/useTheme.ts +18 -18
- package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
- package/src/lib/theme/test/testTheme.ts +15 -16
- package/src/lib/theme/tokens/index.ts +2 -7
- package/src/lib/theme/tokens/tokens.ts +25 -24
- package/src/lib/theme/types.ts +428 -411
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
- package/src/lib/theme/utils/componentTheming.ts +18 -18
- package/src/lib/theme/utils/domUtils.ts +277 -289
- package/src/lib/theme/utils/index.ts +1 -2
- package/src/lib/theme/utils/injectCSS.ts +10 -14
- package/src/lib/theme/utils/naming.ts +20 -16
- package/src/lib/theme/utils/themeHelpers.ts +10 -12
- package/src/lib/theme/utils/themeUtils.ts +85 -86
- package/src/lib/theme/utils/themeValidation.ts +82 -33
- package/src/lib/theme-tools.ts +8 -6
- package/src/lib/types/components.ts +172 -71
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +1 -1
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +3 -1
- package/src/lib/utils/dataTableExport.ts +1 -5
- package/src/lib/utils/fontPreloader.ts +10 -19
- package/src/lib/utils/icons.ts +4 -1
- package/src/lib/utils/index.ts +2 -6
- package/src/lib/utils/memoryMonitor.ts +10 -8
- package/src/lib/utils/themeNaming.ts +2 -2
- package/src/styles/01-settings/_index.scss +0 -1
- package/src/styles/01-settings/_settings.colors.scss +8 -8
- package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +3 -4
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.typography.scss +1 -1
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +30 -18
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.atomix-glass.scss +13 -9
- package/src/styles/06-components/_components.button.scss +16 -4
- package/src/styles/06-components/_components.callout.scss +27 -21
- package/src/styles/06-components/_components.card.scss +5 -14
- package/src/styles/06-components/_components.chart.scss +22 -19
- package/src/styles/06-components/_components.checkbox.scss +3 -1
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
- package/src/styles/06-components/_components.edge-panel.scss +9 -2
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.side-menu.scss +5 -5
- package/src/styles/06-components/_components.toggle.scss +18 -0
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/06-components/old.chart.styles.scss +0 -2
- package/src/styles/99-utilities/_utilities.border.scss +69 -27
- package/src/styles/99-utilities/_utilities.display.scss +1 -1
- package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
- package/src/styles/99-utilities/_utilities.position.scss +16 -9
- package/src/styles/99-utilities/_utilities.scss +1 -1
- package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
- package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
- package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
- 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:
|
|
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(
|
|
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:
|
|
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: {
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
566
|
+
render: args => (
|
|
564
567
|
<div style={{ minHeight: '200vh' }}>
|
|
565
|
-
<div
|
|
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
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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
|
-
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
{
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
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
|
-
|
|
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
|
-
</
|
|
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
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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
|
-
|
|
11
|
+
AtomixGlass: ({ children }: any) => <div>{children}</div>,
|
|
12
12
|
}));
|
|
13
13
|
|
|
14
14
|
describe('Checkbox Component', () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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
|
});
|