@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,107 @@
1
+ import { render, screen, fireEvent } from '@testing-library/react';
2
+ import { describe, it, expect, vi } from 'vitest';
3
+ import { axe, toHaveNoViolations } from 'jest-axe';
4
+ import { Button } from './Button';
5
+ import React from 'react';
6
+
7
+ expect.extend(toHaveNoViolations);
8
+
9
+ // Mock AtomixGlass component
10
+ vi.mock('../AtomixGlass/AtomixGlass', () => ({
11
+ AtomixGlass: ({ children, ...props }: any) => (
12
+ <div data-testid="atomix-glass" data-glass-props={JSON.stringify(props)}>
13
+ {children}
14
+ </div>
15
+ ),
16
+ }));
17
+
18
+ describe('Button Component', () => {
19
+ it('renders correctly with label', () => {
20
+ render(<Button label="Click Me" />);
21
+ expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
22
+ });
23
+
24
+ it('renders correctly with children', () => {
25
+ render(<Button>Click Me</Button>);
26
+ expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument();
27
+ });
28
+
29
+ it('handles onClick event', () => {
30
+ const handleClick = vi.fn();
31
+ render(<Button onClick={handleClick}>Click Me</Button>);
32
+ fireEvent.click(screen.getByRole('button'));
33
+ expect(handleClick).toHaveBeenCalledTimes(1);
34
+ });
35
+
36
+ it('does not fire onClick when disabled', () => {
37
+ const handleClick = vi.fn();
38
+ render(<Button disabled onClick={handleClick}>Click Me</Button>);
39
+ const button = screen.getByRole('button');
40
+ expect(button).toBeDisabled();
41
+ fireEvent.click(button);
42
+ expect(handleClick).not.toHaveBeenCalled();
43
+ });
44
+
45
+ it('renders loading state correctly', () => {
46
+ render(<Button loading>Submit</Button>);
47
+ const button = screen.getByRole('button');
48
+ // It should be disabled or aria-disabled
49
+ expect(button).toHaveAttribute('aria-busy', 'true');
50
+ // Check for spinner (implementation detail: spinner usually has specific class or role)
51
+ // Based on Button.tsx: <span className="...spinner...">...</span>
52
+ // Let's look for the spinner component or class if we can't find by role
53
+ // Or check if text is still there.
54
+ expect(screen.getByText('Submit')).toBeInTheDocument();
55
+ });
56
+
57
+ it('replaces text with loadingText when loading', () => {
58
+ render(<Button loading loadingText="Processing...">Submit</Button>);
59
+ expect(screen.queryByText('Submit')).not.toBeInTheDocument();
60
+ expect(screen.getByText('Processing...')).toBeInTheDocument();
61
+ });
62
+
63
+ it('renders as a link when href is provided', () => {
64
+ render(<Button href="/home">Home</Button>);
65
+ const link = screen.getByRole('link', { name: /home/i });
66
+ expect(link).toHaveAttribute('href', '/home');
67
+ });
68
+
69
+ it('renders as disabled link when disabled and href provided', () => {
70
+ // Current implementation might be buggy here, let's see
71
+ render(<Button href="/home" disabled>Home</Button>);
72
+ const link = screen.queryByRole('link');
73
+ const button = screen.queryByRole('button');
74
+
75
+ // If it renders as button when disabled (which logic suggested), then:
76
+ if (button) {
77
+ expect(button).toBeDisabled();
78
+ } else if (link) {
79
+ expect(link).toHaveAttribute('aria-disabled', 'true');
80
+ // Should not navigate
81
+ }
82
+ });
83
+
84
+ it('forwards ref', () => {
85
+ const ref = React.createRef<HTMLButtonElement>();
86
+ render(<Button ref={ref}>Ref Button</Button>);
87
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
88
+ });
89
+
90
+ it('handles iconOnly correctly with aria-label', () => {
91
+ render(<Button iconOnly icon={<span>Icon</span>} aria-label="Icon Button" />);
92
+ expect(screen.getByLabelText('Icon Button')).toBeInTheDocument();
93
+ });
94
+
95
+ it('does not render [object Object] as aria-label when children is an element', () => {
96
+ const { container } = render(<Button iconOnly icon={<span>Icon</span>}><span>Text</span></Button>);
97
+ const button = screen.getByRole('button');
98
+ // aria-label should probably be undefined or empty, or extracted text, but definitely not "[object Object]"
99
+ expect(button.getAttribute('aria-label')).not.toBe('[object Object]');
100
+ });
101
+
102
+ it('should have no accessibility violations', async () => {
103
+ const { container } = render(<Button>Accessible Button</Button>);
104
+ const results = await axe(container);
105
+ expect(results).toHaveNoViolations();
106
+ });
107
+ });
@@ -1,5 +1,4 @@
1
1
  import React, { ElementType, forwardRef, useCallback } from 'react';
2
- import { useButton } from '../../lib/composables/useButton';
3
2
  import { ButtonProps } from '../../lib/types/components';
4
3
  import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
5
4
  import { Spinner } from '../Spinner/Spinner';
@@ -46,10 +45,10 @@ export const Button = React.memo(
46
45
  onHover,
47
46
  onFocus,
48
47
  onBlur,
49
- ariaLabel,
50
- ariaDescribedBy,
51
- ariaExpanded,
52
- ariaControls,
48
+ 'aria-label': ariaLabel,
49
+ 'aria-describedby': ariaDescribedBy,
50
+ 'aria-expanded': ariaExpanded,
51
+ 'aria-controls': ariaControls,
53
52
  tabIndex,
54
53
  style,
55
54
  LinkComponent,
@@ -60,24 +59,14 @@ export const Button = React.memo(
60
59
  const isDisabled = disabled || loading;
61
60
 
62
61
  // Determine if we should render as a link
62
+ // If disabled, we still check href, but we might want to render as button or anchor with aria-disabled
63
+ // The previous logic was Boolean(href && !isDisabled). This meant if disabled, it renders as <button>.
64
+ // This is a safe fallback for disabled links.
63
65
  const shouldRenderAsLink = Boolean(href && !isDisabled);
64
66
 
65
67
  // Resolve icon element - support both icon (ReactNode) and iconName (string)
66
68
  const iconElement = iconName ? <Icon name={iconName as PhosphorIconsType} size={iconSize} /> : icon;
67
69
 
68
- const { generateButtonClass, handleClick } = useButton({
69
- variant,
70
- size,
71
- disabled: isDisabled,
72
- rounded,
73
- glass,
74
- loading,
75
- fullWidth,
76
- block,
77
- active,
78
- selected,
79
- });
80
-
81
70
  const buttonClass = [
82
71
  BUTTON.BASE_CLASS,
83
72
  ThemeNaming.variantClass(THEME_NAMING.BUTTON_PREFIX, variant),
@@ -144,6 +133,9 @@ export const Button = React.memo(
144
133
  // Determine spinner size based on button size
145
134
  const spinnerSize = size === 'sm' ? 'sm' : size === 'lg' ? 'md' : 'sm';
146
135
 
136
+ // Safe Aria Label
137
+ const safeAriaLabel = ariaLabel || (iconOnly ? (typeof label === 'string' ? label : (typeof children === 'string' ? children : undefined)) : undefined);
138
+
147
139
  // Button content with icon positioning
148
140
  const buttonContent = (
149
141
  <>
@@ -172,17 +164,14 @@ export const Button = React.memo(
172
164
 
173
165
  // Button props
174
166
  const buttonProps = {
175
- ref,
176
167
  className: buttonClass,
177
- type: Component === 'button' && !shouldRenderAsLink ? type : undefined,
178
168
  onClick: handleClickEvent,
179
169
  onMouseEnter: onHover ? handleMouseEnter : undefined,
180
170
  onFocus: onFocus ? handleFocusEvent : undefined,
181
171
  onBlur: onBlur ? handleBlurEvent : undefined,
182
- disabled: isDisabled && Component === 'button' && !shouldRenderAsLink,
183
172
  'aria-disabled': isDisabled,
184
173
  'aria-busy': loading,
185
- 'aria-label': ariaLabel || (iconOnly ? label || children : undefined),
174
+ 'aria-label': safeAriaLabel,
186
175
  'aria-describedby': ariaDescribedBy,
187
176
  'aria-expanded': ariaExpanded,
188
177
  'aria-controls': ariaControls,
@@ -191,60 +180,67 @@ export const Button = React.memo(
191
180
  ...props,
192
181
  };
193
182
 
194
- // Default glass props
195
- const defaultGlassProps = {
196
- displacementScale: 20,
197
- blurAmount: 0,
198
- saturation: 200,
199
- elasticity: 0,
200
- };
201
- const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
183
+ let content: React.ReactElement;
202
184
 
203
185
  // Render as anchor if href is provided
204
186
  if (shouldRenderAsLink) {
205
- const { ref: _, ...buttonPropsWithoutRef } = buttonProps;
206
- const anchorButtonProps = {
207
- ...buttonPropsWithoutRef,
208
- type: undefined,
209
- disabled: undefined,
210
- };
211
-
212
187
  // Use custom LinkComponent if provided (e.g., Next.js Link)
213
188
  if (LinkComponent) {
214
189
  const LinkComp = LinkComponent as React.ComponentType<any>;
215
190
  const linkProps = {
216
- ...anchorButtonProps,
217
- ref: ref as React.Ref<HTMLAnchorElement>,
191
+ ...buttonProps,
192
+ ref: ref as any, // LinkComponent usually forwards ref to anchor
218
193
  href,
219
194
  target,
220
195
  rel: target === '_blank' ? 'noopener noreferrer' : undefined,
221
196
  };
222
197
 
223
- const linkElement = (
198
+ content = (
224
199
  <LinkComp {...linkProps}>
225
200
  {buttonContent}
226
201
  </LinkComp>
227
202
  );
228
-
229
- return glass ? <AtomixGlass {...glassProps}>{linkElement}</AtomixGlass> : linkElement;
203
+ } else {
204
+ // Fallback to regular anchor tag
205
+ content = (
206
+ <a
207
+ {...buttonProps}
208
+ ref={ref as React.Ref<HTMLAnchorElement>}
209
+ href={href}
210
+ target={target}
211
+ rel={target === '_blank' ? 'noopener noreferrer' : undefined}
212
+ >
213
+ {buttonContent}
214
+ </a>
215
+ );
230
216
  }
231
-
232
- // Fallback to regular anchor tag
233
- const anchorElement = (
234
- <a {...anchorButtonProps} ref={ref as React.Ref<HTMLAnchorElement>} href={href} target={target} rel={target === '_blank' ? 'noopener noreferrer' : undefined}>
217
+ } else {
218
+ // Default button rendering
219
+ content = (
220
+ <Component
221
+ {...buttonProps}
222
+ ref={ref}
223
+ type={Component === 'button' ? type : undefined}
224
+ disabled={isDisabled}
225
+ >
235
226
  {buttonContent}
236
- </a>
227
+ </Component>
237
228
  );
238
-
239
- return glass ? <AtomixGlass {...glassProps}>{anchorElement}</AtomixGlass> : anchorElement;
240
229
  }
241
230
 
242
- // Default button rendering
243
- const buttonElement = (
244
- <Component {...buttonProps}>{buttonContent}</Component>
245
- );
231
+ if (glass) {
232
+ // Default glass props
233
+ const defaultGlassProps = {
234
+ displacementScale: 20,
235
+ blurAmount: 0,
236
+ saturation: 200,
237
+ elasticity: 0,
238
+ };
239
+ const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
240
+ return <AtomixGlass {...glassProps}>{content}</AtomixGlass>;
241
+ }
246
242
 
247
- return glass ? <AtomixGlass {...glassProps}>{buttonElement}</AtomixGlass> : buttonElement;
243
+ return content;
248
244
  }
249
245
  )
250
246
  );