@shohojdhara/atomix 0.3.15 → 0.4.1
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 +20234 -2027
- 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 +4 -5
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +87 -10
- package/dist/core.js +673 -480
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +15 -3
- package/dist/forms.js +530 -97
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +5 -6
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +644 -277
- package/dist/index.esm.js +1948 -1347
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3333 -2728
- 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 +2 -2
- package/scripts/atomix-cli.js +10 -1
- package/scripts/cli/__tests__/utils.test.js +6 -2
- package/scripts/cli/migration-tools.js +2 -2
- package/scripts/cli/theme-bridge.js +7 -9
- package/scripts/cli/utils.js +2 -1
- package/src/components/Accordion/Accordion.stories.tsx +72 -23
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +219 -96
- package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
- 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 +173 -65
- package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
- 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 +166 -918
- package/src/components/Callout/Callout.tsx +196 -84
- package/src/components/Callout/CalloutCompound.test.tsx +72 -0
- 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 +425 -298
- package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
- package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
- package/src/components/EdgePanel/EdgePanel.tsx +163 -113
- package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
- 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.stories.tsx +23 -0
- package/src/components/Form/Select.test.tsx +99 -0
- package/src/components/Form/Select.tsx +239 -186
- package/src/components/Form/SelectOption.tsx +88 -0
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +93 -23
- package/src/components/Hero/Hero.test.tsx +142 -0
- package/src/components/Hero/Hero.tsx +343 -58
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.test.tsx +62 -0
- package/src/components/List/List.tsx +32 -25
- package/src/components/List/ListItem.tsx +20 -0
- package/src/components/Modal/Modal.stories.tsx +67 -2
- package/src/components/Modal/Modal.tsx +208 -125
- package/src/components/Modal/ModalCompound.test.tsx +94 -0
- 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/Steps/Steps.tsx +124 -21
- package/src/components/Steps/StepsCompound.test.tsx +81 -0
- package/src/components/Tabs/Tabs.stories.tsx +12 -9
- package/src/components/Tabs/Tabs.tsx +230 -75
- package/src/components/Tabs/TabsCompound.test.tsx +64 -0
- 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/index.ts +0 -4
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +102 -60
- 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 +105 -111
- 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 +180 -73
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
- package/src/lib/utils/__tests__/csv.test.ts +1 -1
- package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
- 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 +3 -3
- 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.breakpoints.scss +1 -1
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +36 -24
- 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 -47
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
import { Tabs } from './Tabs';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
describe('Tabs Component', () => {
|
|
7
|
+
it('renders correctly with legacy props', () => {
|
|
8
|
+
const items = [
|
|
9
|
+
{ label: 'Tab 1', content: 'Content 1' },
|
|
10
|
+
{ label: 'Tab 2', content: 'Content 2' },
|
|
11
|
+
];
|
|
12
|
+
render(<Tabs items={items} />);
|
|
13
|
+
|
|
14
|
+
expect(screen.getByText('Tab 1')).toBeInTheDocument();
|
|
15
|
+
expect(screen.getByText('Tab 2')).toBeInTheDocument();
|
|
16
|
+
expect(screen.getByText('Content 1')).toBeVisible();
|
|
17
|
+
|
|
18
|
+
// Content 2 is rendered but hidden
|
|
19
|
+
const content2 = screen.getByText('Content 2').closest('.c-tabs__panel');
|
|
20
|
+
expect(content2).toHaveStyle({ height: '0px', opacity: '0' });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it('renders correctly with compound components', () => {
|
|
24
|
+
render(
|
|
25
|
+
<Tabs>
|
|
26
|
+
<Tabs.List>
|
|
27
|
+
<Tabs.Trigger index={0}>Tab 1</Tabs.Trigger>
|
|
28
|
+
<Tabs.Trigger index={1}>Tab 2</Tabs.Trigger>
|
|
29
|
+
</Tabs.List>
|
|
30
|
+
<Tabs.Panels>
|
|
31
|
+
<Tabs.Panel index={0}>Content 1</Tabs.Panel>
|
|
32
|
+
<Tabs.Panel index={1}>Content 2</Tabs.Panel>
|
|
33
|
+
</Tabs.Panels>
|
|
34
|
+
</Tabs>
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
expect(screen.getByText('Tab 1')).toBeInTheDocument();
|
|
38
|
+
expect(screen.getByText('Tab 2')).toBeInTheDocument();
|
|
39
|
+
expect(screen.getByText('Content 1')).toBeVisible();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('switches tabs in compound mode', () => {
|
|
43
|
+
render(
|
|
44
|
+
<Tabs>
|
|
45
|
+
<Tabs.List>
|
|
46
|
+
<Tabs.Trigger index={0}>Tab 1</Tabs.Trigger>
|
|
47
|
+
<Tabs.Trigger index={1}>Tab 2</Tabs.Trigger>
|
|
48
|
+
</Tabs.List>
|
|
49
|
+
<Tabs.Panels>
|
|
50
|
+
<Tabs.Panel index={0}>Content 1</Tabs.Panel>
|
|
51
|
+
<Tabs.Panel index={1}>Content 2</Tabs.Panel>
|
|
52
|
+
</Tabs.Panels>
|
|
53
|
+
</Tabs>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
fireEvent.click(screen.getByText('Tab 2'));
|
|
57
|
+
|
|
58
|
+
const content1 = screen.getByText('Content 1').closest('.c-tabs__panel');
|
|
59
|
+
const content2 = screen.getByText('Content 2').closest('.c-tabs__panel');
|
|
60
|
+
|
|
61
|
+
expect(content1).toHaveStyle({ height: '0px', opacity: '0' });
|
|
62
|
+
expect(content2).toHaveStyle({ height: 'auto', opacity: '1' });
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -3,7 +3,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|
|
3
3
|
import { fn } from '@storybook/test';
|
|
4
4
|
import { Toggle } from './Toggle';
|
|
5
5
|
|
|
6
|
-
const meta = {
|
|
6
|
+
const meta: Meta<typeof Toggle> = {
|
|
7
7
|
title: 'Components/Toggle',
|
|
8
8
|
component: Toggle,
|
|
9
9
|
parameters: {
|
|
@@ -75,7 +75,7 @@ Toggle provides an on/off switch control for binary choices. It offers a more vi
|
|
|
75
75
|
description: 'Whether the toggle is initially on (uncontrolled)',
|
|
76
76
|
table: {
|
|
77
77
|
type: { summary: 'boolean' },
|
|
78
|
-
defaultValue: { summary: false },
|
|
78
|
+
defaultValue: { summary: 'false' },
|
|
79
79
|
},
|
|
80
80
|
},
|
|
81
81
|
checked: {
|
|
@@ -95,7 +95,7 @@ Toggle provides an on/off switch control for binary choices. It offers a more vi
|
|
|
95
95
|
description: 'Whether the toggle is disabled',
|
|
96
96
|
table: {
|
|
97
97
|
type: { summary: 'boolean' },
|
|
98
|
-
defaultValue: { summary: false },
|
|
98
|
+
defaultValue: { summary: 'false' },
|
|
99
99
|
},
|
|
100
100
|
},
|
|
101
101
|
glass: {
|
|
@@ -103,11 +103,11 @@ Toggle provides an on/off switch control for binary choices. It offers a more vi
|
|
|
103
103
|
description: 'Enable glass morphism effect',
|
|
104
104
|
table: {
|
|
105
105
|
type: { summary: 'boolean' },
|
|
106
|
-
defaultValue: { summary: false },
|
|
106
|
+
defaultValue: { summary: 'false' },
|
|
107
107
|
},
|
|
108
108
|
},
|
|
109
109
|
},
|
|
110
|
-
}
|
|
110
|
+
};
|
|
111
111
|
|
|
112
112
|
export default meta;
|
|
113
113
|
type Story = StoryObj<typeof meta>;
|
|
@@ -171,7 +171,15 @@ export const InitiallyOn: Story = {
|
|
|
171
171
|
|
|
172
172
|
export const DisabledStates: Story = {
|
|
173
173
|
render: () => (
|
|
174
|
-
<div
|
|
174
|
+
<div
|
|
175
|
+
style={{
|
|
176
|
+
display: 'flex',
|
|
177
|
+
flexDirection: 'column',
|
|
178
|
+
alignItems: 'center',
|
|
179
|
+
gap: '2rem',
|
|
180
|
+
padding: '30px',
|
|
181
|
+
}}
|
|
182
|
+
>
|
|
175
183
|
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
|
|
176
184
|
<Toggle disabled={true} checked={false} />
|
|
177
185
|
<span>Disabled Off</span>
|
|
@@ -193,13 +201,19 @@ export const DisabledStates: Story = {
|
|
|
193
201
|
|
|
194
202
|
export const WithGlassEffect: Story = {
|
|
195
203
|
render: args => (
|
|
196
|
-
<div
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
204
|
+
<div
|
|
205
|
+
style={{
|
|
206
|
+
background: 'url(https://images.unsplash.com/photo-1579546929518-9e396f3cc809)',
|
|
207
|
+
backgroundSize: 'cover',
|
|
208
|
+
backgroundPosition: 'center',
|
|
209
|
+
padding: '3rem',
|
|
210
|
+
borderRadius: '12px',
|
|
211
|
+
minHeight: '200px',
|
|
212
|
+
display: 'flex',
|
|
213
|
+
alignItems: 'center',
|
|
214
|
+
justifyContent: 'center',
|
|
215
|
+
}}
|
|
216
|
+
>
|
|
203
217
|
<Toggle {...args} />
|
|
204
218
|
</div>
|
|
205
219
|
),
|
|
@@ -4,88 +4,83 @@ import { Toggle } from './Toggle';
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
|
|
6
6
|
describe('Toggle Component', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
it('renders correctly', () => {
|
|
8
|
+
render(<Toggle />);
|
|
9
|
+
const toggle = screen.getByRole('switch');
|
|
10
|
+
expect(toggle).toBeInTheDocument();
|
|
11
|
+
expect(toggle).toHaveAttribute('aria-checked', 'false');
|
|
12
|
+
});
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
it('handles defaultChecked (uncontrolled)', () => {
|
|
15
|
+
render(<Toggle defaultChecked={true} />);
|
|
16
|
+
const toggle = screen.getByRole('switch');
|
|
17
|
+
expect(toggle).toHaveAttribute('aria-checked', 'true');
|
|
18
|
+
});
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
it('toggles state when clicked (uncontrolled)', () => {
|
|
21
|
+
const handleChange = vi.fn();
|
|
22
|
+
render(<Toggle onChange={handleChange} />);
|
|
23
|
+
const toggle = screen.getByRole('switch');
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
fireEvent.click(toggle);
|
|
26
|
+
expect(toggle).toHaveAttribute('aria-checked', 'true');
|
|
27
|
+
expect(handleChange).toHaveBeenCalledWith(true);
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
fireEvent.click(toggle);
|
|
30
|
+
expect(toggle).toHaveAttribute('aria-checked', 'false');
|
|
31
|
+
expect(handleChange).toHaveBeenCalledWith(false);
|
|
32
|
+
});
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
it('handles checked (controlled)', () => {
|
|
35
|
+
const { rerender } = render(<Toggle checked={true} />);
|
|
36
|
+
const toggle = screen.getByRole('switch');
|
|
37
|
+
expect(toggle).toHaveAttribute('aria-checked', 'true');
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
rerender(<Toggle checked={false} />);
|
|
40
|
+
expect(toggle).toHaveAttribute('aria-checked', 'false');
|
|
41
|
+
});
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
it('calls onChange but does not toggle internally when controlled', () => {
|
|
44
|
+
const handleChange = vi.fn();
|
|
45
|
+
render(<Toggle checked={false} onChange={handleChange} />);
|
|
46
|
+
const toggle = screen.getByRole('switch');
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
fireEvent.click(toggle);
|
|
49
|
+
expect(handleChange).toHaveBeenCalledWith(true);
|
|
50
|
+
// Should still be false because it's controlled and we haven't rerendered with checked={true}
|
|
51
|
+
expect(toggle).toHaveAttribute('aria-checked', 'false');
|
|
52
|
+
});
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
54
|
+
it('does not toggle when disabled', () => {
|
|
55
|
+
const handleChange = vi.fn();
|
|
56
|
+
render(<Toggle disabled onChange={handleChange} />);
|
|
57
|
+
const toggle = screen.getByRole('switch');
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
59
|
+
fireEvent.click(toggle);
|
|
60
|
+
expect(handleChange).not.toHaveBeenCalled();
|
|
61
|
+
expect(toggle).toHaveAttribute('aria-checked', 'false');
|
|
62
|
+
expect(toggle).toHaveAttribute('aria-disabled', 'true');
|
|
63
|
+
expect(toggle).toHaveAttribute('tabindex', '-1');
|
|
64
|
+
});
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
it('handles keyboard interaction', () => {
|
|
67
|
+
const handleChange = vi.fn();
|
|
68
|
+
render(<Toggle onChange={handleChange} />);
|
|
69
|
+
const toggle = screen.getByRole('switch');
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
fireEvent.keyDown(toggle, { key: 'Enter' });
|
|
72
|
+
expect(toggle).toHaveAttribute('aria-checked', 'true');
|
|
73
|
+
expect(handleChange).toHaveBeenCalledWith(true);
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
75
|
+
fireEvent.keyDown(toggle, { key: ' ' });
|
|
76
|
+
expect(toggle).toHaveAttribute('aria-checked', 'false');
|
|
77
|
+
expect(handleChange).toHaveBeenCalledWith(false);
|
|
78
|
+
});
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
);
|
|
87
|
-
const toggle = screen.getByRole('switch');
|
|
88
|
-
expect(toggle).toHaveAttribute('aria-label', 'Accessible Toggle');
|
|
89
|
-
expect(toggle).toHaveAttribute('aria-describedby', 'description-id');
|
|
90
|
-
});
|
|
80
|
+
it('applies accessibility attributes', () => {
|
|
81
|
+
render(<Toggle aria-label="Accessible Toggle" aria-describedby="description-id" />);
|
|
82
|
+
const toggle = screen.getByRole('switch');
|
|
83
|
+
expect(toggle).toHaveAttribute('aria-label', 'Accessible Toggle');
|
|
84
|
+
expect(toggle).toHaveAttribute('aria-describedby', 'description-id');
|
|
85
|
+
});
|
|
91
86
|
});
|
|
@@ -91,8 +91,11 @@ export const Toggle: React.FC<ToggleProps> = ({
|
|
|
91
91
|
'c-toggle',
|
|
92
92
|
isChecked && TOGGLE.CLASSES.IS_ON,
|
|
93
93
|
disabled && 'is-disabled',
|
|
94
|
+
glass && 'c-toggle--glass',
|
|
94
95
|
className,
|
|
95
|
-
]
|
|
96
|
+
]
|
|
97
|
+
.filter(Boolean)
|
|
98
|
+
.join(' ');
|
|
96
99
|
|
|
97
100
|
const toggleContent = (
|
|
98
101
|
<div
|
|
@@ -193,15 +193,17 @@ export const ClickTrigger: Story = {
|
|
|
193
193
|
|
|
194
194
|
export const AllPositions: Story = {
|
|
195
195
|
render: () => (
|
|
196
|
-
<div
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
196
|
+
<div
|
|
197
|
+
style={{
|
|
198
|
+
display: 'grid',
|
|
199
|
+
gridTemplateColumns: 'repeat(3, 1fr)',
|
|
200
|
+
gap: '20px',
|
|
201
|
+
padding: '50px',
|
|
202
|
+
alignItems: 'center',
|
|
203
|
+
justifyItems: 'center',
|
|
204
|
+
height: '500px',
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
205
207
|
<div>
|
|
206
208
|
<Tooltip content="Top Left Tooltip">
|
|
207
209
|
<button className="c-btn c-btn--primary">Top Left</button>
|
|
@@ -217,23 +219,23 @@ export const AllPositions: Story = {
|
|
|
217
219
|
<button className="c-btn c-btn--primary">Top Right</button>
|
|
218
220
|
</Tooltip>
|
|
219
221
|
</div>
|
|
220
|
-
|
|
222
|
+
|
|
221
223
|
<div>
|
|
222
224
|
<Tooltip content="Left Tooltip" position="left">
|
|
223
225
|
<button className="c-btn c-btn--primary">Left</button>
|
|
224
226
|
</Tooltip>
|
|
225
227
|
</div>
|
|
226
|
-
|
|
228
|
+
|
|
227
229
|
<div style={{ textAlign: 'center' }}>
|
|
228
230
|
<p>All tooltip positions</p>
|
|
229
231
|
</div>
|
|
230
|
-
|
|
232
|
+
|
|
231
233
|
<div>
|
|
232
234
|
<Tooltip content="Right Tooltip" position="right">
|
|
233
235
|
<button className="c-btn c-btn--primary">Right</button>
|
|
234
236
|
</Tooltip>
|
|
235
237
|
</div>
|
|
236
|
-
|
|
238
|
+
|
|
237
239
|
<div>
|
|
238
240
|
<Tooltip content="Bottom Left Tooltip" position="bottom-left">
|
|
239
241
|
<button className="c-btn c-btn--primary">Bottom Left</button>
|
|
@@ -262,13 +264,15 @@ export const AllPositions: Story = {
|
|
|
262
264
|
|
|
263
265
|
export const WithGlassEffect: Story = {
|
|
264
266
|
render: args => (
|
|
265
|
-
<div
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
267
|
+
<div
|
|
268
|
+
style={{
|
|
269
|
+
display: 'flex',
|
|
270
|
+
justifyContent: 'center',
|
|
271
|
+
padding: '100px',
|
|
272
|
+
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
273
|
+
minHeight: '300px',
|
|
274
|
+
}}
|
|
275
|
+
>
|
|
272
276
|
<Tooltip {...args}>
|
|
273
277
|
<button className="c-btn c-btn--primary">Hover me</button>
|
|
274
278
|
</Tooltip>
|
|
@@ -2,7 +2,11 @@ import React, { ReactNode, memo } from 'react';
|
|
|
2
2
|
import { TOOLTIP } from '../../lib/constants/components';
|
|
3
3
|
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
4
4
|
import { AtomixGlassProps } from '../../lib/types/components';
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
useTooltip,
|
|
7
|
+
type TooltipPosition,
|
|
8
|
+
type TooltipTrigger,
|
|
9
|
+
} from '../../lib/composables/useTooltip';
|
|
6
10
|
|
|
7
11
|
export interface TooltipProps {
|
|
8
12
|
/**
|
|
@@ -19,14 +23,14 @@ export interface TooltipProps {
|
|
|
19
23
|
* The position of the tooltip relative to the trigger
|
|
20
24
|
*/
|
|
21
25
|
position?:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
| 'top'
|
|
27
|
+
| 'bottom'
|
|
28
|
+
| 'left'
|
|
29
|
+
| 'right'
|
|
30
|
+
| 'top-left'
|
|
31
|
+
| 'top-right'
|
|
32
|
+
| 'bottom-left'
|
|
33
|
+
| 'bottom-right';
|
|
30
34
|
|
|
31
35
|
/**
|
|
32
36
|
* How the tooltip is triggered
|
|
@@ -60,109 +64,103 @@ export interface TooltipProps {
|
|
|
60
64
|
glass?: AtomixGlassProps | boolean;
|
|
61
65
|
}
|
|
62
66
|
|
|
63
|
-
export const Tooltip: React.FC<TooltipProps> = memo(
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
67
|
+
export const Tooltip: React.FC<TooltipProps> = memo(
|
|
68
|
+
({
|
|
69
|
+
content,
|
|
70
|
+
children,
|
|
71
|
+
position = TOOLTIP.DEFAULTS.POSITION,
|
|
72
|
+
trigger = TOOLTIP.DEFAULTS.TRIGGER,
|
|
73
|
+
className = '',
|
|
74
|
+
style,
|
|
75
|
+
delay = TOOLTIP.DEFAULTS.DELAY,
|
|
76
|
+
offset = TOOLTIP.DEFAULTS.OFFSET,
|
|
77
|
+
glass,
|
|
78
|
+
}) => {
|
|
79
|
+
const {
|
|
80
|
+
isVisible,
|
|
81
|
+
isPositioned,
|
|
82
|
+
tooltipId,
|
|
83
|
+
triggerRef,
|
|
84
|
+
tooltipRef,
|
|
85
|
+
tooltipStyle,
|
|
86
|
+
arrowStyle,
|
|
87
|
+
triggerProps,
|
|
88
|
+
wrapperProps,
|
|
89
|
+
} = useTooltip({
|
|
90
|
+
position: position as TooltipPosition,
|
|
91
|
+
trigger: trigger as TooltipTrigger,
|
|
92
|
+
offset,
|
|
93
|
+
delay,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const getTooltipPositionClasses = () => {
|
|
97
|
+
const positionMap: Record<string, string> = {
|
|
98
|
+
top: 'c-tooltip--top',
|
|
99
|
+
bottom: 'c-tooltip--bottom',
|
|
100
|
+
left: 'c-tooltip--left',
|
|
101
|
+
right: 'c-tooltip--right',
|
|
102
|
+
'top-left': 'c-tooltip--top-left',
|
|
103
|
+
'top-right': 'c-tooltip--top-right',
|
|
104
|
+
'bottom-left': 'c-tooltip--bottom-left',
|
|
105
|
+
'bottom-right': 'c-tooltip--bottom-right',
|
|
106
|
+
};
|
|
107
|
+
return positionMap[position] || 'c-tooltip--top';
|
|
101
108
|
};
|
|
102
|
-
return positionMap[position] || 'c-tooltip--top';
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
const renderContent = () => {
|
|
106
|
-
const contentElement = (
|
|
107
|
-
<div
|
|
108
|
-
className={`c-tooltip__content ${TOOLTIP.SELECTORS.CONTENT.substring(1)} ${isVisible && isPositioned && 'is-active'}`}
|
|
109
|
-
>
|
|
110
|
-
<span
|
|
111
|
-
className={TOOLTIP.SELECTORS.ARROW.substring(1)}
|
|
112
|
-
style={arrowStyle}
|
|
113
|
-
></span>
|
|
114
|
-
{content}
|
|
115
|
-
</div>
|
|
116
|
-
);
|
|
117
109
|
|
|
118
|
-
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
110
|
+
const renderContent = () => {
|
|
111
|
+
const contentElement = (
|
|
112
|
+
<div
|
|
113
|
+
className={`c-tooltip__content ${TOOLTIP.SELECTORS.CONTENT.substring(1)} ${isVisible && isPositioned && 'is-active'}`}
|
|
114
|
+
>
|
|
115
|
+
<span className={TOOLTIP.SELECTORS.ARROW.substring(1)} style={arrowStyle}></span>
|
|
116
|
+
{content}
|
|
117
|
+
</div>
|
|
118
|
+
);
|
|
123
119
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
<div
|
|
140
|
-
ref={triggerRef}
|
|
141
|
-
className={`${TOOLTIP.SELECTORS.TRIGGER.substring(1)}${className ? ` ${className}` : ''}`}
|
|
142
|
-
{...triggerProps}
|
|
143
|
-
>
|
|
144
|
-
{children}
|
|
145
|
-
</div>
|
|
146
|
-
{isVisible && (
|
|
120
|
+
if (glass) {
|
|
121
|
+
const defaultGlassProps = {
|
|
122
|
+
displacementScale: 100,
|
|
123
|
+
blurAmount: 3,
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
127
|
+
|
|
128
|
+
return <AtomixGlass {...glassProps}>{contentElement}</AtomixGlass>;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return contentElement;
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<div className="u-position-relative u-inline-block" style={style} {...wrapperProps}>
|
|
147
136
|
<div
|
|
148
|
-
ref={
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
className={`c-tooltip ${TOOLTIP.SELECTORS.TOOLTIP.substring(1)} ${getTooltipPositionClasses()} ${glass ? 'c-tooltip--glass' : ''}`}
|
|
152
|
-
data-tooltip-position={position}
|
|
153
|
-
data-tooltip-trigger={trigger}
|
|
154
|
-
style={{
|
|
155
|
-
...tooltipStyle,
|
|
156
|
-
// Position off-screen initially to prevent jump, then move to calculated position
|
|
157
|
-
...(isPositioned ? {} : { left: '-9999px', top: '-9999px' }),
|
|
158
|
-
}}
|
|
137
|
+
ref={triggerRef}
|
|
138
|
+
className={`${TOOLTIP.SELECTORS.TRIGGER.substring(1)}${className ? ` ${className}` : ''}`}
|
|
139
|
+
{...triggerProps}
|
|
159
140
|
>
|
|
160
|
-
{
|
|
141
|
+
{children}
|
|
161
142
|
</div>
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
143
|
+
{isVisible && (
|
|
144
|
+
<div
|
|
145
|
+
ref={tooltipRef}
|
|
146
|
+
id={tooltipId}
|
|
147
|
+
role="tooltip"
|
|
148
|
+
className={`c-tooltip ${TOOLTIP.SELECTORS.TOOLTIP.substring(1)} ${getTooltipPositionClasses()} ${glass ? 'c-tooltip--glass' : ''}`}
|
|
149
|
+
data-tooltip-position={position}
|
|
150
|
+
data-tooltip-trigger={trigger}
|
|
151
|
+
style={{
|
|
152
|
+
...tooltipStyle,
|
|
153
|
+
// Position off-screen initially to prevent jump, then move to calculated position
|
|
154
|
+
...(isPositioned ? {} : { left: '-9999px', top: '-9999px' }),
|
|
155
|
+
}}
|
|
156
|
+
>
|
|
157
|
+
{renderContent()}
|
|
158
|
+
</div>
|
|
159
|
+
)}
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
);
|
|
166
164
|
|
|
167
165
|
Tooltip.displayName = 'Tooltip';
|
|
168
166
|
|