@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
@@ -1,85 +1,206 @@
1
- import React from 'react';
1
+ import React, { memo, forwardRef } from 'react';
2
2
  import { CalloutProps } from '../../lib/types/components';
3
3
  import { useCallout } from '../../lib/composables/useCallout';
4
4
  import { Icon } from '../Icon/Icon';
5
5
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
6
6
 
7
+ // Subcomponents
8
+ export const CalloutIcon = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
9
+ ({ children, className = '', ...props }, ref) => (
10
+ <div ref={ref} className={`c-callout__icon ${className}`.trim()} {...props}>
11
+ {children}
12
+ </div>
13
+ )
14
+ );
15
+ CalloutIcon.displayName = 'CalloutIcon';
16
+
17
+ export const CalloutMessage = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
18
+ ({ children, className = '', ...props }, ref) => (
19
+ <div ref={ref} className={`c-callout__message ${className}`.trim()} {...props}>
20
+ {children}
21
+ </div>
22
+ )
23
+ );
24
+ CalloutMessage.displayName = 'CalloutMessage';
25
+
26
+ export const CalloutTitle = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
27
+ ({ children, className = '', ...props }, ref) => (
28
+ <div ref={ref} className={`c-callout__title ${className}`.trim()} {...props}>
29
+ {children}
30
+ </div>
31
+ )
32
+ );
33
+ CalloutTitle.displayName = 'CalloutTitle';
34
+
35
+ export const CalloutText = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
36
+ ({ children, className = '', ...props }, ref) => (
37
+ <div ref={ref} className={`c-callout__text ${className}`.trim()} {...props}>
38
+ {children}
39
+ </div>
40
+ )
41
+ );
42
+ CalloutText.displayName = 'CalloutText';
43
+
44
+ export const CalloutActions = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
45
+ ({ children, className = '', ...props }, ref) => (
46
+ <div ref={ref} className={`c-callout__actions ${className}`.trim()} {...props}>
47
+ {children}
48
+ </div>
49
+ )
50
+ );
51
+ CalloutActions.displayName = 'CalloutActions';
52
+
53
+ export interface CalloutCloseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
54
+ export const CalloutCloseButton = forwardRef<HTMLButtonElement, CalloutCloseButtonProps>(
55
+ ({ onClick, className = '', ...props }, ref) => (
56
+ <button
57
+ ref={ref}
58
+ className={`c-callout__close-btn ${className}`.trim()}
59
+ onClick={onClick}
60
+ aria-label="Close"
61
+ {...props}
62
+ >
63
+ <Icon name="X" size="md" />
64
+ </button>
65
+ )
66
+ );
67
+ CalloutCloseButton.displayName = 'CalloutCloseButton';
68
+
69
+ // Wrapper for content (icon + message)
70
+ export const CalloutContent = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
71
+ ({ children, className = '', ...props }, ref) => (
72
+ <div ref={ref} className={`c-callout__content ${className}`.trim()} {...props}>
73
+ {children}
74
+ </div>
75
+ )
76
+ );
77
+ CalloutContent.displayName = 'CalloutContent';
78
+
7
79
  /**
8
80
  * Callout component for displaying important messages, notifications, or alerts
9
81
  */
10
- export const Callout: React.FC<CalloutProps> = ({
11
- title,
12
- children,
13
- icon,
14
- variant = 'primary',
15
- onClose,
16
- actions,
17
- compact = false,
18
- isToast = false,
19
- glass,
20
- className,
21
- style,
22
- ...props
23
- }) => {
24
- const { generateCalloutClass, handleClose } = useCallout({
25
- variant,
26
- compact,
27
- isToast,
82
+ type CalloutComponent = React.FC<CalloutProps> & {
83
+ Icon: typeof CalloutIcon;
84
+ Message: typeof CalloutMessage;
85
+ Title: typeof CalloutTitle;
86
+ Text: typeof CalloutText;
87
+ Actions: typeof CalloutActions;
88
+ CloseButton: typeof CalloutCloseButton;
89
+ Content: typeof CalloutContent;
90
+ };
91
+
92
+ export const Callout: CalloutComponent = memo(
93
+ ({
94
+ title,
95
+ children,
96
+ icon,
97
+ variant = 'primary',
98
+ onClose,
99
+ actions,
100
+ compact = false,
101
+ isToast = false,
28
102
  glass,
29
103
  className,
30
104
  style,
31
- });
105
+ ...props
106
+ }: CalloutProps) => {
107
+ const { generateCalloutClass, handleClose } = useCallout({
108
+ variant,
109
+ compact,
110
+ isToast,
111
+ glass,
112
+ className,
113
+ style,
114
+ });
32
115
 
33
- // Determine appropriate ARIA attributes based on variant
34
- const getAriaAttributes = () => {
35
- const baseAttributes: Record<string, string> = {
36
- role: 'region',
37
- };
116
+ // Determine appropriate ARIA attributes based on variant
117
+ const getAriaAttributes = () => {
118
+ const baseAttributes: Record<string, string> = {
119
+ role: 'region',
120
+ };
38
121
 
39
- // For toast notifications or alerts, use appropriate role and live region
40
- if (isToast) {
41
- baseAttributes.role = 'alert';
42
- baseAttributes['aria-live'] = 'polite';
43
- } else if (['warning', 'error'].includes(variant)) {
44
- baseAttributes.role = 'alert';
45
- baseAttributes['aria-live'] = 'assertive';
46
- } else if (['info', 'success'].includes(variant)) {
47
- baseAttributes.role = 'status';
48
- baseAttributes['aria-live'] = 'polite';
49
- }
122
+ // For toast notifications or alerts, use appropriate role and live region
123
+ if (isToast) {
124
+ baseAttributes.role = 'alert';
125
+ baseAttributes['aria-live'] = 'polite';
126
+ } else if (['warning', 'error'].includes(variant)) {
127
+ baseAttributes.role = 'alert';
128
+ baseAttributes['aria-live'] = 'assertive';
129
+ } else if (['info', 'success'].includes(variant)) {
130
+ baseAttributes.role = 'status';
131
+ baseAttributes['aria-live'] = 'polite';
132
+ }
133
+
134
+ return baseAttributes;
135
+ };
50
136
 
51
- return baseAttributes;
52
- };
137
+ // Check for compound usage
138
+ const hasCompoundComponents = React.Children.toArray(children).some((child) =>
139
+ React.isValidElement(child) &&
140
+ [
141
+ 'CalloutIcon',
142
+ 'CalloutMessage',
143
+ 'CalloutTitle',
144
+ 'CalloutText',
145
+ 'CalloutActions',
146
+ 'CalloutContent',
147
+ ].includes((child.type as any).displayName)
148
+ );
53
149
 
54
- const calloutContent = (
55
- <>
56
- <div className="c-callout__content">
57
- {icon && <div className="c-callout__icon">{icon}</div>}
58
- <div className="c-callout__message">
59
- {title && <div className="c-callout__title">{title}</div>}
60
- {children && <div className="c-callout__text">{children}</div>}
150
+ const calloutContent = hasCompoundComponents ? (
151
+ children
152
+ ) : (
153
+ <>
154
+ <div className="c-callout__content">
155
+ {icon && <div className="c-callout__icon">{icon}</div>}
156
+ <div className="c-callout__message">
157
+ {title && <div className="c-callout__title">{title}</div>}
158
+ {children && <div className="c-callout__text">{children}</div>}
159
+ </div>
61
160
  </div>
62
- </div>
63
161
 
64
- {actions && <div className="c-callout__actions">{actions}</div>}
65
-
66
- {onClose && (
67
- <button className="c-callout__close-btn" onClick={handleClose(onClose)} aria-label="Close">
68
- <Icon name="X" size="md" />
69
- </button>
70
- )}
71
- </>
72
- );
73
-
74
- if (glass) {
75
- // Default glass settings for callouts
76
- const defaultGlassProps = {
77
- displacementScale: 30,
78
- cornerRadius: 8,
79
- elasticity: 0,
80
- };
162
+ {actions && <div className="c-callout__actions">{actions}</div>}
163
+
164
+ {onClose && (
165
+ <button
166
+ className="c-callout__close-btn"
167
+ onClick={handleClose(onClose)}
168
+ aria-label="Close"
169
+ >
170
+ <Icon name="X" size="md" />
171
+ </button>
172
+ )}
173
+ </>
174
+ );
175
+
176
+ if (glass) {
177
+ // Default glass settings for callouts
178
+ const defaultGlassProps = {
179
+ displacementScale: 30,
180
+ cornerRadius: 8,
181
+ elasticity: 0,
182
+ };
183
+
184
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
81
185
 
82
- const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
186
+ return (
187
+ <div
188
+ className={generateCalloutClass({ variant, compact, isToast, glass, className })}
189
+ {...getAriaAttributes()}
190
+ {...props}
191
+ style={style}
192
+ >
193
+ <AtomixGlass {...glassProps}>
194
+ <div
195
+ className="c-callout__glass-content"
196
+ style={{ borderRadius: glassProps.cornerRadius }}
197
+ >
198
+ {calloutContent}
199
+ </div>
200
+ </AtomixGlass>
201
+ </div>
202
+ );
203
+ }
83
204
 
84
205
  return (
85
206
  <div
@@ -88,32 +209,23 @@ export const Callout: React.FC<CalloutProps> = ({
88
209
  {...props}
89
210
  style={style}
90
211
  >
91
- <AtomixGlass {...glassProps}>
92
- <div
93
- className="c-callout__glass-content"
94
- style={{ borderRadius: glassProps.cornerRadius }}
95
- >
96
- {calloutContent}
97
- </div>
98
- </AtomixGlass>
212
+ {calloutContent}
99
213
  </div>
100
214
  );
101
215
  }
102
-
103
- return (
104
- <div
105
- className={generateCalloutClass({ variant, compact, isToast, glass, className })}
106
- {...getAriaAttributes()}
107
- {...props}
108
- style={style}
109
- >
110
- {calloutContent}
111
- </div>
112
- );
113
- };
216
+ ) as unknown as CalloutComponent;
114
217
 
115
218
  Callout.displayName = 'Callout';
116
219
 
220
+ // Attach subcomponents
221
+ Callout.Icon = CalloutIcon;
222
+ Callout.Message = CalloutMessage;
223
+ Callout.Title = CalloutTitle;
224
+ Callout.Text = CalloutText;
225
+ Callout.Actions = CalloutActions;
226
+ Callout.CloseButton = CalloutCloseButton;
227
+ Callout.Content = CalloutContent;
228
+
117
229
  export type { CalloutProps };
118
230
 
119
231
  export default Callout;
@@ -0,0 +1,72 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { Callout } from './Callout';
4
+ import React from 'react';
5
+
6
+ describe('Callout Component', () => {
7
+ it('renders correctly with legacy props', () => {
8
+ render(
9
+ <Callout title="Legacy Title" icon={<span>Icon</span>}>
10
+ Legacy Content
11
+ </Callout>
12
+ );
13
+
14
+ expect(screen.getByText('Legacy Title')).toBeInTheDocument();
15
+ expect(screen.getByText('Legacy Content')).toBeInTheDocument();
16
+ expect(screen.getByText('Icon')).toBeInTheDocument();
17
+ });
18
+
19
+ it('renders correctly with compound components', () => {
20
+ render(
21
+ <Callout>
22
+ <Callout.Content>
23
+ <Callout.Icon>
24
+ <span>Compound Icon</span>
25
+ </Callout.Icon>
26
+ <Callout.Message>
27
+ <Callout.Title>Compound Title</Callout.Title>
28
+ <Callout.Text>Compound Text</Callout.Text>
29
+ </Callout.Message>
30
+ </Callout.Content>
31
+ <Callout.Actions>
32
+ <button>Action</button>
33
+ </Callout.Actions>
34
+ <Callout.CloseButton onClick={() => {}} />
35
+ </Callout>
36
+ );
37
+
38
+ expect(screen.getByText('Compound Icon')).toBeInTheDocument();
39
+ expect(screen.getByText('Compound Title')).toBeInTheDocument();
40
+ expect(screen.getByText('Compound Text')).toBeInTheDocument();
41
+ expect(screen.getByText('Action')).toBeInTheDocument();
42
+ expect(screen.getByLabelText('Close')).toBeInTheDocument();
43
+ });
44
+
45
+ it('prioritizes compound components over legacy props', () => {
46
+ render(
47
+ <Callout title="Legacy Title">
48
+ <Callout.Content>
49
+ <Callout.Message>
50
+ <Callout.Text>Compound Text</Callout.Text>
51
+ </Callout.Message>
52
+ </Callout.Content>
53
+ </Callout>
54
+ );
55
+
56
+ expect(screen.getByText('Compound Text')).toBeInTheDocument();
57
+ expect(screen.queryByText('Legacy Title')).not.toBeInTheDocument();
58
+ });
59
+
60
+ it('renders close button when used as compound', () => {
61
+ const onClose = vi.fn();
62
+ render(
63
+ <Callout>
64
+ <Callout.CloseButton onClick={onClose} />
65
+ </Callout>
66
+ );
67
+
68
+ const button = screen.getByLabelText('Close');
69
+ fireEvent.click(button);
70
+ expect(onClose).toHaveBeenCalled();
71
+ });
72
+ });
@@ -130,64 +130,64 @@ Cards are flexible containers for displaying content with optional headers, imag
130
130
  defaultValue: { summary: 'none' },
131
131
  },
132
132
  },
133
- row: {
134
- control: 'boolean',
133
+ row: {
134
+ control: 'boolean',
135
135
  description: 'Whether to arrange content horizontally',
136
136
  table: {
137
137
  type: { summary: 'boolean' },
138
138
  defaultValue: { summary: false },
139
139
  },
140
140
  },
141
- flat: {
142
- control: 'boolean',
141
+ flat: {
142
+ control: 'boolean',
143
143
  description: 'Whether to remove border radius',
144
144
  table: {
145
145
  type: { summary: 'boolean' },
146
146
  defaultValue: { summary: false },
147
147
  },
148
148
  },
149
- active: {
150
- control: 'boolean',
149
+ active: {
150
+ control: 'boolean',
151
151
  description: 'Whether the card is in active state',
152
152
  table: {
153
153
  type: { summary: 'boolean' },
154
154
  defaultValue: { summary: false },
155
155
  },
156
156
  },
157
- disabled: {
158
- control: 'boolean',
157
+ disabled: {
158
+ control: 'boolean',
159
159
  description: 'Whether the card is disabled',
160
160
  table: {
161
161
  type: { summary: 'boolean' },
162
162
  defaultValue: { summary: false },
163
163
  },
164
164
  },
165
- loading: {
166
- control: 'boolean',
165
+ loading: {
166
+ control: 'boolean',
167
167
  description: 'Whether the card is in loading state',
168
168
  table: {
169
169
  type: { summary: 'boolean' },
170
170
  defaultValue: { summary: false },
171
171
  },
172
172
  },
173
- selected: {
174
- control: 'boolean',
173
+ selected: {
174
+ control: 'boolean',
175
175
  description: 'Whether the card is selected',
176
176
  table: {
177
177
  type: { summary: 'boolean' },
178
178
  defaultValue: { summary: false },
179
179
  },
180
180
  },
181
- interactive: {
182
- control: 'boolean',
181
+ interactive: {
182
+ control: 'boolean',
183
183
  description: 'Whether the card responds to interactions',
184
184
  table: {
185
185
  type: { summary: 'boolean' },
186
186
  defaultValue: { summary: false },
187
187
  },
188
188
  },
189
- className: {
190
- control: 'text',
189
+ className: {
190
+ control: 'text',
191
191
  description: 'Additional CSS class names',
192
192
  table: {
193
193
  type: { summary: 'string' },
@@ -381,12 +381,14 @@ export const WithGlassEffect: Story = {
381
381
  parameters: {
382
382
  docs: {
383
383
  description: {
384
- story: 'Demonstrates a card with glass morphism effect applied, creating a translucent, frosted appearance that works well over colorful backgrounds.',
384
+ story:
385
+ 'Demonstrates a card with glass morphism effect applied, creating a translucent, frosted appearance that works well over colorful backgrounds.',
385
386
  },
386
387
  },
387
388
  },
388
389
  render: args => (
389
- <div className="u-bg-cover u-h-80vh u-w-90vw u-grid u-rounded-xl u-overflow-hidden"
390
+ <div
391
+ className="u-bg-cover u-h-80vh u-w-90vw u-grid u-rounded-xl u-overflow-hidden"
390
392
  style={{
391
393
  backgroundImage: `url(https://picsum.photos/id/128/1920/1024)`,
392
394
  }}
@@ -720,7 +722,8 @@ export const AllGlassModesComparison: Story = {
720
722
  parameters: {
721
723
  docs: {
722
724
  description: {
723
- story: 'Side-by-side comparison of all available glass morphism modes (standard, polar, prominent, shader) to help you choose the right effect for your design.',
725
+ story:
726
+ 'Side-by-side comparison of all available glass morphism modes (standard, polar, prominent, shader) to help you choose the right effect for your design.',
724
727
  },
725
728
  },
726
729
  },
@@ -966,7 +969,8 @@ export const GlassCardGallery: Story = {
966
969
  // Glass Card Layouts
967
970
  export const GlassCardLayouts: Story = {
968
971
  render: () => (
969
- <div className="u-bg-cover u-bg-center u-p-12 u-rounded-xl u-min-h-95vh u-min-w-95vw u-overflow-auto"
972
+ <div
973
+ className="u-bg-cover u-bg-center u-p-12 u-rounded-xl u-min-h-95vh u-min-w-95vw u-overflow-auto"
970
974
  style={{
971
975
  backgroundImage: 'url(https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?w=1920)',
972
976
  }}
@@ -979,9 +983,7 @@ export const GlassCardLayouts: Story = {
979
983
  <div className="u-flex u-gap-8">
980
984
  {/* Standard Layout */}
981
985
  <div className="u-w-50">
982
- <h3 className="u-text-white u-mb-4 u-text-shadow">
983
- Standard Layout
984
- </h3>
986
+ <h3 className="u-text-white u-mb-4 u-text-shadow">Standard Layout</h3>
985
987
  <Card
986
988
  title="Standard Glass Card"
987
989
  text="This is a standard glass card with vertical layout."
@@ -999,9 +1001,7 @@ export const GlassCardLayouts: Story = {
999
1001
 
1000
1002
  {/* Row Layout */}
1001
1003
  <div className="u-w-50">
1002
- <h3 className="u-text-white u-mb-4 u-text-shadow">
1003
- Row Layout
1004
- </h3>
1004
+ <h3 className="u-text-white u-mb-4 u-text-shadow">Row Layout</h3>
1005
1005
  <Card
1006
1006
  title="Row Glass Card"
1007
1007
  text="This is a row glass card with horizontal layout."
@@ -1024,9 +1024,7 @@ export const GlassCardLayouts: Story = {
1024
1024
 
1025
1025
  {/* Flat Layout */}
1026
1026
  <div className="u-w-50">
1027
- <h3 className="u-text-white u-mb-4 u-text-shadow">
1028
- Flat Layout
1029
- </h3>
1027
+ <h3 className="u-text-white u-mb-4 u-text-shadow">Flat Layout</h3>
1030
1028
  <Card
1031
1029
  title="Flat Glass Card"
1032
1030
  text="This is a flat glass card with edge-to-edge image."
@@ -1081,7 +1079,13 @@ export const SizeVariants: Story = {
1081
1079
  // Color Variants
1082
1080
  export const ColorVariants: Story = {
1083
1081
  render: () => (
1084
- <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1rem' }}>
1082
+ <div
1083
+ style={{
1084
+ display: 'grid',
1085
+ gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
1086
+ gap: '1rem',
1087
+ }}
1088
+ >
1085
1089
  <Card variant="primary" title="Primary Card" text="Primary variant card." />
1086
1090
  <Card variant="secondary" title="Secondary Card" text="Secondary variant card." />
1087
1091
  <Card variant="success" title="Success Card" text="Success variant card." />
@@ -1097,11 +1101,37 @@ export const ColorVariants: Story = {
1097
1101
  // Appearance Variants
1098
1102
  export const AppearanceVariants: Story = {
1099
1103
  render: () => (
1100
- <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1rem' }}>
1101
- <Card appearance="filled" variant="primary" title="Filled Card" text="Filled appearance with solid background." />
1102
- <Card appearance="outlined" variant="primary" title="Outlined Card" text="Outlined appearance with border only." />
1103
- <Card appearance="ghost" variant="primary" title="Ghost Card" text="Ghost appearance with minimal styling." />
1104
- <Card appearance="elevated" variant="primary" title="Elevated Card" text="Elevated appearance with shadow." />
1104
+ <div
1105
+ style={{
1106
+ display: 'grid',
1107
+ gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
1108
+ gap: '1rem',
1109
+ }}
1110
+ >
1111
+ <Card
1112
+ appearance="filled"
1113
+ variant="primary"
1114
+ title="Filled Card"
1115
+ text="Filled appearance with solid background."
1116
+ />
1117
+ <Card
1118
+ appearance="outlined"
1119
+ variant="primary"
1120
+ title="Outlined Card"
1121
+ text="Outlined appearance with border only."
1122
+ />
1123
+ <Card
1124
+ appearance="ghost"
1125
+ variant="primary"
1126
+ title="Ghost Card"
1127
+ text="Ghost appearance with minimal styling."
1128
+ />
1129
+ <Card
1130
+ appearance="elevated"
1131
+ variant="primary"
1132
+ title="Elevated Card"
1133
+ text="Elevated appearance with shadow."
1134
+ />
1105
1135
  </div>
1106
1136
  ),
1107
1137
  };
@@ -1188,7 +1218,8 @@ export const Comprehensive: Story = {
1188
1218
  parameters: {
1189
1219
  docs: {
1190
1220
  description: {
1191
- story: 'A comprehensive example demonstrating various card features including sizes, variants, appearances, elevations, and states in a grid layout.',
1221
+ story:
1222
+ 'A comprehensive example demonstrating various card features including sizes, variants, appearances, elevations, and states in a grid layout.',
1192
1223
  },
1193
1224
  },
1194
1225
  },
@@ -96,7 +96,24 @@ export const Card = React.memo(
96
96
  ]
97
97
  .filter(Boolean)
98
98
  .join(' '),
99
- [size, variant, appearance, elevation, hoverable, hoverElevation, row, flat, active, disabled, loading, selected, interactive, isClickable, glass, className]
99
+ [
100
+ size,
101
+ variant,
102
+ appearance,
103
+ elevation,
104
+ hoverable,
105
+ hoverElevation,
106
+ row,
107
+ flat,
108
+ active,
109
+ disabled,
110
+ loading,
111
+ selected,
112
+ interactive,
113
+ isClickable,
114
+ glass,
115
+ className,
116
+ ]
100
117
  );
101
118
 
102
119
  // Determine ARIA role
@@ -239,11 +256,7 @@ export const Card = React.memo(
239
256
 
240
257
  if (glass) {
241
258
  const glassProps = glass === true ? {} : glass;
242
- return (
243
- <AtomixGlass {...{ ...glassProps, elasticity: 0 }}>
244
- {anchorElement}
245
- </AtomixGlass>
246
- );
259
+ return <AtomixGlass {...{ ...glassProps, elasticity: 0 }}>{anchorElement}</AtomixGlass>;
247
260
  }
248
261
 
249
262
  return anchorElement;
@@ -258,11 +271,7 @@ export const Card = React.memo(
258
271
 
259
272
  if (glass) {
260
273
  const glassProps = glass === true ? {} : glass;
261
- return (
262
- <AtomixGlass {...{ ...glassProps, elasticity: 0 }}>
263
- {divElement}
264
- </AtomixGlass>
265
- );
274
+ return <AtomixGlass {...{ ...glassProps, elasticity: 0 }}>{divElement}</AtomixGlass>;
266
275
  }
267
276
 
268
277
  return divElement;
@@ -327,10 +336,16 @@ export interface CardBodyProps extends React.HTMLAttributes<HTMLDivElement> {
327
336
 
328
337
  export const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(
329
338
  ({ scrollable = false, maxHeight, children, className = '', style, ...props }, ref) => {
330
- const bodyClasses = `${CARD.SELECTORS.BODY.substring(1)} ${scrollable ? 'c-card__body--scrollable' : ''} ${className}`.trim();
339
+ const bodyClasses =
340
+ `${CARD.SELECTORS.BODY.substring(1)} ${scrollable ? 'c-card__body--scrollable' : ''} ${className}`.trim();
331
341
  const bodyStyle: React.CSSProperties = {
332
342
  ...style,
333
- ...(scrollable && maxHeight ? { maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight, overflowY: 'auto' } : {}),
343
+ ...(scrollable && maxHeight
344
+ ? {
345
+ maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,
346
+ overflowY: 'auto',
347
+ }
348
+ : {}),
334
349
  };
335
350
 
336
351
  return (
@@ -352,7 +367,8 @@ export interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {
352
367
 
353
368
  export const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(
354
369
  ({ align, children, className = '', style, ...props }, ref) => {
355
- const footerClasses = `${CARD.SELECTORS.FOOTER.substring(1)} ${align ? `c-card__footer--align-${align}` : ''} ${className}`.trim();
370
+ const footerClasses =
371
+ `${CARD.SELECTORS.FOOTER.substring(1)} ${align ? `c-card__footer--align-${align}` : ''} ${className}`.trim();
356
372
 
357
373
  return (
358
374
  <div ref={ref} className={footerClasses} style={style} {...props}>