@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shohojdhara/atomix",
3
- "version": "0.3.15",
3
+ "version": "0.4.1",
4
4
  "description": "Atomix Design System - A modern component library for web applications",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -302,4 +302,4 @@
302
302
  "publishConfig": {
303
303
  "access": "public"
304
304
  }
305
- }
305
+ }
@@ -78,6 +78,15 @@ const packageJson = JSON.parse(
78
78
  // CLI Configuration
79
79
  const DEBUG = process.env.ATOMIX_DEBUG === 'true' || process.argv.includes('--debug');
80
80
 
81
+ const SENSITIVE_KEYS = /password|secret|token|api[-_]?key|access[-_]?key|auth[-_]?token|authorization|credential/i;
82
+
83
+ function sensitiveDataReplacer(key, value) {
84
+ if (key && SENSITIVE_KEYS.test(key)) {
85
+ return '***REDACTED***';
86
+ }
87
+ return value;
88
+ }
89
+
81
90
  /**
82
91
  * Debug logger
83
92
  */
@@ -85,7 +94,7 @@ function debug(message, data = null) {
85
94
  if (DEBUG) {
86
95
  console.log(chalk.gray(`[DEBUG] ${message}`));
87
96
  if (data) {
88
- console.log(chalk.gray(JSON.stringify(data, null, 2),));
97
+ console.log(chalk.gray(JSON.stringify(data, sensitiveDataReplacer, 2)));
89
98
  }
90
99
  }
91
100
  }
@@ -115,12 +115,16 @@ describe('CLI Utils', () => {
115
115
  'command | pipe',
116
116
  '`substitution`',
117
117
  '$(command)',
118
- 'input > /dev/null'
118
+ 'input > /dev/null',
119
+ '"quoted"',
120
+ "'singlequoted'",
121
+ '" $(whoami) "',
122
+ "' ; rm -rf / '"
119
123
  ];
120
124
 
121
125
  dangerousInputs.forEach(input => {
122
126
  const sanitized = sanitizeInput(input);
123
- expect(sanitized).not.toMatch(/[;&|`$<>]/);
127
+ expect(sanitized).not.toMatch(/[;&|`$<>\\"']/);
124
128
  });
125
129
  });
126
130
 
@@ -3,7 +3,7 @@
3
3
  * Helps migrate from other design systems and CSS frameworks
4
4
  */
5
5
 
6
- import { readFile, writeFile, readdir, stat } from 'fs/promises';
6
+ import { readFile, writeFile, readdir, lstat } from 'fs/promises';
7
7
  import { join, extname, relative } from 'path';
8
8
  import chalk from 'chalk';
9
9
  import ora from 'ora';
@@ -329,7 +329,7 @@ async function getAllFiles(dir, extensions = []) {
329
329
 
330
330
  for (const entry of entries) {
331
331
  const fullPath = join(currentPath, entry);
332
- const stats = await stat(fullPath);
332
+ const stats = await lstat(fullPath);
333
333
 
334
334
  if (stats.isDirectory()) {
335
335
  // Skip node_modules and hidden directories
@@ -3,11 +3,11 @@
3
3
  *
4
4
  * Bridges the TypeScript theme devtools CLI (src/lib/theme/devtools/CLI.ts) with the main JavaScript CLI.
5
5
  *
6
- * @dependency ts-node
6
+ * @dependency tsx
7
7
  * Theme subcommands (atomix theme validate|list|inspect|compare|export|create) run the TypeScript
8
- * theme CLI via ts-node. Ensure ts-node is installed in the project when using these commands:
9
- * npm install --save-dev ts-node
10
- * If ts-node is missing, theme subcommands will fail; run `atomix doctor` to check availability.
8
+ * theme CLI via tsx. Ensure tsx is installed in the project when using these commands:
9
+ * npm install --save-dev tsx
10
+ * If tsx is missing, theme subcommands will fail; run `atomix doctor` to check availability.
11
11
  */
12
12
 
13
13
  import { spawn } from 'child_process';
@@ -29,13 +29,11 @@ export async function executeThemeCommand(command, args = [], options = {}) {
29
29
  // Path to the theme CLI
30
30
  const themeCliPath = join(__dirname, '../../src/lib/theme/devtools/CLI.ts');
31
31
 
32
- // Use ts-node to execute TypeScript CLI
33
- const tsNodePath = join(__dirname, '../../node_modules/.bin/ts-node');
32
+ // Use tsx to execute TypeScript CLI
33
+ const tsxPath = join(__dirname, '../../node_modules/.bin/tsx');
34
34
 
35
35
  return new Promise((resolve, reject) => {
36
- const child = spawn(tsNodePath, [
37
- '--esm',
38
- '--experimental-specifier-resolution=node',
36
+ const child = spawn(tsxPath, [
39
37
  themeCliPath,
40
38
  command,
41
39
  ...args
@@ -175,8 +175,9 @@ export function sanitizeInput(input) {
175
175
  }
176
176
 
177
177
  // Remove any shell metacharacters that could be dangerous
178
+ // Added single and double quotes to the blacklist to prevent shell injection
178
179
  return input
179
- .replace(/[;&|`$<>\\]/g, '')
180
+ .replace(/[;&|`$<>\\"']/g, '')
180
181
  .replace(/\0/g, '') // Remove null bytes
181
182
  .trim();
182
183
  }
@@ -1,7 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { Meta, StoryObj } from '@storybook/react';
3
3
  import { fn } from '@storybook/test';
4
- import { Accordion } from './Accordion';
4
+ import { Accordion } from './Accordion';
5
5
  import { ACCORDION } from '../../lib/constants/components';
6
6
  import type { AtomixGlassProps } from '../../lib/types/components';
7
7
 
@@ -29,9 +29,7 @@ const mockHandlers = {
29
29
  // Sample content for stories
30
30
  const sampleContent = (
31
31
  <div>
32
- <p>
33
- This accordion contains rich HTML content including headings, paragraphs, and lists.
34
- </p>
32
+ <p>This accordion contains rich HTML content including headings, paragraphs, and lists.</p>
35
33
  <ul>
36
34
  <li>
37
35
  List item with <a href="#">link</a>
@@ -65,6 +63,7 @@ The Accordion component provides an expandable/collapsible container for content
65
63
  - Glass morphism effect support
66
64
  - Keyboard navigation support
67
65
  - Disabled state handling
66
+ - **Compound Component Pattern** (new)
68
67
 
69
68
  ## Accessibility
70
69
 
@@ -83,6 +82,19 @@ The Accordion component provides an expandable/collapsible container for content
83
82
  </Accordion>
84
83
  \`\`\`
85
84
 
85
+ ### Compound Component Usage
86
+
87
+ \`\`\`tsx
88
+ <Accordion>
89
+ <Accordion.Header>
90
+ <span>Custom Header Content</span>
91
+ </Accordion.Header>
92
+ <Accordion.Body>
93
+ <p>Content goes here</p>
94
+ </Accordion.Body>
95
+ </Accordion>
96
+ \`\`\`
97
+
86
98
  ### With Custom Icon
87
99
 
88
100
  \`\`\`tsx
@@ -268,6 +280,32 @@ export const WithAllProps: Story = {
268
280
  },
269
281
  };
270
282
 
283
+ export const CompoundUsage: Story = {
284
+ render: args => (
285
+ <Accordion {...args}>
286
+ <Accordion.Header>
287
+ <div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
288
+ <strong>Custom Header Layout</strong>
289
+ <span style={{ fontSize: '0.8em', color: '#666' }}>(with subtitle)</span>
290
+ </div>
291
+ </Accordion.Header>
292
+ <Accordion.Body>
293
+ <p>
294
+ This accordion uses the Compound Component pattern (Accordion.Header and Accordion.Body).
295
+ This allows for complete control over the header layout and content structure.
296
+ </p>
297
+ </Accordion.Body>
298
+ </Accordion>
299
+ ),
300
+ parameters: {
301
+ docs: {
302
+ description: {
303
+ story: 'Demonstrates the Compound Component usage pattern for custom header layouts.',
304
+ },
305
+ },
306
+ },
307
+ };
308
+
271
309
  // ============================================================================
272
310
  // VARIANTS & STATES STORIES
273
311
  // ============================================================================
@@ -396,28 +434,22 @@ export const ControlledState: Story = {
396
434
  title: 'Controlled Accordion',
397
435
  children: <p>This accordion is controlled by external state.</p>,
398
436
  },
399
- render: (args) => {
437
+ render: args => {
400
438
  const [open, setOpen] = React.useState(false);
401
439
  return (
402
440
  <div>
403
- <button
404
- className="c-btn c-btn--primary u-mb-3"
405
- onClick={() => setOpen(prev => !prev)}
406
- >
441
+ <button className="c-btn c-btn--primary u-mb-3" onClick={() => setOpen(prev => !prev)}>
407
442
  Toggle Accordion (Controlled)
408
443
  </button>
409
- <Accordion
410
- {...args}
411
- isOpen={open}
412
- onOpenChange={setOpen}
413
- />
444
+ <Accordion {...args} isOpen={open} onOpenChange={setOpen} />
414
445
  </div>
415
446
  );
416
447
  },
417
448
  parameters: {
418
449
  docs: {
419
450
  description: {
420
- story: 'This story demonstrates a controlled Accordion using the `isOpen` and `onOpenChange` props.',
451
+ story:
452
+ 'This story demonstrates a controlled Accordion using the `isOpen` and `onOpenChange` props.',
421
453
  },
422
454
  },
423
455
  },
@@ -489,8 +521,14 @@ export const GlassEffect: Story = {
489
521
  children: <p>This accordion has a glass morphism effect applied.</p>,
490
522
  glass: true,
491
523
  },
492
- render: (args) => (
493
- <div className="u-bg-cover u-bg-center u-p-8 u-rounded-xl u-min-h-97vh u-flex u-items-center u-justify-center" style={{backgroundImage: 'url(https://images.unsplash.com/photo-1759915995309-404c743bfbf9?q=80&w=3270&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)'}}>
524
+ render: args => (
525
+ <div
526
+ className="u-bg-cover u-bg-center u-p-8 u-rounded-xl u-min-h-97vh u-flex u-items-center u-justify-center"
527
+ style={{
528
+ backgroundImage:
529
+ 'url(https://images.unsplash.com/photo-1759915995309-404c743bfbf9?q=80&w=3270&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)',
530
+ }}
531
+ >
494
532
  <div className="u-w-full u-max-w-md">
495
533
  <Accordion {...args} />
496
534
  </div>
@@ -499,7 +537,8 @@ export const GlassEffect: Story = {
499
537
  parameters: {
500
538
  docs: {
501
539
  description: {
502
- story: 'This story demonstrates an Accordion with glass morphism effect enabled against a gradient background.',
540
+ story:
541
+ 'This story demonstrates an Accordion with glass morphism effect enabled against a gradient background.',
503
542
  },
504
543
  },
505
544
  },
@@ -516,8 +555,16 @@ export const GlassCustom: Story = {
516
555
  mode: 'polar',
517
556
  } as GlassProps,
518
557
  },
519
- render: (args) => (
520
- <div className="u-bg-cover u-bg-center u-p-8 u-rounded-xl u-min-h-97vh u-flex u-items-center u-justify-center" style={{backgroundImage: 'url(https://images.unsplash.com/photo-1754147965582-edcb63324a81?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)', backgroundSize: '120%', animation: 'gradient 15s ease infinite'}}>
558
+ render: args => (
559
+ <div
560
+ className="u-bg-cover u-bg-center u-p-8 u-rounded-xl u-min-h-97vh u-flex u-items-center u-justify-center"
561
+ style={{
562
+ backgroundImage:
563
+ 'url(https://images.unsplash.com/photo-1754147965582-edcb63324a81?q=80&w=2070&auto=format&fit=crop&ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D)',
564
+ backgroundSize: '120%',
565
+ animation: 'gradient 15s ease infinite',
566
+ }}
567
+ >
521
568
  <style>
522
569
  {`
523
570
  @keyframes gradient {
@@ -538,7 +585,8 @@ export const GlassCustom: Story = {
538
585
  parameters: {
539
586
  docs: {
540
587
  description: {
541
- story: 'This story demonstrates an Accordion with custom glass morphism settings against a scenic background image.',
588
+ story:
589
+ 'This story demonstrates an Accordion with custom glass morphism settings against a scenic background image.',
542
590
  },
543
591
  },
544
592
  },
@@ -567,7 +615,8 @@ export const KeyboardNavigation: Story = {
567
615
  title: 'Keyboard Accessible',
568
616
  children: (
569
617
  <p>
570
- This accordion is fully operable via keyboard navigation. Press Tab to focus and Enter/Space to toggle.
618
+ This accordion is fully operable via keyboard navigation. Press Tab to focus and Enter/Space
619
+ to toggle.
571
620
  </p>
572
621
  ),
573
622
  },
@@ -578,4 +627,4 @@ export const KeyboardNavigation: Story = {
578
627
  },
579
628
  },
580
629
  },
581
- };
630
+ };
@@ -4,54 +4,74 @@ import { Accordion } from './Accordion';
4
4
  import React from 'react';
5
5
 
6
6
  describe('Accordion Component', () => {
7
- it('renders correctly with title', () => {
8
- render(<Accordion title="Test Accordion">Content</Accordion>);
9
- expect(screen.getByText('Test Accordion')).toBeInTheDocument();
10
- expect(screen.getByText('Content')).toBeInTheDocument();
11
- });
12
-
13
- it('toggles when clicked', () => {
14
- const onOpenChange = vi.fn();
15
- render(<Accordion title="Test" onOpenChange={onOpenChange}>Content</Accordion>);
16
- const button = screen.getByRole('button');
17
-
18
- fireEvent.click(button);
19
- expect(onOpenChange).toHaveBeenCalledWith(true);
20
- expect(button).toHaveAttribute('aria-expanded', 'true');
21
-
22
- fireEvent.click(button);
23
- expect(onOpenChange).toHaveBeenCalledWith(false);
24
- expect(button).toHaveAttribute('aria-expanded', 'false');
25
- });
26
-
27
- it('calls legacy onOpen/onClose handlers', () => {
28
- const onOpen = vi.fn();
29
- const onClose = vi.fn();
30
- render(<Accordion title="Test" onOpen={onOpen} onClose={onClose}>Content</Accordion>);
31
- const button = screen.getByRole('button');
32
-
33
- fireEvent.click(button);
34
- expect(onOpen).toHaveBeenCalled();
35
-
36
- fireEvent.click(button);
37
- expect(onClose).toHaveBeenCalled();
38
- });
39
-
40
- it('handles controlled state', () => {
41
- const onOpenChange = vi.fn();
42
- const { rerender } = render(<Accordion title="Test" isOpen={false} onOpenChange={onOpenChange}>Content</Accordion>);
43
- const button = screen.getByRole('button');
44
-
45
- fireEvent.click(button);
46
- expect(onOpenChange).toHaveBeenCalledWith(true);
47
- expect(button).toHaveAttribute('aria-expanded', 'false'); // Should not change internally
48
-
49
- rerender(<Accordion title="Test" isOpen={true} onOpenChange={onOpenChange}>Content</Accordion>);
50
- expect(button).toHaveAttribute('aria-expanded', 'true');
51
- });
52
-
53
- it('supports glass effect', () => {
54
- const { container } = render(<Accordion title="Test" glass>Content</Accordion>);
55
- expect(container.querySelector('.c-accordion--glass')).toBeInTheDocument();
56
- });
7
+ it('renders correctly with title', () => {
8
+ render(<Accordion title="Test Accordion">Content</Accordion>);
9
+ expect(screen.getByText('Test Accordion')).toBeInTheDocument();
10
+ expect(screen.getByText('Content')).toBeInTheDocument();
11
+ });
12
+
13
+ it('toggles when clicked', () => {
14
+ const onOpenChange = vi.fn();
15
+ render(
16
+ <Accordion title="Test" onOpenChange={onOpenChange}>
17
+ Content
18
+ </Accordion>
19
+ );
20
+ const button = screen.getByRole('button');
21
+
22
+ fireEvent.click(button);
23
+ expect(onOpenChange).toHaveBeenCalledWith(true);
24
+ expect(button).toHaveAttribute('aria-expanded', 'true');
25
+
26
+ fireEvent.click(button);
27
+ expect(onOpenChange).toHaveBeenCalledWith(false);
28
+ expect(button).toHaveAttribute('aria-expanded', 'false');
29
+ });
30
+
31
+ it('calls legacy onOpen/onClose handlers', () => {
32
+ const onOpen = vi.fn();
33
+ const onClose = vi.fn();
34
+ render(
35
+ <Accordion title="Test" onOpen={onOpen} onClose={onClose}>
36
+ Content
37
+ </Accordion>
38
+ );
39
+ const button = screen.getByRole('button');
40
+
41
+ fireEvent.click(button);
42
+ expect(onOpen).toHaveBeenCalled();
43
+
44
+ fireEvent.click(button);
45
+ expect(onClose).toHaveBeenCalled();
46
+ });
47
+
48
+ it('handles controlled state', () => {
49
+ const onOpenChange = vi.fn();
50
+ const { rerender } = render(
51
+ <Accordion title="Test" isOpen={false} onOpenChange={onOpenChange}>
52
+ Content
53
+ </Accordion>
54
+ );
55
+ const button = screen.getByRole('button');
56
+
57
+ fireEvent.click(button);
58
+ expect(onOpenChange).toHaveBeenCalledWith(true);
59
+ expect(button).toHaveAttribute('aria-expanded', 'false'); // Should not change internally
60
+
61
+ rerender(
62
+ <Accordion title="Test" isOpen={true} onOpenChange={onOpenChange}>
63
+ Content
64
+ </Accordion>
65
+ );
66
+ expect(button).toHaveAttribute('aria-expanded', 'true');
67
+ });
68
+
69
+ it('supports glass effect', () => {
70
+ const { container } = render(
71
+ <Accordion title="Test" glass>
72
+ Content
73
+ </Accordion>
74
+ );
75
+ expect(container.querySelector('.c-accordion--glass')).toBeInTheDocument();
76
+ });
57
77
  });