@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.
- package/CHANGELOG.md +39 -0
- package/README.md +2 -0
- package/build-tools/EXAMPLES.md +372 -0
- package/build-tools/README.md +242 -0
- package/build-tools/__tests__/error-handler.test.js +230 -0
- package/build-tools/__tests__/index.test.js +141 -0
- package/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/build-tools/__tests__/utils.test.js +161 -0
- package/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/build-tools/error-handler.js +308 -0
- package/build-tools/index.d.ts +43 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +67 -0
- package/build-tools/rollup-plugin.js +236 -0
- package/build-tools/types.d.ts +163 -0
- package/build-tools/utils.js +203 -0
- package/build-tools/vite-plugin.js +161 -0
- package/build-tools/webpack-loader.js +123 -0
- package/dist/atomix.css +298 -167
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +3 -3
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/EXAMPLES.md +372 -0
- package/dist/build-tools/README.md +242 -0
- package/dist/build-tools/__tests__/error-handler.test.js +230 -0
- package/dist/build-tools/__tests__/index.test.js +141 -0
- package/dist/build-tools/__tests__/rollup-plugin.test.js +194 -0
- package/dist/build-tools/__tests__/utils.test.js +161 -0
- package/dist/build-tools/__tests__/vite-plugin.test.js +129 -0
- package/dist/build-tools/__tests__/webpack-loader.test.js +190 -0
- package/dist/build-tools/error-handler.js +308 -0
- package/dist/build-tools/index.d.ts +43 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +67 -0
- package/dist/build-tools/rollup-plugin.js +236 -0
- package/dist/build-tools/types.d.ts +163 -0
- package/dist/build-tools/utils.js +203 -0
- package/dist/build-tools/vite-plugin.js +161 -0
- package/dist/build-tools/webpack-loader.js +123 -0
- package/dist/charts.d.ts +2 -2
- package/dist/charts.js +87 -58
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +42 -12
- package/dist/core.js +175 -135
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +30 -16
- package/dist/forms.js +146 -131
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +2 -2
- package/dist/heavy.js +151 -118
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +130 -106
- package/dist/index.esm.js +1083 -465
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1102 -483
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/theme.d.ts +27 -2
- package/dist/theme.js +721 -108
- package/dist/theme.js.map +1 -1
- package/package.json +23 -8
- package/scripts/atomix-cli.js +749 -1153
- package/scripts/cli/__tests__/README.md +81 -0
- package/scripts/cli/__tests__/basic.test.js +115 -0
- package/scripts/cli/__tests__/component-generator.test.js +332 -0
- package/scripts/cli/__tests__/integration.test.js +327 -0
- package/scripts/cli/__tests__/test-setup.js +133 -0
- package/scripts/cli/__tests__/token-manager.test.js +251 -0
- package/scripts/cli/__tests__/utils.test.js +78 -118
- package/scripts/cli/component-generator.js +564 -0
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/documentation-sync.js +542 -0
- package/scripts/cli/interactive-init.js +129 -292
- package/scripts/cli/mappings.js +211 -0
- package/scripts/cli/migration-tools.js +95 -288
- package/scripts/cli/template-manager.js +105 -0
- package/scripts/cli/templates/README.md +123 -0
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +171 -0
- package/scripts/cli/templates/config-templates.js +126 -0
- package/scripts/cli/templates/index.js +102 -0
- package/scripts/cli/templates/project-templates.js +342 -0
- package/scripts/cli/templates/react-templates.js +331 -0
- package/scripts/cli/templates/scss-templates.js +155 -0
- package/scripts/cli/templates/storybook-templates.js +236 -0
- package/scripts/cli/templates/testing-templates.js +224 -0
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/token-templates.js +447 -0
- package/scripts/cli/templates/types-templates.js +147 -0
- package/scripts/cli/templates.js +35 -0
- package/scripts/cli/theme-bridge.js +28 -16
- package/scripts/cli/token-manager.js +432 -247
- package/scripts/cli/utils.js +37 -26
- package/src/components/Accordion/Accordion.stories.tsx +369 -870
- package/src/components/Accordion/Accordion.test.tsx +57 -0
- package/src/components/Accordion/Accordion.tsx +4 -0
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +2 -2
- package/src/components/AtomixGlass/shader-utils.ts +5 -0
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2965 -2861
- package/src/components/AtomixGlass/stories/Modes.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +348 -0
- package/src/components/AtomixGlass/stories/Performance.stories.tsx +103 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +73 -59
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +1 -1
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +239 -27
- package/src/components/Badge/Badge.stories.tsx +132 -373
- package/src/components/Badge/Badge.test.tsx +51 -0
- package/src/components/Badge/Badge.tsx +20 -1
- package/src/components/Block/Block.stories.tsx +26 -17
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +141 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +2 -2
- package/src/components/Button/Button.stories.tsx +463 -1126
- package/src/components/Button/Button.test.tsx +107 -0
- package/src/components/Button/Button.tsx +50 -54
- package/src/components/Button/ButtonGroup.stories.tsx +373 -217
- package/src/components/Button/README.md +5 -0
- package/src/components/Callout/Callout.stories.tsx +299 -644
- package/src/components/Callout/Callout.test.tsx +10 -10
- package/src/components/Callout/Callout.tsx +7 -7
- package/src/components/Callout/README.md +9 -8
- package/src/components/Card/Card.stories.tsx +248 -68
- package/src/components/Card/Card.tsx +2 -2
- package/src/components/Chart/Chart.stories.tsx +156 -14
- package/src/components/Chart/Chart.tsx +1 -1
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +151 -69
- package/src/components/Countdown/Countdown.stories.tsx +115 -8
- package/src/components/DataTable/DataTable.stories.tsx +346 -146
- package/src/components/DataTable/DataTable.tsx +14 -12
- package/src/components/DatePicker/DatePicker.stories.tsx +325 -1066
- package/src/components/Dropdown/Dropdown.stories.tsx +157 -37
- package/src/components/EdgePanel/EdgePanel.stories.tsx +230 -21
- package/src/components/Footer/Footer.stories.tsx +392 -328
- package/src/components/Form/Checkbox.stories.tsx +143 -9
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +90 -52
- package/src/components/Form/Form.stories.tsx +121 -22
- package/src/components/Form/FormGroup.stories.tsx +128 -5
- package/src/components/Form/Input.stories.tsx +28 -16
- package/src/components/Form/Input.test.tsx +59 -0
- package/src/components/Form/Input.tsx +97 -95
- package/src/components/Form/Radio.stories.tsx +232 -97
- package/src/components/Form/Radio.tsx +2 -2
- package/src/components/Form/Select.stories.tsx +144 -12
- package/src/components/Form/Select.tsx +2 -2
- package/src/components/Form/Textarea.stories.tsx +171 -13
- package/src/components/Form/Textarea.test.tsx +45 -0
- package/src/components/Form/Textarea.tsx +88 -86
- package/src/components/Hero/Hero.stories.tsx +333 -32
- package/src/components/List/List.stories.tsx +143 -5
- package/src/components/Modal/Modal.stories.tsx +185 -46
- package/src/components/Navigation/Navbar/Navbar.stories.tsx +5 -5
- package/src/components/Navigation/Navbar/Navbar.tsx +1 -1
- package/src/components/Navigation/README.md +1 -1
- package/src/components/Pagination/Pagination.stories.tsx +5 -2
- package/src/components/Pagination/Pagination.tsx +1 -1
- package/src/components/PhotoViewer/PhotoViewer.stories.tsx +10 -10
- package/src/components/Popover/Popover.stories.tsx +449 -99
- package/src/components/ProductReview/ProductReview.tsx +1 -1
- package/src/components/Progress/Progress.stories.tsx +167 -5
- package/src/components/Progress/Progress.tsx +46 -46
- package/src/components/Rating/Rating.stories.tsx +4 -4
- package/src/components/Rating/Rating.tsx +8 -8
- package/src/components/River/River.stories.tsx +1 -1
- package/src/components/SectionIntro/SectionIntro.stories.tsx +240 -48
- package/src/components/Slider/Slider.stories.tsx +63 -63
- package/src/components/Spinner/Spinner.stories.tsx +104 -10
- package/src/components/Spinner/Spinner.test.tsx +35 -0
- package/src/components/Spinner/Spinner.tsx +9 -2
- package/src/components/Steps/Steps.stories.tsx +172 -43
- package/src/components/Tabs/Tabs.stories.tsx +136 -10
- package/src/components/Testimonial/Testimonial.stories.tsx +121 -4
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +153 -43
- package/src/components/Toggle/Toggle.test.tsx +91 -0
- package/src/components/Toggle/Toggle.tsx +44 -27
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -104
- package/src/components/Tooltip/Tooltip.tsx +1 -1
- package/src/components/Upload/Upload.stories.tsx +113 -24
- package/src/layouts/Grid/Grid.stories.tsx +49 -49
- package/src/layouts/MasonryGrid/MasonryGrid.stories.tsx +2 -2
- package/src/lib/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +193 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/useAccordion.ts +12 -3
- package/src/lib/composables/useAtomixGlass.ts +28 -56
- package/src/lib/composables/useBreadcrumb.ts +2 -2
- package/src/lib/composables/useCallout.ts +7 -7
- package/src/lib/composables/useChartExport.ts +2 -7
- package/src/lib/composables/useDataTable.ts +46 -29
- package/src/lib/composables/useNavbar.ts +1 -1
- package/src/lib/constants/components.ts +10 -33
- package/src/lib/storybook/InteractiveDemo.tsx +113 -0
- package/src/lib/storybook/PreviewContainer.tsx +36 -0
- package/src/lib/storybook/VariantsGrid.tsx +21 -0
- package/src/lib/storybook/index.ts +3 -0
- package/src/lib/theme/core/createThemeObject.ts +9 -5
- package/src/lib/theme/devtools/CLI.ts +155 -0
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +213 -0
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +566 -0
- package/src/lib/theme/devtools/LiveEditor.tsx +2 -1
- package/src/lib/theme/devtools/index.ts +3 -0
- package/src/lib/theme/errors/errors.ts +8 -0
- package/src/lib/theme/runtime/ThemeProvider.tsx +117 -57
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +305 -0
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +588 -0
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +264 -0
- package/src/lib/theme/utils/index.ts +1 -0
- package/src/lib/theme/utils/themeValidation.ts +501 -0
- package/src/lib/theme-tools.ts +32 -3
- package/src/lib/types/components.ts +82 -27
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/csv.ts +17 -0
- package/src/lib/utils/dataTableExport.ts +1 -10
- package/src/lib/utils/themeNaming.ts +1 -1
- package/src/styles/01-settings/_index.scss +2 -1
- package/src/styles/01-settings/_settings.accordion.scss +28 -7
- package/src/styles/01-settings/_settings.colors.scss +11 -11
- package/src/styles/01-settings/_settings.typography.scss +5 -5
- package/src/styles/02-tools/_tools.utility-api.scss +14 -0
- package/src/styles/06-components/_components.accordion.scss +56 -14
- package/src/styles/06-components/_components.callout.scss +29 -33
- package/src/styles/06-components/_components.checkbox.scss +23 -17
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/99-utilities/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.display.scss +14 -3
- package/src/styles/99-utilities/_utilities.flex.scss +10 -10
- package/src/styles/99-utilities/_utilities.scss +3 -1
- package/src/styles/99-utilities/_utilities.text-gradient.scss +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +28 -8
- package/themes/dark-complementary/README.md +98 -0
- package/themes/dark-complementary/index.scss +158 -0
- package/themes/default-light/README.md +81 -0
- package/themes/default-light/index.scss +154 -0
- package/themes/high-contrast/README.md +105 -0
- package/themes/high-contrast/index.scss +172 -0
- package/themes/test-theme/README.md +38 -0
- package/themes/test-theme/index.scss +47 -0
- package/scripts/cli/__tests__/cli-commands.test.js +0 -204
- package/scripts/cli/__tests__/vitest.config.js +0 -26
- package/src/components/AtomixGlass/stories/AtomixGlass.stories.tsx +0 -1438
- package/src/lib/composables/useButton.ts +0 -93
- 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':
|
|
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
|
-
|
|
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
|
-
...
|
|
217
|
-
ref: ref as
|
|
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
|
-
|
|
198
|
+
content = (
|
|
224
199
|
<LinkComp {...linkProps}>
|
|
225
200
|
{buttonContent}
|
|
226
201
|
</LinkComp>
|
|
227
202
|
);
|
|
228
|
-
|
|
229
|
-
|
|
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
|
-
//
|
|
233
|
-
|
|
234
|
-
<
|
|
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
|
-
</
|
|
227
|
+
</Component>
|
|
237
228
|
);
|
|
238
|
-
|
|
239
|
-
return glass ? <AtomixGlass {...glassProps}>{anchorElement}</AtomixGlass> : anchorElement;
|
|
240
229
|
}
|
|
241
230
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
|
|
243
|
+
return content;
|
|
248
244
|
}
|
|
249
245
|
)
|
|
250
246
|
);
|