@shohojdhara/atomix 0.3.13 → 0.3.15

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 (249) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +2 -0
  3. package/build-tools/EXAMPLES.md +372 -0
  4. package/build-tools/README.md +242 -0
  5. package/build-tools/__tests__/error-handler.test.js +230 -0
  6. package/build-tools/__tests__/index.test.js +141 -0
  7. package/build-tools/__tests__/rollup-plugin.test.js +194 -0
  8. package/build-tools/__tests__/utils.test.js +161 -0
  9. package/build-tools/__tests__/vite-plugin.test.js +129 -0
  10. package/build-tools/__tests__/webpack-loader.test.js +190 -0
  11. package/build-tools/error-handler.js +308 -0
  12. package/build-tools/index.d.ts +43 -0
  13. package/build-tools/index.js +88 -0
  14. package/build-tools/package.json +67 -0
  15. package/build-tools/rollup-plugin.js +236 -0
  16. package/build-tools/types.d.ts +163 -0
  17. package/build-tools/utils.js +203 -0
  18. package/build-tools/vite-plugin.js +161 -0
  19. package/build-tools/webpack-loader.js +123 -0
  20. package/dist/atomix.css +298 -167
  21. package/dist/atomix.css.map +1 -1
  22. package/dist/atomix.min.css +3 -3
  23. package/dist/atomix.min.css.map +1 -1
  24. package/dist/build-tools/EXAMPLES.md +372 -0
  25. package/dist/build-tools/README.md +242 -0
  26. package/dist/build-tools/__tests__/error-handler.test.js +230 -0
  27. package/dist/build-tools/__tests__/index.test.js +141 -0
  28. package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
  29. package/dist/build-tools/__tests__/utils.test.js +161 -0
  30. package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
  31. package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
  32. package/dist/build-tools/error-handler.js +308 -0
  33. package/dist/build-tools/index.d.ts +43 -0
  34. package/dist/build-tools/index.js +88 -0
  35. package/dist/build-tools/package.json +67 -0
  36. package/dist/build-tools/rollup-plugin.js +236 -0
  37. package/dist/build-tools/types.d.ts +163 -0
  38. package/dist/build-tools/utils.js +203 -0
  39. package/dist/build-tools/vite-plugin.js +161 -0
  40. package/dist/build-tools/webpack-loader.js +123 -0
  41. package/dist/charts.d.ts +2 -2
  42. package/dist/charts.js +87 -58
  43. package/dist/charts.js.map +1 -1
  44. package/dist/core.d.ts +42 -12
  45. package/dist/core.js +175 -135
  46. package/dist/core.js.map +1 -1
  47. package/dist/forms.d.ts +30 -16
  48. package/dist/forms.js +146 -131
  49. package/dist/forms.js.map +1 -1
  50. package/dist/heavy.d.ts +2 -2
  51. package/dist/heavy.js +151 -118
  52. package/dist/heavy.js.map +1 -1
  53. package/dist/index.d.ts +130 -106
  54. package/dist/index.esm.js +1083 -465
  55. package/dist/index.esm.js.map +1 -1
  56. package/dist/index.js +1102 -483
  57. package/dist/index.js.map +1 -1
  58. package/dist/index.min.js +1 -1
  59. package/dist/index.min.js.map +1 -1
  60. package/dist/theme.d.ts +27 -2
  61. package/dist/theme.js +721 -108
  62. package/dist/theme.js.map +1 -1
  63. package/package.json +23 -8
  64. package/scripts/atomix-cli.js +749 -1153
  65. package/scripts/cli/__tests__/README.md +81 -0
  66. package/scripts/cli/__tests__/basic.test.js +115 -0
  67. package/scripts/cli/__tests__/component-generator.test.js +332 -0
  68. package/scripts/cli/__tests__/integration.test.js +327 -0
  69. package/scripts/cli/__tests__/test-setup.js +133 -0
  70. package/scripts/cli/__tests__/token-manager.test.js +251 -0
  71. package/scripts/cli/__tests__/utils.test.js +78 -118
  72. package/scripts/cli/component-generator.js +564 -0
  73. package/scripts/cli/dependency-checker.js +355 -0
  74. package/scripts/cli/documentation-sync.js +542 -0
  75. package/scripts/cli/interactive-init.js +129 -292
  76. package/scripts/cli/mappings.js +211 -0
  77. package/scripts/cli/migration-tools.js +95 -288
  78. package/scripts/cli/template-manager.js +105 -0
  79. package/scripts/cli/templates/README.md +123 -0
  80. package/scripts/cli/templates/common-templates.js +636 -0
  81. package/scripts/cli/templates/composable-templates.js +171 -0
  82. package/scripts/cli/templates/config-templates.js +126 -0
  83. package/scripts/cli/templates/index.js +102 -0
  84. package/scripts/cli/templates/project-templates.js +342 -0
  85. package/scripts/cli/templates/react-templates.js +331 -0
  86. package/scripts/cli/templates/scss-templates.js +155 -0
  87. package/scripts/cli/templates/storybook-templates.js +236 -0
  88. package/scripts/cli/templates/testing-templates.js +224 -0
  89. package/scripts/cli/templates/testing-utils.js +278 -0
  90. package/scripts/cli/templates/token-templates.js +447 -0
  91. package/scripts/cli/templates/types-templates.js +147 -0
  92. package/scripts/cli/templates.js +35 -0
  93. package/scripts/cli/theme-bridge.js +28 -16
  94. package/scripts/cli/token-manager.js +432 -247
  95. package/scripts/cli/utils.js +37 -26
  96. package/src/components/Accordion/Accordion.stories.tsx +369 -870
  97. package/src/components/Accordion/Accordion.test.tsx +57 -0
  98. package/src/components/Accordion/Accordion.tsx +4 -0
  99. package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
  100. package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
  101. package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
  102. package/src/components/AtomixGlass/glass-utils.ts +2 -2
  103. package/src/components/AtomixGlass/shader-utils.ts +5 -0
  104. package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
  105. package/src/components/AtomixGlass/stories/Examples.stories.tsx +2965 -2861
  106. package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
  107. package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
  108. package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
  109. package/src/components/AtomixGlass/stories/Playground.stories.tsx +73 -59
  110. package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
  111. package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
  112. package/src/components/Avatar/Avatar.stories.tsx +239 -27
  113. package/src/components/Badge/Badge.stories.tsx +132 -373
  114. package/src/components/Badge/Badge.test.tsx +51 -0
  115. package/src/components/Badge/Badge.tsx +20 -1
  116. package/src/components/Block/Block.stories.tsx +26 -17
  117. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
  118. package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
  119. package/src/components/Button/Button.stories.tsx +463 -1126
  120. package/src/components/Button/Button.test.tsx +107 -0
  121. package/src/components/Button/Button.tsx +50 -54
  122. package/src/components/Button/ButtonGroup.stories.tsx +373 -217
  123. package/src/components/Button/README.md +5 -0
  124. package/src/components/Callout/Callout.stories.tsx +299 -644
  125. package/src/components/Callout/Callout.test.tsx +10 -10
  126. package/src/components/Callout/Callout.tsx +7 -7
  127. package/src/components/Callout/README.md +9 -8
  128. package/src/components/Card/Card.stories.tsx +248 -68
  129. package/src/components/Card/Card.tsx +2 -2
  130. package/src/components/Chart/Chart.stories.tsx +156 -14
  131. package/src/components/Chart/Chart.tsx +1 -1
  132. package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
  133. package/src/components/Countdown/Countdown.stories.tsx +115 -8
  134. package/src/components/DataTable/DataTable.stories.tsx +346 -146
  135. package/src/components/DataTable/DataTable.tsx +14 -12
  136. package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
  137. package/src/components/Dropdown/Dropdown.stories.tsx +157 -37
  138. package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
  139. package/src/components/Footer/Footer.stories.tsx +392 -328
  140. package/src/components/Form/Checkbox.stories.tsx +143 -9
  141. package/src/components/Form/Checkbox.test.tsx +63 -0
  142. package/src/components/Form/Checkbox.tsx +90 -52
  143. package/src/components/Form/Form.stories.tsx +121 -22
  144. package/src/components/Form/FormGroup.stories.tsx +128 -5
  145. package/src/components/Form/Input.stories.tsx +28 -16
  146. package/src/components/Form/Input.test.tsx +59 -0
  147. package/src/components/Form/Input.tsx +97 -95
  148. package/src/components/Form/Radio.stories.tsx +232 -97
  149. package/src/components/Form/Radio.tsx +2 -2
  150. package/src/components/Form/Select.stories.tsx +144 -12
  151. package/src/components/Form/Select.tsx +2 -2
  152. package/src/components/Form/Textarea.stories.tsx +171 -13
  153. package/src/components/Form/Textarea.test.tsx +45 -0
  154. package/src/components/Form/Textarea.tsx +88 -86
  155. package/src/components/Hero/Hero.stories.tsx +333 -32
  156. package/src/components/List/List.stories.tsx +143 -5
  157. package/src/components/Modal/Modal.stories.tsx +185 -46
  158. package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
  159. package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
  160. package/src/components/Navigation/README.md +1 -1
  161. package/src/components/Pagination/Pagination.stories.tsx +5 -2
  162. package/src/components/Pagination/Pagination.tsx +1 -1
  163. package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
  164. package/src/components/Popover/Popover.stories.tsx +449 -99
  165. package/src/components/ProductReview/ProductReview.tsx +1 -1
  166. package/src/components/Progress/Progress.stories.tsx +167 -5
  167. package/src/components/Progress/Progress.tsx +46 -46
  168. package/src/components/Rating/Rating.stories.tsx +4 -4
  169. package/src/components/Rating/Rating.tsx +8 -8
  170. package/src/components/River/River.stories.tsx +1 -1
  171. package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
  172. package/src/components/Slider/Slider.stories.tsx +63 -63
  173. package/src/components/Spinner/Spinner.stories.tsx +104 -10
  174. package/src/components/Spinner/Spinner.test.tsx +35 -0
  175. package/src/components/Spinner/Spinner.tsx +9 -2
  176. package/src/components/Steps/Steps.stories.tsx +172 -43
  177. package/src/components/Tabs/Tabs.stories.tsx +136 -10
  178. package/src/components/Testimonial/Testimonial.stories.tsx +121 -4
  179. package/src/components/Todo/Todo.stories.tsx +198 -9
  180. package/src/components/Toggle/Toggle.stories.tsx +153 -43
  181. package/src/components/Toggle/Toggle.test.tsx +91 -0
  182. package/src/components/Toggle/Toggle.tsx +44 -27
  183. package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
  184. package/src/components/Tooltip/Tooltip.tsx +1 -1
  185. package/src/components/Upload/Upload.stories.tsx +113 -24
  186. package/src/layouts/Grid/Grid.stories.tsx +49 -49
  187. package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
  188. package/src/lib/README.md +2 -2
  189. package/src/lib/__tests__/theme-tools.test.ts +193 -0
  190. package/src/lib/composables/index.ts +2 -2
  191. package/src/lib/composables/useAccordion.ts +12 -3
  192. package/src/lib/composables/useAtomixGlass.ts +28 -56
  193. package/src/lib/composables/useBreadcrumb.ts +2 -2
  194. package/src/lib/composables/useCallout.ts +7 -7
  195. package/src/lib/composables/useChartExport.ts +2 -7
  196. package/src/lib/composables/useDataTable.ts +46 -29
  197. package/src/lib/composables/useNavbar.ts +1 -1
  198. package/src/lib/constants/components.ts +10 -33
  199. package/src/lib/storybook/InteractiveDemo.tsx +113 -0
  200. package/src/lib/storybook/PreviewContainer.tsx +36 -0
  201. package/src/lib/storybook/VariantsGrid.tsx +21 -0
  202. package/src/lib/storybook/index.ts +3 -0
  203. package/src/lib/theme/core/createThemeObject.ts +9 -5
  204. package/src/lib/theme/devtools/CLI.ts +155 -0
  205. package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
  206. package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
  207. package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
  208. package/src/lib/theme/devtools/index.ts +3 -0
  209. package/src/lib/theme/errors/errors.ts +8 -0
  210. package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
  211. package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
  212. package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
  213. package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
  214. package/src/lib/theme/utils/index.ts +1 -0
  215. package/src/lib/theme/utils/themeValidation.ts +501 -0
  216. package/src/lib/theme-tools.ts +32 -3
  217. package/src/lib/types/components.ts +82 -27
  218. package/src/lib/utils/__tests__/csv.test.ts +45 -0
  219. package/src/lib/utils/csv.ts +17 -0
  220. package/src/lib/utils/dataTableExport.ts +1 -10
  221. package/src/lib/utils/themeNaming.ts +1 -1
  222. package/src/styles/01-settings/_index.scss +2 -1
  223. package/src/styles/01-settings/_settings.accordion.scss +28 -7
  224. package/src/styles/01-settings/_settings.colors.scss +11 -11
  225. package/src/styles/01-settings/_settings.typography.scss +5 -5
  226. package/src/styles/02-tools/_tools.utility-api.scss +14 -0
  227. package/src/styles/06-components/_components.accordion.scss +56 -14
  228. package/src/styles/06-components/_components.callout.scss +29 -33
  229. package/src/styles/06-components/_components.checkbox.scss +23 -17
  230. package/src/styles/06-components/_index.scss +1 -1
  231. package/src/styles/99-utilities/_index.scss +2 -0
  232. package/src/styles/99-utilities/_utilities.display.scss +14 -3
  233. package/src/styles/99-utilities/_utilities.flex.scss +10 -10
  234. package/src/styles/99-utilities/_utilities.scss +3 -1
  235. package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
  236. package/src/styles/99-utilities/_utilities.text.scss +28 -8
  237. package/themes/dark-complementary/README.md +98 -0
  238. package/themes/dark-complementary/index.scss +158 -0
  239. package/themes/default-light/README.md +81 -0
  240. package/themes/default-light/index.scss +154 -0
  241. package/themes/high-contrast/README.md +105 -0
  242. package/themes/high-contrast/index.scss +172 -0
  243. package/themes/test-theme/README.md +38 -0
  244. package/themes/test-theme/index.scss +47 -0
  245. package/scripts/cli/__tests__/cli-commands.test.js +0 -204
  246. package/scripts/cli/__tests__/vitest.config.js +0 -26
  247. package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
  248. package/src/lib/composables/useButton.ts +0 -93
  249. package/src/lib/composables/useCheckbox.ts +0 -70
@@ -0,0 +1,57 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { Accordion } from './Accordion';
4
+ import React from 'react';
5
+
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
+ });
57
+ });
@@ -12,6 +12,8 @@ export const Accordion: React.FC<AccordionProps> = memo(({
12
12
  defaultOpen = false,
13
13
  isOpen: controlledOpen,
14
14
  onOpenChange,
15
+ onOpen,
16
+ onClose,
15
17
  disabled = false,
16
18
  iconPosition = 'right',
17
19
  icon,
@@ -39,6 +41,8 @@ export const Accordion: React.FC<AccordionProps> = memo(({
39
41
  iconPosition,
40
42
  isOpen: controlledOpen,
41
43
  onOpenChange,
44
+ onOpen,
45
+ onClose,
42
46
  });
43
47
 
44
48
  // Default icon
@@ -57,7 +57,7 @@ import { useAtomixGlass } from '../../lib/composables/useAtomixGlass';
57
57
  *
58
58
  * @example
59
59
  * // OverLight - Object config with custom settings
60
- * <AtomixGlass
60
+ * <AtomixGlass
61
61
  * overLight={{
62
62
  * threshold: 0.8,
63
63
  * opacity: 0.6,
@@ -147,14 +147,16 @@ export function AtomixGlass({
147
147
  children,
148
148
  });
149
149
 
150
- // Use consistent overLight state from hook
151
- const isOverLight = overLightConfig.isOverLight;
150
+ // Calculate isOverLight independently from overLightConfig to prevent displacement changes on hover
151
+ // overLightConfig recalculates with hover/active states, but displacement should remain stable
152
+ const isOverLight = useMemo(() => overLightConfig?.isOverLight, [overLight]);
153
+
152
154
  const shouldRenderOverLightLayers = enableOverLightLayers && isOverLight;
153
155
 
154
156
  // Calculate base style with transforms
155
157
  const baseStyle = {
156
158
  ...style,
157
- ...(elasticity !== 0 && !effectiveDisableEffects && {
159
+ ...(!effectiveDisableEffects && {
158
160
  transform: transformStyle,
159
161
  }),
160
162
  };
@@ -171,26 +173,32 @@ export function AtomixGlass({
171
173
  .join(' ');
172
174
 
173
175
  // Calculate position and size styles
174
- const positionStyles = {
175
- position: (style.position || 'absolute') as React.CSSProperties['position'],
176
- top: style.top || 0,
177
- left: style.left || 0,
178
- };
176
+ const positionStyles = useMemo(
177
+ () => ({
178
+ position: (style.position || 'absolute') as React.CSSProperties['position'],
179
+ top: style.top || 0,
180
+ left: style.left || 0,
181
+ }),
182
+ [style.position, style.top, style.left]
183
+ );
179
184
 
180
- const adjustedSize = {
181
- width:
182
- style.position !== 'fixed'
183
- ? '100%'
184
- : style.width
185
- ? style.width
186
- : Math.max(glassSize.width, 0),
187
- height:
188
- style.position !== 'fixed'
189
- ? '100%'
190
- : style.height
191
- ? style.height
192
- : Math.max(glassSize.height, 0),
193
- };
185
+ const adjustedSize = useMemo(
186
+ () => ({
187
+ width:
188
+ style.position !== 'fixed'
189
+ ? '100%'
190
+ : style.width
191
+ ? style.width
192
+ : Math.max(glassSize.width, 0),
193
+ height:
194
+ style.position !== 'fixed'
195
+ ? '100%'
196
+ : style.height
197
+ ? style.height
198
+ : Math.max(glassSize.height, 0),
199
+ }),
200
+ [style.position, style.width, style.height, glassSize.width, glassSize.height]
201
+ );
194
202
 
195
203
  // Memoize expensive gradient calculations
196
204
  const gradientValues = useMemo(() => {
@@ -252,15 +260,30 @@ export function AtomixGlass({
252
260
  hover2: isActive ? 0.5 : 0,
253
261
  hover3: isHovered ? 0.4 : isActive ? 0.8 : 0,
254
262
  base: isOverLight ? overLightOpacity || BASE_OVER_LIGHT_OPACITY : 0,
255
- over: isOverLight ? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER : 0,
263
+ over: isOverLight
264
+ ? (overLightOpacity || BASE_OVER_LIGHT_OPACITY) * OVER_OPACITY_MULTIPLIER
265
+ : 0,
256
266
  };
257
267
  }, [isHovered, isActive, isOverLight, overLightConfig.opacity]);
258
268
 
259
269
  // Memoize CSS variables object
260
270
  const glassVars = useMemo(() => {
261
- const whiteColor = '255, 255, 255';
262
- const blackColor = '0, 0, 0';
263
- const { borderGradientAngle, borderStop1, borderStop2, borderOpacities, hoverPositions, basePosition, mx, my, absMx, absMy } = gradientValues;
271
+ const whiteColor = ATOMIX_GLASS.CONSTANTS.PALETTE.WHITE;
272
+ const blackColor = ATOMIX_GLASS.CONSTANTS.PALETTE.BLACK;
273
+ const {
274
+ borderGradientAngle,
275
+ borderStop1,
276
+ borderStop2,
277
+ borderOpacities,
278
+ hoverPositions,
279
+ basePosition,
280
+ mx,
281
+ my,
282
+ absMx,
283
+ absMy,
284
+ } = gradientValues;
285
+
286
+ const configBorderOpacity = overLightConfig?.borderOpacity ?? 1;
264
287
 
265
288
  return {
266
289
  '--atomix-glass-radius': `${effectiveCornerRadius}px`,
@@ -268,12 +291,14 @@ export function AtomixGlass({
268
291
  '--atomix-glass-position': positionStyles.position,
269
292
  '--atomix-glass-top': positionStyles.top !== 'fixed' ? `${positionStyles.top}px` : '0',
270
293
  '--atomix-glass-left': positionStyles.left !== 'fixed' ? `${positionStyles.left}px` : '0',
271
- '--atomix-glass-width': style.position !== 'fixed' ? adjustedSize.width : `${adjustedSize.width}px`,
272
- '--atomix-glass-height': style.position !== 'fixed' ? adjustedSize.height : `${adjustedSize.height}px`,
294
+ '--atomix-glass-width':
295
+ style.position !== 'fixed' ? adjustedSize.width : `${adjustedSize.width}px`,
296
+ '--atomix-glass-height':
297
+ style.position !== 'fixed' ? adjustedSize.height : `${adjustedSize.height}px`,
273
298
  '--atomix-glass-border-width': 'var(--atomix-spacing-0-5, 0.09375rem)',
274
299
  '--atomix-glass-blend-mode': isOverLight ? 'multiply' : 'overlay',
275
- '--atomix-glass-border-gradient-1': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacities[0]}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacities[1]}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
276
- '--atomix-glass-border-gradient-2': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${borderOpacities[2]}) ${borderStop1}%, rgba(${whiteColor}, ${borderOpacities[3]}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
300
+ '--atomix-glass-border-gradient-1': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[0] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[1] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
301
+ '--atomix-glass-border-gradient-2': `linear-gradient(${borderGradientAngle}deg, rgba(${whiteColor}, 0) 0%, rgba(${whiteColor}, ${(borderOpacities[2] ?? 1) * configBorderOpacity}) ${borderStop1}%, rgba(${whiteColor}, ${(borderOpacities[3] ?? 1) * configBorderOpacity}) ${borderStop2}%, rgba(${whiteColor}, 0) 100%)`,
277
302
  '--atomix-glass-hover-1-opacity': opacityValues.hover1,
278
303
  '--atomix-glass-hover-1-gradient': isOverLight
279
304
  ? `radial-gradient(circle at ${hoverPositions.hover1.x}% ${hoverPositions.hover1.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_START}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_STOP}%, rgba(${blackColor}, 0) ${ATOMIX_GLASS.CONSTANTS.GRADIENT_OPACITY.HOVER_1.BLACK_END}%)`
@@ -295,14 +320,26 @@ export function AtomixGlass({
295
320
  ? `radial-gradient(circle at ${basePosition.x}% ${basePosition.y}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_BASE + absMx * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_START_MULTIPLIER}) 0%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID}) ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_MID_STOP}%, rgba(${blackColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_BASE + absMy * ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.BLACK_END_MULTIPLIER}) 100%)`
296
321
  : `rgba(${whiteColor}, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_GRADIENT.WHITE_OPACITY})`,
297
322
  } as React.CSSProperties;
298
- }, [gradientValues, opacityValues, effectiveCornerRadius, transformStyle, positionStyles, adjustedSize, style.position, isOverLight]);
323
+ }, [
324
+ gradientValues,
325
+ opacityValues,
326
+ effectiveCornerRadius,
327
+ transformStyle,
328
+ positionStyles,
329
+ adjustedSize,
330
+ style.position,
331
+ isOverLight,
332
+ overLightConfig.borderOpacity,
333
+ ]);
299
334
 
300
335
  // Helper function to render background layers
301
336
  const renderBackgroundLayer = (layerType: 'dark' | 'black') => (
302
337
  <div
303
338
  className={[
304
339
  ATOMIX_GLASS.BACKGROUND_LAYER_CLASS,
305
- layerType === 'dark' ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS,
340
+ layerType === 'dark'
341
+ ? ATOMIX_GLASS.BACKGROUND_LAYER_DARK_CLASS
342
+ : ATOMIX_GLASS.BACKGROUND_LAYER_BLACK_CLASS,
306
343
  isOverLight
307
344
  ? ATOMIX_GLASS.BACKGROUND_LAYER_OVER_LIGHT_CLASS
308
345
  : ATOMIX_GLASS.BACKGROUND_LAYER_HIDDEN_CLASS,
@@ -342,7 +379,7 @@ export function AtomixGlass({
342
379
  ? 0
343
380
  : mode === 'shader'
344
381
  ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.SHADER_DISPLACEMENT
345
- : overLightConfig.isOverLight
382
+ : isOverLight
346
383
  ? displacementScale * ATOMIX_GLASS.CONSTANTS.MULTIPLIERS.OVER_LIGHT_DISPLACEMENT
347
384
  : displacementScale
348
385
  }
@@ -350,7 +387,7 @@ export function AtomixGlass({
350
387
  saturation={
351
388
  effectiveHighContrast
352
389
  ? ATOMIX_GLASS.CONSTANTS.SATURATION.HIGH_CONTRAST
353
- : overLightConfig.isOverLight
390
+ : isOverLight
354
391
  ? saturation * overLightConfig.saturationBoost
355
392
  : saturation
356
393
  }
@@ -369,10 +406,15 @@ export function AtomixGlass({
369
406
  onMouseLeave={handleMouseLeave}
370
407
  onMouseDown={handleMouseDown}
371
408
  onMouseUp={handleMouseUp}
372
- active={isActive}
373
409
  isHovered={isHovered}
374
410
  isActive={isActive}
375
- overLight={overLightConfig.isOverLight}
411
+ overLight={isOverLight}
412
+ overLightConfig={{
413
+ contrast: overLightConfig.contrast,
414
+ brightness: overLightConfig.brightness,
415
+ shadowIntensity: overLightConfig.shadowIntensity,
416
+ borderOpacity: overLightConfig.borderOpacity,
417
+ }}
376
418
  onClick={onClick}
377
419
  mode={mode}
378
420
  transform={baseStyle.transform}
@@ -407,8 +449,7 @@ export function AtomixGlass({
407
449
  className={ATOMIX_GLASS.OVERLAY_HIGHLIGHT_CLASS}
408
450
  style={{
409
451
  opacity:
410
- opacityValues.over *
411
- ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
452
+ opacityValues.over * ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.OPACITY_MULTIPLIER,
412
453
  background: `radial-gradient(circle at ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_X}% ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.POSITION_Y}%, rgba(255, 255, 255, ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.WHITE_OPACITY}) 0%, transparent ${ATOMIX_GLASS.CONSTANTS.OVERLAY_HIGHLIGHT.STOP}%)`,
413
454
  }}
414
455
  />
@@ -3,13 +3,7 @@ import type { CSSProperties } from 'react';
3
3
  import type { DisplacementMode, MousePosition, GlassSize } from '../../lib/types/components';
4
4
  import type { FragmentShaderType } from './shader-utils';
5
5
  import { GlassFilter } from './GlassFilter';
6
- import {
7
- calculateElementCenter,
8
- calculateDistance,
9
- calculateMouseInfluence,
10
- clampBlur,
11
- validateGlassSize,
12
- } from './glass-utils';
6
+ import { calculateMouseInfluence, clampBlur, validateGlassSize } from './glass-utils';
13
7
  import { ATOMIX_GLASS } from '../../lib/constants/components';
14
8
 
15
9
  const { CONSTANTS } = ATOMIX_GLASS;
@@ -58,7 +52,9 @@ const setCachedShader = (key: string, url: string): void => {
58
52
  // Development mode: log cache size
59
53
  if (typeof process === 'undefined' || process.env?.NODE_ENV !== 'production') {
60
54
  if (sharedShaderCache.size >= MAX_CACHE_SIZE * 0.8) {
61
- console.log(`AtomixGlass: Shader cache size: ${String(sharedShaderCache.size).replace(/[\r\n]/g, '')}/${String(MAX_CACHE_SIZE).replace(/[\r\n]/g, '')}`);
55
+ console.log(
56
+ `AtomixGlass: Shader cache size: ${String(sharedShaderCache.size).replace(/[\r\n]/g, '')}/${String(MAX_CACHE_SIZE).replace(/[\r\n]/g, '')}`
57
+ );
62
58
  }
63
59
  }
64
60
  };
@@ -76,10 +72,15 @@ interface AtomixGlassContainerProps {
76
72
  onMouseEnter?: () => void;
77
73
  onMouseDown?: () => void;
78
74
  onMouseUp?: () => void;
79
- active?: boolean;
80
75
  isHovered?: boolean;
81
76
  isActive?: boolean;
82
77
  overLight?: boolean;
78
+ overLightConfig?: {
79
+ contrast?: number;
80
+ brightness?: number;
81
+ shadowIntensity?: number;
82
+ borderOpacity?: number;
83
+ };
83
84
  cornerRadius?: number;
84
85
  padding?: string;
85
86
  glassSize?: GlassSize;
@@ -115,10 +116,10 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
115
116
  onMouseLeave,
116
117
  onMouseDown,
117
118
  onMouseUp,
118
- active = false,
119
119
  isHovered = false,
120
120
  isActive = false,
121
121
  overLight = false,
122
+ overLightConfig = {},
122
123
  cornerRadius = 0,
123
124
  padding = '0 0',
124
125
  glassSize = { width: 0, height: 0 },
@@ -153,14 +154,19 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
153
154
  useEffect(() => {
154
155
  if (mode === 'shader') {
155
156
  // Dynamic import shader utilities
156
- import('./shader-utils').then((shaderUtils) => {
157
- shaderUtilsRef.current = {
158
- ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
159
- fragmentShaders: shaderUtils.fragmentShaders,
160
- };
161
- }).catch((error) => {
162
- console.warn('AtomixGlassContainer: Error loading shader utilities', String(error).replace(/[\r\n]/g, ''));
163
- });
157
+ import('./shader-utils')
158
+ .then(shaderUtils => {
159
+ shaderUtilsRef.current = {
160
+ ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
161
+ fragmentShaders: shaderUtils.fragmentShaders,
162
+ };
163
+ })
164
+ .catch(error => {
165
+ console.warn(
166
+ 'AtomixGlassContainer: Error loading shader utilities',
167
+ String(error).replace(/[\r\n]/g, '')
168
+ );
169
+ });
164
170
  } else {
165
171
  // Clear shader utils when not in shader mode to free memory
166
172
  shaderUtilsRef.current = null;
@@ -170,7 +176,12 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
170
176
  // Generate shader map with debouncing and caching
171
177
  useEffect(() => {
172
178
  // Enhanced validation for shader mode
173
- if (mode === 'shader' && glassSize && validateGlassSize(glassSize) && shaderUtilsRef.current) {
179
+ if (
180
+ mode === 'shader' &&
181
+ glassSize &&
182
+ validateGlassSize(glassSize) &&
183
+ shaderUtilsRef.current
184
+ ) {
174
185
  // Create cache key from size and variant
175
186
  const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`;
176
187
 
@@ -262,11 +273,13 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
262
273
  const EDGE_BLUR_MULTIPLIER = 1.25;
263
274
  const CENTER_BLUR_MULTIPLIER = 1.1;
264
275
  const FLOW_BLUR_MULTIPLIER = 1.2;
265
- const MOUSE_INFLUENCE_BLUR_FACTOR = 0.4;
276
+ const MOUSE_INFLUENCE_BLUR_FACTOR = 0.15;
266
277
  const EDGE_INTENSITY_MULTIPLIER = 1.5;
267
- const EDGE_INTENSITY_MOUSE_FACTOR = 0.3;
278
+ const EDGE_INTENSITY_MOUSE_FACTOR = 0.15;
268
279
  const CENTER_INTENSITY_DISTANCE_FACTOR = 0.3;
269
- const CENTER_INTENSITY_MOUSE_FACTOR = 0.2;
280
+ const CENTER_INTENSITY_MOUSE_FACTOR = 0.1;
281
+ // Maximum blur multiplier relative to base — prevents runaway blur
282
+ const MAX_BLUR_RELATIVE = 2;
270
283
 
271
284
  const liquidBlur = useMemo(() => {
272
285
  const defaultBlur = {
@@ -280,60 +293,42 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
280
293
  if (
281
294
  !enableLiquidBlur ||
282
295
  !rectCache ||
283
- !globalMousePosition ||
284
- typeof globalMousePosition.x !== 'number' ||
285
- typeof globalMousePosition.y !== 'number' ||
286
- isNaN(globalMousePosition.x) ||
287
- isNaN(globalMousePosition.y)
296
+ !mouseOffset ||
297
+ typeof mouseOffset.x !== 'number' ||
298
+ typeof mouseOffset.y !== 'number' ||
299
+ isNaN(mouseOffset.x) ||
300
+ isNaN(mouseOffset.y)
288
301
  ) {
289
302
  return defaultBlur;
290
303
  }
291
304
 
292
305
  try {
293
- // Cache center and distance calculations
294
- const center = calculateElementCenter(rectCache);
295
- const distance = calculateDistance(globalMousePosition, center);
296
- const maxDistance =
297
- Math.sqrt(rectCache.width * rectCache.width + rectCache.height * rectCache.height) / 2;
298
- const normalizedDistance = Math.min(distance / maxDistance, 1);
299
306
  const mouseInfluence = calculateMouseInfluence(mouseOffset);
307
+ const maxBlur = blurAmount * MAX_BLUR_RELATIVE;
300
308
 
301
- const baseBlur = blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR;
302
- const edgeIntensity = normalizedDistance * EDGE_INTENSITY_MULTIPLIER + mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR;
303
- const edgeBlur = baseBlur * (0.8 + edgeIntensity * 0.6);
304
- const centerIntensity = (1 - normalizedDistance) * CENTER_INTENSITY_DISTANCE_FACTOR + mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR;
305
- const centerBlur = baseBlur * (0.3 + centerIntensity * 0.4);
306
- const deltaX = globalMousePosition.x - center.x;
307
- const deltaY = globalMousePosition.y - center.y;
308
- const flowDirection = Math.atan2(deltaY, deltaX);
309
- const flowIntensity = Math.sin(flowDirection + mouseInfluence * Math.PI) * 0.5 + 0.5;
310
- const flowBlur = baseBlur * (0.4 + flowIntensity * 0.6);
311
-
312
- const hoverMultiplier = isHovered ? 1.2 : 1;
313
- const activeMultiplier = isActive ? 1.4 : 1;
314
- const stateMultiplier = hoverMultiplier * activeMultiplier;
315
-
309
+ const baseBlur = Math.min(
310
+ maxBlur,
311
+ blurAmount + mouseInfluence * blurAmount * MOUSE_INFLUENCE_BLUR_FACTOR
312
+ );
313
+ const edgeIntensity = mouseInfluence * EDGE_INTENSITY_MOUSE_FACTOR;
314
+ const edgeBlur = Math.min(maxBlur, baseBlur * (0.8 + edgeIntensity * 0.4));
315
+ const centerIntensity = mouseInfluence * CENTER_INTENSITY_MOUSE_FACTOR;
316
+ const centerBlur = Math.min(maxBlur, baseBlur * (0.3 + centerIntensity * 0.3));
317
+ const flowBlur = Math.min(maxBlur, baseBlur * FLOW_BLUR_MULTIPLIER);
318
+
319
+ // NOTE: hover/active multipliers intentionally omitted here —
320
+ // they belong on opacity layers, not the blur filter itself.
316
321
  return {
317
- baseBlur: clampBlur(baseBlur * stateMultiplier),
318
- edgeBlur: clampBlur(edgeBlur * stateMultiplier),
319
- centerBlur: clampBlur(centerBlur * stateMultiplier),
320
- flowBlur: clampBlur(flowBlur * stateMultiplier),
322
+ baseBlur: clampBlur(baseBlur),
323
+ edgeBlur: clampBlur(edgeBlur),
324
+ centerBlur: clampBlur(centerBlur),
325
+ flowBlur: clampBlur(flowBlur),
321
326
  };
322
327
  } catch (error) {
323
328
  console.warn('AtomixGlassContainer: Error calculating liquid blur', error);
324
329
  return defaultBlur;
325
330
  }
326
- }, [
327
- enableLiquidBlur,
328
- blurAmount,
329
- globalMousePosition,
330
- mouseOffset,
331
- isHovered,
332
- isActive,
333
- rectCache,
334
- style,
335
- glassSize,
336
- ]);
331
+ }, [enableLiquidBlur, blurAmount, mouseOffset, rectCache]);
337
332
 
338
333
  const backdropStyle = useMemo(() => {
339
334
  try {
@@ -364,15 +359,18 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
364
359
  const useMultiPass = enableLiquidBlur && !devicePrefersPerformance && !areaIsLarge;
365
360
 
366
361
  if (useMultiPass) {
367
- const blurLayers = [
368
- `blur(${validatedBaseBlur}px)`,
369
- `blur(${validatedEdgeBlur}px)`,
370
- `blur(${validatedCenterBlur}px)`,
371
- `blur(${validatedFlowBlur}px)`,
372
- ];
362
+ // Use a single weighted-average blur instead of stacking multiple
363
+ // blur() calls. CSS blur() is additive — stacking 4 passes
364
+ // causes the perceived blur to compound far beyond any single value.
365
+ const weightedBlur = clampBlur(
366
+ validatedBaseBlur * 0.4 +
367
+ validatedEdgeBlur * 0.25 +
368
+ validatedCenterBlur * 0.15 +
369
+ validatedFlowBlur * 0.2
370
+ );
373
371
 
374
372
  return {
375
- backdropFilter: `${blurLayers.join(' ')} saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`,
373
+ backdropFilter: `blur(${weightedBlur}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`,
376
374
  };
377
375
  }
378
376
 
@@ -387,7 +385,7 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
387
385
  );
388
386
 
389
387
  return {
390
- backdropFilter: `blur(${effectiveBlur}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(1.05) brightness(1.05)`,
388
+ backdropFilter: `blur(${effectiveBlur}px) saturate(${Math.min(dynamicSaturation, 200)}%) contrast(${overLightConfig?.contrast || 1.05}) brightness(${overLightConfig?.brightness || 1.05})`,
391
389
  };
392
390
  } catch (error) {
393
391
  console.warn('AtomixGlassContainer: Error calculating backdrop style', error);
@@ -424,11 +422,11 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
424
422
  '--atomix-glass-container-backdrop': backdropStyle?.backdropFilter || 'none',
425
423
  '--atomix-glass-container-shadow': overLight
426
424
  ? [
427
- `inset 0 1px 0 rgba(255, 255, 255, ${0.4 + mx * 0.002})`,
428
- `inset 0 -1px 0 rgba(0, 0, 0, ${0.2 + Math.abs(my) * 0.001})`,
429
- `inset 0 0 20px rgba(0, 0, 0, ${0.08 + Math.abs(mx + my) * 0.001})`,
430
- `0 2px 12px rgba(0, 0, 0, ${0.12 + Math.abs(my) * 0.002})`,
431
- ].join(', ')
425
+ `inset 0 1px 0 rgba(255, 255, 255, ${(0.4 + mx * 0.002) * (overLightConfig?.shadowIntensity || 1)})`,
426
+ `inset 0 -1px 0 rgba(0, 0, 0, ${(0.2 + Math.abs(my) * 0.001) * (overLightConfig?.shadowIntensity || 1)})`,
427
+ `inset 0 0 20px rgba(0, 0, 0, ${(0.08 + Math.abs(mx + my) * 0.001) * (overLightConfig?.shadowIntensity || 1)})`,
428
+ `0 2px 12px rgba(0, 0, 0, ${(0.12 + Math.abs(my) * 0.002) * (overLightConfig?.shadowIntensity || 1)})`,
429
+ ].join(', ')
432
430
  : '0 0 20px rgba(0, 0, 0, 0.15) inset, 0 4px 8px rgba(0, 0, 0, 0.08) inset',
433
431
  '--atomix-glass-container-shadow-opacity': effectiveDisableEffects ? 0 : 1,
434
432
  // Background and shadow values use design token-aligned RGB values
@@ -464,10 +462,29 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
464
462
  effectiveDisableEffects,
465
463
  ]);
466
464
 
465
+ // Helper to force no transition/animation overrides with !important
466
+ const setForceNoTransition = (el: HTMLElement | null) => {
467
+ if (el) {
468
+ el.style.setProperty('transition-duration', '0s', 'important');
469
+ el.style.setProperty('animation-duration', '0s', 'important');
470
+ el.style.setProperty('transition-delay', '0s', 'important');
471
+ }
472
+ };
473
+
467
474
  return (
468
475
  <div
469
- ref={ref}
470
- className={`${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${active ? ATOMIX_GLASS.CLASSES.ACTIVE : ''} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ''}`}
476
+ ref={el => {
477
+ // Apply force no-transition
478
+ setForceNoTransition(el);
479
+
480
+ // Handle forwarded ref
481
+ if (typeof ref === 'function') {
482
+ ref(el);
483
+ } else if (ref) {
484
+ (ref as React.MutableRefObject<HTMLDivElement | null>).current = el;
485
+ }
486
+ }}
487
+ className={`${ATOMIX_GLASS.CONTAINER_CLASS} ${className} ${isActive ? ATOMIX_GLASS.CLASSES.ACTIVE : ''} ${overLight ? ATOMIX_GLASS.CLASSES.OVER_LIGHT : ''}`}
471
488
  style={{ ...style, ...containerVars }}
472
489
  onClick={onClick}
473
490
  >
@@ -484,7 +501,10 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
484
501
  onMouseDown={onMouseDown}
485
502
  onMouseUp={onMouseUp}
486
503
  >
487
- <div className={ATOMIX_GLASS.FILTER_CLASS}>
504
+ <div
505
+ className={ATOMIX_GLASS.FILTER_CLASS}
506
+ style={{ zIndex: 1, position: 'absolute', inset: 0 }}
507
+ >
488
508
  <GlassFilter
489
509
  blurAmount={blurAmount}
490
510
  mode={mode}
@@ -503,6 +523,7 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
503
523
  />
504
524
  {/* Enhanced Apple Liquid Glass Inner Shadow Layer */}
505
525
  <div
526
+ ref={setForceNoTransition}
506
527
  className={ATOMIX_GLASS.FILTER_OVERLAY_CLASS}
507
528
  style={
508
529
  {
@@ -532,7 +553,8 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
532
553
  {
533
554
  position: 'relative',
534
555
  textShadow: `var(--atomix-glass-container-text-shadow)`,
535
- ...(elasticity > 0 ? { zIndex: 100 } : {}),
556
+ // Ensure content is always above the filter layer (zIndex 1)
557
+ zIndex: elasticity > 0 ? 100 : 2,
536
558
  } as CSSProperties
537
559
  }
538
560
  >
@@ -544,4 +566,4 @@ export const AtomixGlassContainer = forwardRef<HTMLDivElement, AtomixGlassContai
544
566
  }
545
567
  );
546
568
 
547
- AtomixGlassContainer.displayName = 'AtomixGlassContainer';
569
+ AtomixGlassContainer.displayName = 'AtomixGlassContainer';