@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.
Files changed (276) hide show
  1. package/build-tools/index.d.ts +31 -30
  2. package/build-tools/package.json +4 -21
  3. package/dist/atomix.css +20234 -2027
  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 +4 -5
  10. package/dist/charts.js.map +1 -1
  11. package/dist/core.d.ts +87 -10
  12. package/dist/core.js +673 -480
  13. package/dist/core.js.map +1 -1
  14. package/dist/forms.d.ts +15 -3
  15. package/dist/forms.js +530 -97
  16. package/dist/forms.js.map +1 -1
  17. package/dist/heavy.js +5 -6
  18. package/dist/heavy.js.map +1 -1
  19. package/dist/index.d.ts +644 -277
  20. package/dist/index.esm.js +1948 -1347
  21. package/dist/index.esm.js.map +1 -1
  22. package/dist/index.js +3333 -2728
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.min.js +1 -1
  25. package/dist/index.min.js.map +1 -1
  26. package/dist/layout.js.map +1 -1
  27. package/dist/theme.d.ts +9 -9
  28. package/dist/theme.js.map +1 -1
  29. package/package.json +2 -2
  30. package/scripts/atomix-cli.js +10 -1
  31. package/scripts/cli/__tests__/utils.test.js +6 -2
  32. package/scripts/cli/migration-tools.js +2 -2
  33. package/scripts/cli/theme-bridge.js +7 -9
  34. package/scripts/cli/utils.js +2 -1
  35. package/src/components/Accordion/Accordion.stories.tsx +72 -23
  36. package/src/components/Accordion/Accordion.test.tsx +70 -50
  37. package/src/components/Accordion/Accordion.tsx +219 -96
  38. package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
  39. package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
  40. package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
  41. package/src/components/AtomixGlass/glass-utils.ts +4 -3
  42. package/src/components/AtomixGlass/shader-utils.ts +128 -52
  43. package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
  44. package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
  45. package/src/components/Avatar/Avatar.stories.tsx +45 -62
  46. package/src/components/Avatar/Avatar.tsx +58 -56
  47. package/src/components/Badge/Badge.stories.tsx +20 -9
  48. package/src/components/Badge/Badge.test.tsx +41 -41
  49. package/src/components/Badge/Badge.tsx +64 -62
  50. package/src/components/Block/Block.stories.tsx +14 -4
  51. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
  52. package/src/components/Breadcrumb/Breadcrumb.tsx +173 -65
  53. package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
  54. package/src/components/Button/Button.stories.tsx +13 -22
  55. package/src/components/Button/Button.test.tsx +97 -81
  56. package/src/components/Button/Button.tsx +46 -14
  57. package/src/components/Button/ButtonGroup.stories.tsx +37 -32
  58. package/src/components/Button/ButtonGroup.tsx +4 -15
  59. package/src/components/Callout/Callout.stories.tsx +166 -918
  60. package/src/components/Callout/Callout.tsx +196 -84
  61. package/src/components/Callout/CalloutCompound.test.tsx +72 -0
  62. package/src/components/Card/Card.stories.tsx +67 -36
  63. package/src/components/Card/Card.tsx +30 -14
  64. package/src/components/Chart/AreaChart.tsx +1 -1
  65. package/src/components/Chart/CandlestickChart.tsx +23 -16
  66. package/src/components/Chart/Chart.stories.tsx +4 -9
  67. package/src/components/Chart/Chart.tsx +40 -44
  68. package/src/components/Chart/ChartRenderer.tsx +39 -12
  69. package/src/components/Chart/ChartToolbar.tsx +21 -5
  70. package/src/components/Chart/DonutChart.tsx +1 -1
  71. package/src/components/Chart/FunnelChart.tsx +4 -1
  72. package/src/components/Chart/GaugeChart.tsx +3 -1
  73. package/src/components/Chart/HeatmapChart.tsx +50 -37
  74. package/src/components/Chart/LineChart.tsx +3 -2
  75. package/src/components/Chart/MultiAxisChart.tsx +24 -16
  76. package/src/components/Chart/RadarChart.tsx +19 -17
  77. package/src/components/Chart/ScatterChart.tsx +29 -21
  78. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
  79. package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
  80. package/src/components/Countdown/Countdown.stories.tsx +7 -7
  81. package/src/components/DataTable/DataTable.stories.tsx +43 -38
  82. package/src/components/DataTable/DataTable.test.tsx +26 -148
  83. package/src/components/DataTable/DataTable.tsx +485 -456
  84. package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
  85. package/src/components/DatePicker/DatePicker.tsx +31 -26
  86. package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
  87. package/src/components/Dropdown/Dropdown.tsx +425 -298
  88. package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
  89. package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
  90. package/src/components/EdgePanel/EdgePanel.tsx +163 -113
  91. package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
  92. package/src/components/Footer/Footer.stories.tsx +21 -16
  93. package/src/components/Footer/Footer.tsx +130 -128
  94. package/src/components/Footer/FooterLink.tsx +2 -2
  95. package/src/components/Form/Checkbox.test.tsx +49 -49
  96. package/src/components/Form/Checkbox.tsx +108 -100
  97. package/src/components/Form/Form.stories.tsx +2 -10
  98. package/src/components/Form/Input.stories.tsx +22 -39
  99. package/src/components/Form/Input.test.tsx +38 -44
  100. package/src/components/Form/Radio.stories.tsx +6 -12
  101. package/src/components/Form/Radio.tsx +68 -66
  102. package/src/components/Form/Select.stories.tsx +23 -0
  103. package/src/components/Form/Select.test.tsx +99 -0
  104. package/src/components/Form/Select.tsx +239 -186
  105. package/src/components/Form/SelectOption.tsx +88 -0
  106. package/src/components/Form/Textarea.test.tsx +27 -32
  107. package/src/components/Hero/Hero.stories.tsx +93 -23
  108. package/src/components/Hero/Hero.test.tsx +142 -0
  109. package/src/components/Hero/Hero.tsx +343 -58
  110. package/src/components/Icon/index.ts +7 -1
  111. package/src/components/List/List.test.tsx +62 -0
  112. package/src/components/List/List.tsx +32 -25
  113. package/src/components/List/ListItem.tsx +20 -0
  114. package/src/components/Modal/Modal.stories.tsx +67 -2
  115. package/src/components/Modal/Modal.tsx +208 -125
  116. package/src/components/Modal/ModalCompound.test.tsx +94 -0
  117. package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
  118. package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
  119. package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
  120. package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
  121. package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
  122. package/src/components/Pagination/Pagination.stories.tsx +7 -4
  123. package/src/components/Pagination/Pagination.tsx +199 -202
  124. package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
  125. package/src/components/Popover/Popover.stories.tsx +99 -192
  126. package/src/components/Popover/Popover.tsx +41 -37
  127. package/src/components/Progress/Progress.stories.tsx +35 -44
  128. package/src/components/River/River.stories.tsx +2 -1
  129. package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
  130. package/src/components/Slider/Slider.stories.tsx +12 -4
  131. package/src/components/Spinner/Spinner.stories.tsx +3 -1
  132. package/src/components/Spinner/Spinner.test.tsx +23 -23
  133. package/src/components/Spinner/Spinner.tsx +43 -46
  134. package/src/components/Steps/Steps.stories.tsx +8 -6
  135. package/src/components/Steps/Steps.tsx +124 -21
  136. package/src/components/Steps/StepsCompound.test.tsx +81 -0
  137. package/src/components/Tabs/Tabs.stories.tsx +12 -9
  138. package/src/components/Tabs/Tabs.tsx +230 -75
  139. package/src/components/Tabs/TabsCompound.test.tsx +64 -0
  140. package/src/components/Toggle/Toggle.stories.tsx +27 -13
  141. package/src/components/Toggle/Toggle.test.tsx +65 -70
  142. package/src/components/Toggle/Toggle.tsx +4 -1
  143. package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
  144. package/src/components/Tooltip/Tooltip.tsx +104 -106
  145. package/src/components/Upload/Upload.stories.tsx +129 -127
  146. package/src/components/Upload/Upload.tsx +287 -283
  147. package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
  148. package/src/components/index.ts +13 -2
  149. package/src/layouts/Grid/Grid.stories.tsx +9 -3
  150. package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
  151. package/src/lib/__tests__/theme-tools.test.ts +32 -6
  152. package/src/lib/composables/index.ts +0 -4
  153. package/src/lib/composables/shared-mouse-tracker.ts +13 -14
  154. package/src/lib/composables/useAtomixGlass.ts +102 -60
  155. package/src/lib/composables/useChartExport.ts +1 -1
  156. package/src/lib/composables/useDataTable.ts +29 -17
  157. package/src/lib/composables/useHero.ts +58 -14
  158. package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
  159. package/src/lib/composables/useInput.ts +10 -8
  160. package/src/lib/composables/useSideMenu.ts +6 -5
  161. package/src/lib/composables/useTooltip.ts +1 -2
  162. package/src/lib/composables/useVideoPlayer.ts +44 -35
  163. package/src/lib/config/index.ts +154 -154
  164. package/src/lib/constants/cssVariables.ts +29 -29
  165. package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
  166. package/src/lib/hooks/index.ts +1 -1
  167. package/src/lib/hooks/useComponentCustomization.ts +11 -17
  168. package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
  169. package/src/lib/patterns/__tests__/slots.test.ts +1 -1
  170. package/src/lib/patterns/index.ts +1 -1
  171. package/src/lib/patterns/slots.tsx +8 -13
  172. package/src/lib/storybook/InteractiveDemo.tsx +13 -18
  173. package/src/lib/storybook/PreviewContainer.tsx +1 -1
  174. package/src/lib/storybook/VariantsGrid.tsx +3 -7
  175. package/src/lib/storybook/index.ts +1 -1
  176. package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
  177. package/src/lib/theme/adapters/index.ts +3 -9
  178. package/src/lib/theme/adapters/themeAdapter.ts +41 -26
  179. package/src/lib/theme/config/index.ts +1 -1
  180. package/src/lib/theme/config/types.ts +2 -2
  181. package/src/lib/theme/config/validator.ts +10 -5
  182. package/src/lib/theme/constants/constants.ts +2 -2
  183. package/src/lib/theme/constants/index.ts +1 -2
  184. package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
  185. package/src/lib/theme/core/composeTheme.ts +32 -26
  186. package/src/lib/theme/core/createTheme.ts +1 -1
  187. package/src/lib/theme/core/createThemeObject.ts +308 -301
  188. package/src/lib/theme/core/index.ts +3 -3
  189. package/src/lib/theme/devtools/CLI.ts +105 -111
  190. package/src/lib/theme/devtools/Comparator.tsx +50 -32
  191. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
  192. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
  193. package/src/lib/theme/devtools/Inspector.tsx +75 -60
  194. package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
  195. package/src/lib/theme/devtools/Preview.tsx +150 -106
  196. package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
  197. package/src/lib/theme/devtools/index.ts +3 -9
  198. package/src/lib/theme/devtools/useHistory.ts +23 -21
  199. package/src/lib/theme/errors/errors.ts +12 -11
  200. package/src/lib/theme/errors/index.ts +2 -7
  201. package/src/lib/theme/generators/generateCSS.ts +9 -13
  202. package/src/lib/theme/generators/generateCSSNested.ts +1 -6
  203. package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
  204. package/src/lib/theme/generators/index.ts +1 -4
  205. package/src/lib/theme/i18n/index.ts +1 -1
  206. package/src/lib/theme/i18n/rtl.ts +13 -13
  207. package/src/lib/theme/index.ts +7 -16
  208. package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
  209. package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
  210. package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
  211. package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
  212. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
  213. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
  214. package/src/lib/theme/runtime/index.ts +2 -5
  215. package/src/lib/theme/runtime/useTheme.ts +18 -18
  216. package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
  217. package/src/lib/theme/test/testTheme.ts +15 -16
  218. package/src/lib/theme/tokens/index.ts +2 -7
  219. package/src/lib/theme/tokens/tokens.ts +25 -24
  220. package/src/lib/theme/types.ts +428 -411
  221. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
  222. package/src/lib/theme/utils/componentTheming.ts +18 -18
  223. package/src/lib/theme/utils/domUtils.ts +277 -289
  224. package/src/lib/theme/utils/index.ts +1 -2
  225. package/src/lib/theme/utils/injectCSS.ts +10 -14
  226. package/src/lib/theme/utils/naming.ts +20 -16
  227. package/src/lib/theme/utils/themeHelpers.ts +10 -12
  228. package/src/lib/theme/utils/themeUtils.ts +85 -86
  229. package/src/lib/theme/utils/themeValidation.ts +82 -33
  230. package/src/lib/theme-tools.ts +8 -6
  231. package/src/lib/types/components.ts +180 -73
  232. package/src/lib/types/partProps.ts +1 -1
  233. package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
  234. package/src/lib/utils/__tests__/csv.test.ts +1 -1
  235. package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
  236. package/src/lib/utils/componentUtils.ts +8 -12
  237. package/src/lib/utils/csv.ts +3 -1
  238. package/src/lib/utils/dataTableExport.ts +1 -5
  239. package/src/lib/utils/fontPreloader.ts +10 -19
  240. package/src/lib/utils/icons.ts +4 -1
  241. package/src/lib/utils/index.ts +2 -6
  242. package/src/lib/utils/memoryMonitor.ts +10 -8
  243. package/src/lib/utils/themeNaming.ts +3 -3
  244. package/src/styles/01-settings/_index.scss +0 -1
  245. package/src/styles/01-settings/_settings.colors.scss +8 -8
  246. package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
  247. package/src/styles/01-settings/_settings.navbar.scss +1 -1
  248. package/src/styles/01-settings/_settings.spacing.scss +3 -4
  249. package/src/styles/01-settings/_settings.tooltip.scss +1 -1
  250. package/src/styles/01-settings/_settings.typography.scss +1 -1
  251. package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
  252. package/src/styles/02-tools/_tools.button.scss +51 -21
  253. package/src/styles/02-tools/_tools.utility-api.scss +36 -24
  254. package/src/styles/03-generic/_generic.root.scss +4 -3
  255. package/src/styles/06-components/_components.atomix-glass.scss +13 -9
  256. package/src/styles/06-components/_components.button.scss +16 -4
  257. package/src/styles/06-components/_components.callout.scss +27 -21
  258. package/src/styles/06-components/_components.card.scss +5 -14
  259. package/src/styles/06-components/_components.chart.scss +22 -19
  260. package/src/styles/06-components/_components.checkbox.scss +3 -1
  261. package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
  262. package/src/styles/06-components/_components.edge-panel.scss +9 -2
  263. package/src/styles/06-components/_components.footer.scss +1 -1
  264. package/src/styles/06-components/_components.side-menu.scss +5 -5
  265. package/src/styles/06-components/_components.toggle.scss +18 -0
  266. package/src/styles/06-components/_index.scss +1 -1
  267. package/src/styles/06-components/old.chart.styles.scss +0 -2
  268. package/src/styles/99-utilities/_utilities.border.scss +69 -27
  269. package/src/styles/99-utilities/_utilities.display.scss +1 -1
  270. package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
  271. package/src/styles/99-utilities/_utilities.position.scss +16 -9
  272. package/src/styles/99-utilities/_utilities.scss +1 -1
  273. package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
  274. package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
  275. package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
  276. 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
- } satisfies Meta<typeof Toggle>;
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 style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '2rem', padding: '30px' }}>
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 style={{
197
- display: 'flex',
198
- justifyContent: 'center',
199
- padding: '30px',
200
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
201
- minHeight: '200px'
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
- it('renders correctly', () => {
8
- render(<Toggle />);
9
- const toggle = screen.getByRole('switch');
10
- expect(toggle).toBeInTheDocument();
11
- expect(toggle).toHaveAttribute('aria-checked', 'false');
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
- it('handles defaultChecked (uncontrolled)', () => {
15
- render(<Toggle defaultChecked={true} />);
16
- const toggle = screen.getByRole('switch');
17
- expect(toggle).toHaveAttribute('aria-checked', 'true');
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
- it('toggles state when clicked (uncontrolled)', () => {
21
- const handleChange = vi.fn();
22
- render(<Toggle onChange={handleChange} />);
23
- const toggle = screen.getByRole('switch');
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
- fireEvent.click(toggle);
26
- expect(toggle).toHaveAttribute('aria-checked', 'true');
27
- expect(handleChange).toHaveBeenCalledWith(true);
25
+ fireEvent.click(toggle);
26
+ expect(toggle).toHaveAttribute('aria-checked', 'true');
27
+ expect(handleChange).toHaveBeenCalledWith(true);
28
28
 
29
- fireEvent.click(toggle);
30
- expect(toggle).toHaveAttribute('aria-checked', 'false');
31
- expect(handleChange).toHaveBeenCalledWith(false);
32
- });
29
+ fireEvent.click(toggle);
30
+ expect(toggle).toHaveAttribute('aria-checked', 'false');
31
+ expect(handleChange).toHaveBeenCalledWith(false);
32
+ });
33
33
 
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');
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
- rerender(<Toggle checked={false} />);
40
- expect(toggle).toHaveAttribute('aria-checked', 'false');
41
- });
39
+ rerender(<Toggle checked={false} />);
40
+ expect(toggle).toHaveAttribute('aria-checked', 'false');
41
+ });
42
42
 
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');
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
- 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
- });
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
- it('does not toggle when disabled', () => {
55
- const handleChange = vi.fn();
56
- render(<Toggle disabled onChange={handleChange} />);
57
- const toggle = screen.getByRole('switch');
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
- 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
- });
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
- it('handles keyboard interaction', () => {
67
- const handleChange = vi.fn();
68
- render(<Toggle onChange={handleChange} />);
69
- const toggle = screen.getByRole('switch');
66
+ it('handles keyboard interaction', () => {
67
+ const handleChange = vi.fn();
68
+ render(<Toggle onChange={handleChange} />);
69
+ const toggle = screen.getByRole('switch');
70
70
 
71
- fireEvent.keyDown(toggle, { key: 'Enter' });
72
- expect(toggle).toHaveAttribute('aria-checked', 'true');
73
- expect(handleChange).toHaveBeenCalledWith(true);
71
+ fireEvent.keyDown(toggle, { key: 'Enter' });
72
+ expect(toggle).toHaveAttribute('aria-checked', 'true');
73
+ expect(handleChange).toHaveBeenCalledWith(true);
74
74
 
75
- fireEvent.keyDown(toggle, { key: ' ' });
76
- expect(toggle).toHaveAttribute('aria-checked', 'false');
77
- expect(handleChange).toHaveBeenCalledWith(false);
78
- });
75
+ fireEvent.keyDown(toggle, { key: ' ' });
76
+ expect(toggle).toHaveAttribute('aria-checked', 'false');
77
+ expect(handleChange).toHaveBeenCalledWith(false);
78
+ });
79
79
 
80
- it('applies accessibility attributes', () => {
81
- render(
82
- <Toggle
83
- aria-label="Accessible Toggle"
84
- aria-describedby="description-id"
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
- ].filter(Boolean).join(' ');
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 style={{
197
- display: 'grid',
198
- gridTemplateColumns: 'repeat(3, 1fr)',
199
- gap: '20px',
200
- padding: '50px',
201
- alignItems: 'center',
202
- justifyItems: 'center',
203
- height: '500px'
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 style={{
266
- display: 'flex',
267
- justifyContent: 'center',
268
- padding: '100px',
269
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
270
- minHeight: '300px'
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 { useTooltip, type TooltipPosition, type TooltipTrigger } from '../../lib/composables/useTooltip';
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
- | 'top'
23
- | 'bottom'
24
- | 'left'
25
- | 'right'
26
- | 'top-left'
27
- | 'top-right'
28
- | 'bottom-left'
29
- | 'bottom-right';
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
- content,
65
- children,
66
- position = TOOLTIP.DEFAULTS.POSITION,
67
- trigger = TOOLTIP.DEFAULTS.TRIGGER,
68
- className = '',
69
- style,
70
- delay = TOOLTIP.DEFAULTS.DELAY,
71
- offset = TOOLTIP.DEFAULTS.OFFSET,
72
- glass,
73
- }) => {
74
- const {
75
- isVisible,
76
- isPositioned,
77
- tooltipId,
78
- triggerRef,
79
- tooltipRef,
80
- tooltipStyle,
81
- arrowStyle,
82
- triggerProps,
83
- wrapperProps,
84
- } = useTooltip({
85
- position: position as TooltipPosition,
86
- trigger: trigger as TooltipTrigger,
87
- offset,
88
- delay,
89
- });
90
-
91
- const getTooltipPositionClasses = () => {
92
- const positionMap: Record<string, string> = {
93
- top: 'c-tooltip--top',
94
- bottom: 'c-tooltip--bottom',
95
- left: 'c-tooltip--left',
96
- right: 'c-tooltip--right',
97
- 'top-left': 'c-tooltip--top-left',
98
- 'top-right': 'c-tooltip--top-right',
99
- 'bottom-left': 'c-tooltip--bottom-left',
100
- 'bottom-right': 'c-tooltip--bottom-right',
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
- if (glass) {
119
- const defaultGlassProps = {
120
- displacementScale: 100,
121
- blurAmount: 3,
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
- const glassProps =
125
- glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
126
-
127
- return <AtomixGlass {...glassProps}>{contentElement}</AtomixGlass>;
128
- }
129
-
130
- return contentElement;
131
- };
132
-
133
- return (
134
- <div
135
- className="u-position-relative u-inline-block"
136
- style={style}
137
- {...wrapperProps}
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={tooltipRef}
149
- id={tooltipId}
150
- role="tooltip"
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
- {renderContent()}
141
+ {children}
161
142
  </div>
162
- )}
163
- </div>
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