@shohojdhara/atomix 0.2.1 → 0.2.3
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/README.md +1 -28
- package/dist/atomix.css +1500 -241
- package/dist/atomix.min.css +6 -6
- package/dist/index.d.ts +1052 -194
- package/dist/index.esm.js +12201 -6066
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +5481 -2827
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/themes/boomdevs.css +1500 -301
- package/dist/themes/boomdevs.min.css +60 -8
- package/dist/themes/esrar.css +1500 -241
- package/dist/themes/esrar.min.css +6 -6
- package/dist/themes/mashroom.css +1496 -237
- package/dist/themes/mashroom.min.css +8 -8
- package/dist/themes/shaj-default.css +1451 -192
- package/dist/themes/shaj-default.min.css +6 -6
- package/package.json +66 -15
- package/src/components/Accordion/Accordion.stories.tsx +137 -0
- package/src/components/Accordion/Accordion.tsx +33 -3
- package/src/components/AtomixGlass/AtomixGlass.stories.tsx +3011 -0
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +199 -0
- package/src/components/AtomixGlass/AtomixGlass.tsx +1281 -0
- package/src/components/AtomixGlass/AtomixGlassComprehensivePreview.stories.tsx +1369 -0
- package/src/components/AtomixGlass/README.md +134 -0
- package/src/components/AtomixGlass/index.ts +10 -0
- package/src/components/AtomixGlass/shader-utils.ts +140 -0
- package/src/components/AtomixGlass/utils.ts +8 -0
- package/src/components/Badge/Badge.stories.tsx +169 -0
- package/src/components/Badge/Badge.tsx +27 -2
- package/src/components/Button/Button.stories.tsx +345 -0
- package/src/components/Button/Button.tsx +35 -3
- package/src/components/Button/README.md +216 -0
- package/src/components/Callout/Callout.stories.tsx +813 -78
- package/src/components/Callout/Callout.test.tsx +368 -0
- package/src/components/Callout/Callout.tsx +26 -7
- package/src/components/Callout/README.md +409 -0
- package/src/components/Card/Card.stories.tsx +140 -0
- package/src/components/Card/Card.tsx +19 -3
- package/src/components/DatePicker/DatePicker copy.tsx +551 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +188 -0
- package/src/components/DatePicker/DatePicker.tsx +379 -332
- package/src/components/DatePicker/readme.md +110 -1
- package/src/components/DatePicker/types.ts +8 -0
- package/src/components/Dropdown/Dropdown.stories.tsx +145 -0
- package/src/components/Dropdown/Dropdown.tsx +34 -5
- package/src/components/Footer/Footer.stories.tsx +388 -0
- package/src/components/Footer/Footer.tsx +197 -0
- package/src/components/Footer/FooterLink.tsx +72 -0
- package/src/components/Footer/FooterSection.tsx +87 -0
- package/src/components/Footer/FooterSocialLink.tsx +117 -0
- package/src/components/Footer/README.md +261 -0
- package/src/components/Footer/index.ts +13 -0
- package/src/components/Form/Checkbox.stories.tsx +101 -0
- package/src/components/Form/Checkbox.tsx +26 -2
- package/src/components/Form/Input.stories.tsx +124 -0
- package/src/components/Form/Input.tsx +36 -7
- package/src/components/Form/Radio.stories.tsx +139 -0
- package/src/components/Form/Radio.tsx +26 -2
- package/src/components/Form/Select.stories.tsx +110 -0
- package/src/components/Form/Select.tsx +26 -2
- package/src/components/Form/Textarea.stories.tsx +104 -0
- package/src/components/Form/Textarea.tsx +36 -7
- package/src/components/Hero/Hero.stories.tsx +54 -1
- package/src/components/Hero/Hero.tsx +70 -11
- package/src/components/Modal/Modal.stories.tsx +235 -0
- package/src/components/Modal/Modal.tsx +64 -35
- package/src/components/Pagination/Pagination.stories.tsx +101 -0
- package/src/components/Pagination/Pagination.tsx +25 -1
- package/src/components/Popover/Popover.stories.tsx +94 -0
- package/src/components/Popover/Popover.tsx +30 -4
- package/src/components/Rating/Rating.stories.tsx +112 -0
- package/src/components/Rating/Rating.tsx +25 -1
- package/src/components/SectionIntro/SectionIntro.tsx +9 -11
- package/src/components/Slider/Slider.stories.tsx +634 -50
- package/src/components/Slider/Slider.tsx +5 -3
- package/src/components/Steps/Steps.stories.tsx +119 -0
- package/src/components/Steps/Steps.tsx +32 -1
- package/src/components/Tab/Tab.stories.tsx +88 -0
- package/src/components/Tab/Tab.tsx +32 -1
- package/src/components/Toggle/Toggle.stories.tsx +92 -0
- package/src/components/Toggle/Toggle.tsx +32 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +131 -0
- package/src/components/Tooltip/Tooltip.tsx +43 -7
- package/src/components/VideoPlayer/VideoPlayer.stories.tsx +1002 -196
- package/src/components/VideoPlayer/VideoPlayer.tsx +161 -4
- package/src/components/index.ts +14 -0
- package/src/layouts/Grid/Grid.stories.tsx +226 -159
- package/src/lib/composables/index.ts +4 -0
- package/src/lib/composables/useAtomixGlass.ts +71 -0
- package/src/lib/composables/useButton.ts +3 -1
- package/src/lib/composables/useCallout.ts +4 -1
- package/src/lib/composables/useFooter.ts +85 -0
- package/src/lib/composables/useGlassContainer.ts +168 -0
- package/src/lib/composables/useSlider.ts +191 -4
- package/src/lib/constants/components.ts +173 -0
- package/src/lib/types/components.ts +622 -0
- package/src/lib/utils/displacement-generator.ts +86 -0
- package/src/styles/01-settings/_index.scss +1 -0
- package/src/styles/01-settings/_settings.accordion.scss +20 -19
- package/src/styles/01-settings/_settings.animations.scss +5 -5
- package/src/styles/01-settings/_settings.avatar-group.scss +1 -1
- package/src/styles/01-settings/_settings.avatar.scss +17 -18
- package/src/styles/01-settings/_settings.background.scss +10 -0
- package/src/styles/01-settings/_settings.badge.scss +1 -1
- package/src/styles/01-settings/_settings.breadcrumb.scss +8 -2
- package/src/styles/01-settings/_settings.callout.scss +7 -7
- package/src/styles/01-settings/_settings.card.scss +2 -2
- package/src/styles/01-settings/_settings.chart.scss +7 -7
- package/src/styles/01-settings/_settings.checkbox-group.scss +5 -2
- package/src/styles/01-settings/_settings.checkbox.scss +10 -4
- package/src/styles/01-settings/_settings.countdown.scss +6 -4
- package/src/styles/01-settings/_settings.dropdown.scss +9 -7
- package/src/styles/01-settings/_settings.edge-panel.scss +3 -2
- package/src/styles/01-settings/_settings.footer.scss +125 -0
- package/src/styles/01-settings/_settings.form-group.scss +3 -1
- package/src/styles/01-settings/_settings.form.scss +4 -2
- package/src/styles/01-settings/_settings.hero.scss +9 -7
- package/src/styles/01-settings/_settings.input.scss +9 -7
- package/src/styles/01-settings/_settings.list-group.scss +4 -2
- package/src/styles/01-settings/_settings.list.scss +4 -2
- package/src/styles/01-settings/_settings.menu.scss +10 -8
- package/src/styles/01-settings/_settings.messages.scss +19 -17
- package/src/styles/01-settings/_settings.modal.scss +6 -4
- package/src/styles/01-settings/_settings.nav.scss +6 -4
- package/src/styles/01-settings/_settings.navbar.scss +8 -5
- package/src/styles/01-settings/_settings.pagination.scss +5 -3
- package/src/styles/01-settings/_settings.popover.scss +6 -4
- package/src/styles/01-settings/_settings.rating.scss +5 -3
- package/src/styles/01-settings/_settings.river.scss +8 -6
- package/src/styles/01-settings/_settings.sectionintro.scss +8 -6
- package/src/styles/01-settings/_settings.select.scss +7 -5
- package/src/styles/01-settings/_settings.side-menu.scss +15 -13
- package/src/styles/01-settings/_settings.spacing.scss +4 -0
- package/src/styles/01-settings/_settings.steps.scss +7 -5
- package/src/styles/01-settings/_settings.tabs.scss +7 -5
- package/src/styles/01-settings/_settings.testimonials.scss +6 -4
- package/src/styles/01-settings/_settings.toggle.scss +3 -1
- package/src/styles/01-settings/_settings.tooltip.scss +5 -3
- package/src/styles/01-settings/_settings.upload.scss +22 -20
- package/src/styles/02-tools/_tools.animations.scss +19 -0
- package/src/styles/02-tools/_tools.background.scss +87 -0
- package/src/styles/02-tools/_tools.glass.scss +1 -0
- package/src/styles/02-tools/_tools.rem.scss +18 -5
- package/src/styles/02-tools/_tools.utility-api.scss +32 -26
- package/src/styles/03-generic/_generic.root.scss +15 -2
- package/src/styles/04-elements/_elements.body.scss +6 -0
- package/src/styles/06-components/_components.accordion.scss +24 -4
- package/src/styles/06-components/_components.atomix-glass.scss +0 -0
- package/src/styles/06-components/_components.avatar-group.scss +2 -1
- package/src/styles/06-components/_components.avatar.scss +2 -1
- package/src/styles/06-components/_components.badge.scss +36 -1
- package/src/styles/06-components/_components.breadcrumb.scss +2 -1
- package/src/styles/06-components/_components.button.scss +14 -3
- package/src/styles/06-components/_components.callout.scss +44 -4
- package/src/styles/06-components/_components.card.scss +21 -2
- package/src/styles/06-components/_components.chart.scss +3 -2
- package/src/styles/06-components/_components.checkbox.scss +2 -1
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -2
- package/src/styles/06-components/_components.countdown.scss +2 -1
- package/src/styles/06-components/_components.data-table.scss +7 -6
- package/src/styles/06-components/_components.datepicker.scss +20 -1
- package/src/styles/06-components/_components.dropdown.scss +11 -4
- package/src/styles/06-components/_components.edge-panel.scss +4 -3
- package/src/styles/06-components/_components.footer.scss +825 -0
- package/src/styles/06-components/_components.form-group.scss +1 -0
- package/src/styles/06-components/_components.hero.scss +4 -4
- package/src/styles/06-components/_components.image-gallery.scss +1 -0
- package/src/styles/06-components/_components.input.scss +33 -2
- package/src/styles/06-components/_components.list-group.scss +3 -2
- package/src/styles/06-components/_components.list.scss +2 -1
- package/src/styles/06-components/_components.menu.scss +5 -4
- package/src/styles/06-components/_components.messages.scss +8 -7
- package/src/styles/06-components/_components.modal.scss +3 -2
- package/src/styles/06-components/_components.nav.scss +6 -5
- package/src/styles/06-components/_components.navbar.scss +4 -3
- package/src/styles/06-components/_components.pagination.scss +2 -1
- package/src/styles/06-components/_components.photoviewer.scss +4 -3
- package/src/styles/06-components/_components.popover.scss +3 -2
- package/src/styles/06-components/_components.product-review.scss +3 -2
- package/src/styles/06-components/_components.progress.scss +3 -2
- package/src/styles/06-components/_components.river.scss +3 -2
- package/src/styles/06-components/_components.sectionintro.scss +2 -1
- package/src/styles/06-components/_components.select.scss +5 -4
- package/src/styles/06-components/_components.side-menu.scss +8 -7
- package/src/styles/06-components/_components.skeleton.scss +3 -2
- package/src/styles/06-components/_components.slider.scss +7 -6
- package/src/styles/06-components/_components.spinner.scss +1 -0
- package/src/styles/06-components/_components.steps.scss +3 -2
- package/src/styles/06-components/_components.tabs.scss +4 -3
- package/src/styles/06-components/_components.testimonials.scss +2 -1
- package/src/styles/06-components/_components.todo.scss +3 -2
- package/src/styles/06-components/_components.toggle.scss +5 -4
- package/src/styles/06-components/_components.tooltip.scss +3 -2
- package/src/styles/06-components/_components.upload.scss +4 -3
- package/src/styles/06-components/_components.video-player.scss +50 -27
- package/src/styles/06-components/_index.scss +2 -0
- package/src/styles/99-utilities/_utilities.glass-fixes.scss +48 -0
- package/dist/themes/yabai.css +0 -13711
- package/dist/themes/yabai.min.css +0 -189
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
import { Callout } from './Callout';
|
|
4
|
+
|
|
5
|
+
// Mock AtomixGlass component since it has complex WebGL dependencies
|
|
6
|
+
vi.mock('../AtomixGlass/AtomixGlass', () => ({
|
|
7
|
+
AtomixGlass: ({ children, ...props }: any) => (
|
|
8
|
+
<div data-testid="atomix-glass" data-glass-props={JSON.stringify(props)}>
|
|
9
|
+
{children}
|
|
10
|
+
</div>
|
|
11
|
+
),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
describe('Callout Component', () => {
|
|
15
|
+
describe('Basic functionality', () => {
|
|
16
|
+
it('renders with title and content', () => {
|
|
17
|
+
render(
|
|
18
|
+
<Callout title="Test Title" variant="primary">
|
|
19
|
+
Test content
|
|
20
|
+
</Callout>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
expect(screen.getByText('Test Title')).toBeInTheDocument();
|
|
24
|
+
expect(screen.getByText('Test content')).toBeInTheDocument();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('renders with icon', () => {
|
|
28
|
+
const TestIcon = () => <div data-testid="test-icon">Icon</div>;
|
|
29
|
+
|
|
30
|
+
render(
|
|
31
|
+
<Callout title="Test" variant="primary" icon={<TestIcon />}>
|
|
32
|
+
Content
|
|
33
|
+
</Callout>
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
expect(screen.getByTestId('test-icon')).toBeInTheDocument();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('applies correct variant class', () => {
|
|
40
|
+
const { container } = render(
|
|
41
|
+
<Callout title="Test" variant="success">
|
|
42
|
+
Content
|
|
43
|
+
</Callout>
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
expect(container.firstChild).toHaveClass('c-callout--success');
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('applies oneLine class when enabled', () => {
|
|
50
|
+
const { container } = render(
|
|
51
|
+
<Callout title="Test" variant="primary" oneLine>
|
|
52
|
+
Content
|
|
53
|
+
</Callout>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(container.firstChild).toHaveClass('c-callout--oneline');
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('applies toast class when enabled', () => {
|
|
60
|
+
const { container } = render(
|
|
61
|
+
<Callout title="Test" variant="primary" toast>
|
|
62
|
+
Content
|
|
63
|
+
</Callout>
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
expect(container.firstChild).toHaveClass('c-callout--toast');
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('renders close button when onClose is provided', () => {
|
|
70
|
+
const handleClose = vi.fn();
|
|
71
|
+
|
|
72
|
+
render(
|
|
73
|
+
<Callout title="Test" variant="primary" onClose={handleClose}>
|
|
74
|
+
Content
|
|
75
|
+
</Callout>
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const closeButton = screen.getByRole('button', { name: 'Close' });
|
|
79
|
+
expect(closeButton).toBeInTheDocument();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it('calls onClose when close button is clicked', () => {
|
|
83
|
+
const handleClose = vi.fn();
|
|
84
|
+
|
|
85
|
+
render(
|
|
86
|
+
<Callout title="Test" variant="primary" onClose={handleClose}>
|
|
87
|
+
Content
|
|
88
|
+
</Callout>
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const closeButton = screen.getByRole('button', { name: 'Close' });
|
|
92
|
+
fireEvent.click(closeButton);
|
|
93
|
+
|
|
94
|
+
expect(handleClose).toHaveBeenCalledTimes(1);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('renders action buttons', () => {
|
|
98
|
+
const actions = <button data-testid="action-button">Action</button>;
|
|
99
|
+
|
|
100
|
+
render(
|
|
101
|
+
<Callout title="Test" variant="primary" actions={actions}>
|
|
102
|
+
Content
|
|
103
|
+
</Callout>
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
expect(screen.getByTestId('action-button')).toBeInTheDocument();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe('Glass functionality', () => {
|
|
111
|
+
it('does not render AtomixGlass when glass is false', () => {
|
|
112
|
+
render(
|
|
113
|
+
<Callout title="Test" variant="primary" glass={false}>
|
|
114
|
+
Content
|
|
115
|
+
</Callout>
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
expect(screen.queryByTestId('atomix-glass')).not.toBeInTheDocument();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('renders AtomixGlass when glass is true', () => {
|
|
122
|
+
render(
|
|
123
|
+
<Callout title="Test" variant="primary" glass={true}>
|
|
124
|
+
Content
|
|
125
|
+
</Callout>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
expect(screen.getByTestId('atomix-glass')).toBeInTheDocument();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('applies glass class when glass is enabled', () => {
|
|
132
|
+
const { container } = render(
|
|
133
|
+
<Callout title="Test" variant="primary" glass={true}>
|
|
134
|
+
Content
|
|
135
|
+
</Callout>
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
// The glass class should be applied to the inner callout element
|
|
139
|
+
const calloutElement = container.querySelector('.c-callout');
|
|
140
|
+
expect(calloutElement).toHaveClass('c-callout--glass');
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('uses default glass settings when glass is true', () => {
|
|
144
|
+
render(
|
|
145
|
+
<Callout title="Test" variant="primary" glass={true}>
|
|
146
|
+
Content
|
|
147
|
+
</Callout>
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const glassElement = screen.getByTestId('atomix-glass');
|
|
151
|
+
const glassProps = JSON.parse(glassElement.getAttribute('data-glass-props') || '{}');
|
|
152
|
+
|
|
153
|
+
expect(glassProps).toMatchObject({
|
|
154
|
+
displacementScale: 40,
|
|
155
|
+
blurAmount: 0,
|
|
156
|
+
saturation: 160,
|
|
157
|
+
aberrationIntensity: 1,
|
|
158
|
+
cornerRadius: 8,
|
|
159
|
+
overLight: false,
|
|
160
|
+
mode: 'standard',
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it('uses custom glass settings when glass is an object', () => {
|
|
165
|
+
const customGlass = {
|
|
166
|
+
displacementScale: 60,
|
|
167
|
+
blurAmount: 2,
|
|
168
|
+
saturation: 180,
|
|
169
|
+
cornerRadius: 12,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
render(
|
|
173
|
+
<Callout title="Test" variant="primary" glass={customGlass}>
|
|
174
|
+
Content
|
|
175
|
+
</Callout>
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
const glassElement = screen.getByTestId('atomix-glass');
|
|
179
|
+
const glassProps = JSON.parse(glassElement.getAttribute('data-glass-props') || '{}');
|
|
180
|
+
|
|
181
|
+
expect(glassProps).toMatchObject({
|
|
182
|
+
// Custom values
|
|
183
|
+
displacementScale: 60,
|
|
184
|
+
blurAmount: 2,
|
|
185
|
+
saturation: 180,
|
|
186
|
+
cornerRadius: 12,
|
|
187
|
+
// Default values that weren't overridden
|
|
188
|
+
aberrationIntensity: 1,
|
|
189
|
+
overLight: false,
|
|
190
|
+
mode: 'standard',
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('maintains all functionality with glass enabled', () => {
|
|
195
|
+
const handleClose = vi.fn();
|
|
196
|
+
const TestIcon = () => <div data-testid="test-icon">Icon</div>;
|
|
197
|
+
const actions = <button data-testid="action-button">Action</button>;
|
|
198
|
+
|
|
199
|
+
render(
|
|
200
|
+
<Callout
|
|
201
|
+
title="Glass Test"
|
|
202
|
+
variant="success"
|
|
203
|
+
icon={<TestIcon />}
|
|
204
|
+
glass={true}
|
|
205
|
+
onClose={handleClose}
|
|
206
|
+
actions={actions}
|
|
207
|
+
oneLine
|
|
208
|
+
toast
|
|
209
|
+
>
|
|
210
|
+
Glass content
|
|
211
|
+
</Callout>
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Check that all functionality is preserved
|
|
215
|
+
expect(screen.getByText('Glass Test')).toBeInTheDocument();
|
|
216
|
+
expect(screen.getByText('Glass content')).toBeInTheDocument();
|
|
217
|
+
expect(screen.getByTestId('test-icon')).toBeInTheDocument();
|
|
218
|
+
expect(screen.getByTestId('action-button')).toBeInTheDocument();
|
|
219
|
+
|
|
220
|
+
const closeButton = screen.getByRole('button', { name: 'Close' });
|
|
221
|
+
expect(closeButton).toBeInTheDocument();
|
|
222
|
+
|
|
223
|
+
// Check that glass wrapper is present
|
|
224
|
+
expect(screen.getByTestId('atomix-glass')).toBeInTheDocument();
|
|
225
|
+
|
|
226
|
+
// Check that all classes are applied
|
|
227
|
+
const calloutElement = screen.getByTestId('atomix-glass').firstChild;
|
|
228
|
+
expect(calloutElement).toHaveClass(
|
|
229
|
+
'c-callout',
|
|
230
|
+
'c-callout--success',
|
|
231
|
+
'c-callout--oneline',
|
|
232
|
+
'c-callout--toast',
|
|
233
|
+
'c-callout--glass'
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// Test close functionality
|
|
237
|
+
fireEvent.click(closeButton);
|
|
238
|
+
expect(handleClose).toHaveBeenCalledTimes(1);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
describe('Accessibility', () => {
|
|
243
|
+
it('applies correct ARIA role for different variants', () => {
|
|
244
|
+
// Test alert role for error
|
|
245
|
+
const { rerender } = render(
|
|
246
|
+
<Callout title="Error" variant="error">
|
|
247
|
+
Error message
|
|
248
|
+
</Callout>
|
|
249
|
+
);
|
|
250
|
+
expect(screen.getByRole('alert')).toBeInTheDocument();
|
|
251
|
+
|
|
252
|
+
// Test alert role for warning
|
|
253
|
+
rerender(
|
|
254
|
+
<Callout title="Warning" variant="warning">
|
|
255
|
+
Warning message
|
|
256
|
+
</Callout>
|
|
257
|
+
);
|
|
258
|
+
expect(screen.getByRole('alert')).toBeInTheDocument();
|
|
259
|
+
|
|
260
|
+
// Test status role for info
|
|
261
|
+
rerender(
|
|
262
|
+
<Callout title="Info" variant="info">
|
|
263
|
+
Info message
|
|
264
|
+
</Callout>
|
|
265
|
+
);
|
|
266
|
+
expect(screen.getByRole('status')).toBeInTheDocument();
|
|
267
|
+
|
|
268
|
+
// Test status role for success
|
|
269
|
+
rerender(
|
|
270
|
+
<Callout title="Success" variant="success">
|
|
271
|
+
Success message
|
|
272
|
+
</Callout>
|
|
273
|
+
);
|
|
274
|
+
expect(screen.getByRole('status')).toBeInTheDocument();
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('applies alert role and assertive live region for toast alerts', () => {
|
|
278
|
+
render(
|
|
279
|
+
<Callout title="Toast Error" variant="error" toast>
|
|
280
|
+
Toast error message
|
|
281
|
+
</Callout>
|
|
282
|
+
);
|
|
283
|
+
|
|
284
|
+
const callout = screen.getByRole('alert');
|
|
285
|
+
expect(callout).toHaveAttribute('aria-live', 'polite');
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('applies polite live region for toast notifications', () => {
|
|
289
|
+
render(
|
|
290
|
+
<Callout title="Toast Info" variant="info" toast>
|
|
291
|
+
Toast info message
|
|
292
|
+
</Callout>
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
const callout = screen.getByRole('alert');
|
|
296
|
+
expect(callout).toHaveAttribute('aria-live', 'polite');
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('maintains accessibility with glass effect', () => {
|
|
300
|
+
render(
|
|
301
|
+
<Callout title="Glass Error" variant="error" glass={true} toast>
|
|
302
|
+
Glass error message
|
|
303
|
+
</Callout>
|
|
304
|
+
);
|
|
305
|
+
|
|
306
|
+
// Should still have proper ARIA attributes
|
|
307
|
+
const callout = screen.getByRole('alert');
|
|
308
|
+
expect(callout).toHaveAttribute('aria-live', 'polite');
|
|
309
|
+
|
|
310
|
+
// Should be wrapped in glass but maintain accessibility
|
|
311
|
+
expect(screen.getByTestId('atomix-glass')).toBeInTheDocument();
|
|
312
|
+
});
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
describe('Custom className', () => {
|
|
316
|
+
it('applies custom className', () => {
|
|
317
|
+
const { container } = render(
|
|
318
|
+
<Callout title="Test" variant="primary" className="custom-class">
|
|
319
|
+
Content
|
|
320
|
+
</Callout>
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
expect(container.firstChild).toHaveClass('custom-class');
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it('applies custom className with glass effect', () => {
|
|
327
|
+
const { container } = render(
|
|
328
|
+
<Callout title="Test" variant="primary" glass={true} className="custom-glass">
|
|
329
|
+
Content
|
|
330
|
+
</Callout>
|
|
331
|
+
);
|
|
332
|
+
|
|
333
|
+
const calloutElement = container.querySelector('.c-callout');
|
|
334
|
+
expect(calloutElement).toHaveClass('custom-glass');
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
describe('Content flexibility', () => {
|
|
339
|
+
it('renders without title', () => {
|
|
340
|
+
render(<Callout variant="primary">Content only</Callout>);
|
|
341
|
+
|
|
342
|
+
expect(screen.getByText('Content only')).toBeInTheDocument();
|
|
343
|
+
expect(screen.queryByRole('heading')).not.toBeInTheDocument();
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
it('renders with complex content', () => {
|
|
347
|
+
const complexContent = (
|
|
348
|
+
<div>
|
|
349
|
+
<p>Paragraph content</p>
|
|
350
|
+
<ul>
|
|
351
|
+
<li>List item 1</li>
|
|
352
|
+
<li>List item 2</li>
|
|
353
|
+
</ul>
|
|
354
|
+
</div>
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
render(
|
|
358
|
+
<Callout title="Complex" variant="primary" glass={true}>
|
|
359
|
+
{complexContent}
|
|
360
|
+
</Callout>
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
expect(screen.getByText('Paragraph content')).toBeInTheDocument();
|
|
364
|
+
expect(screen.getByText('List item 1')).toBeInTheDocument();
|
|
365
|
+
expect(screen.getByText('List item 2')).toBeInTheDocument();
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
});
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import { CalloutProps } from '../../lib/types/components';
|
|
3
3
|
import { useCallout } from '../../lib/composables/useCallout';
|
|
4
4
|
import { Icon } from '../Icon/Icon';
|
|
5
|
+
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Callout component for displaying important messages, notifications, or alerts
|
|
@@ -15,6 +16,7 @@ export const Callout: React.FC<CalloutProps> = ({
|
|
|
15
16
|
actions,
|
|
16
17
|
oneLine = false,
|
|
17
18
|
toast = false,
|
|
19
|
+
glass,
|
|
18
20
|
className,
|
|
19
21
|
...props
|
|
20
22
|
}) => {
|
|
@@ -22,6 +24,7 @@ export const Callout: React.FC<CalloutProps> = ({
|
|
|
22
24
|
variant,
|
|
23
25
|
oneLine,
|
|
24
26
|
toast,
|
|
27
|
+
glass,
|
|
25
28
|
className,
|
|
26
29
|
});
|
|
27
30
|
|
|
@@ -46,12 +49,8 @@ export const Callout: React.FC<CalloutProps> = ({
|
|
|
46
49
|
return baseAttributes;
|
|
47
50
|
};
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
className={generateCalloutClass({ variant, oneLine, toast, className })}
|
|
52
|
-
{...getAriaAttributes()}
|
|
53
|
-
{...props}
|
|
54
|
-
>
|
|
52
|
+
const calloutContent = (
|
|
53
|
+
<>
|
|
55
54
|
<div className="c-callout__content">
|
|
56
55
|
{icon && <div className="c-callout__icon">{icon}</div>}
|
|
57
56
|
<div className="c-callout__message">
|
|
@@ -67,8 +66,28 @@ export const Callout: React.FC<CalloutProps> = ({
|
|
|
67
66
|
<Icon name="X" size="md" />
|
|
68
67
|
</button>
|
|
69
68
|
)}
|
|
70
|
-
|
|
69
|
+
</>
|
|
71
70
|
);
|
|
71
|
+
|
|
72
|
+
if (glass) {
|
|
73
|
+
// Default glass settings for callouts
|
|
74
|
+
const defaultGlassProps = {
|
|
75
|
+
displacementScale: 20,
|
|
76
|
+
blurAmount: 2,
|
|
77
|
+
saturation: 70,
|
|
78
|
+
aberrationIntensity: 1,
|
|
79
|
+
cornerRadius: 8,
|
|
80
|
+
overLight: false,
|
|
81
|
+
elasticity: 0,
|
|
82
|
+
mode: 'shader' as const,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
86
|
+
|
|
87
|
+
return <div className={generateCalloutClass({ variant, oneLine, toast, glass, className })} {...getAriaAttributes()} {...props}><AtomixGlass {...glassProps}><div className="c-callout__glass-content">{calloutContent}</div></AtomixGlass></div>;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return <div className={generateCalloutClass({ variant, oneLine, toast, glass, className })} {...getAriaAttributes()} {...props}>{calloutContent}</div>;
|
|
72
91
|
};
|
|
73
92
|
|
|
74
93
|
Callout.displayName = 'Callout';
|