@shohojdhara/atomix 0.3.15 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-tools/index.d.ts +31 -30
- package/build-tools/package.json +4 -21
- package/dist/atomix.css +20234 -2027
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +76 -2
- package/dist/atomix.min.css.map +1 -1
- package/dist/build-tools/index.d.ts +31 -30
- package/dist/build-tools/package.json +4 -21
- package/dist/charts.js +4 -5
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +87 -10
- package/dist/core.js +673 -480
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +15 -3
- package/dist/forms.js +530 -97
- package/dist/forms.js.map +1 -1
- package/dist/heavy.js +5 -6
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +644 -277
- package/dist/index.esm.js +1948 -1347
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +3333 -2728
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/layout.js.map +1 -1
- package/dist/theme.d.ts +9 -9
- package/dist/theme.js.map +1 -1
- package/package.json +2 -2
- package/scripts/atomix-cli.js +10 -1
- package/scripts/cli/__tests__/utils.test.js +6 -2
- package/scripts/cli/migration-tools.js +2 -2
- package/scripts/cli/theme-bridge.js +7 -9
- package/scripts/cli/utils.js +2 -1
- package/src/components/Accordion/Accordion.stories.tsx +72 -23
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +219 -96
- package/src/components/Accordion/AccordionCompound.test.tsx +70 -0
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/glass-utils.ts +4 -3
- package/src/components/AtomixGlass/shader-utils.ts +128 -52
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +1 -1
- package/src/components/AtomixGlass/stories/Shaders.stories.tsx +1 -1
- package/src/components/Avatar/Avatar.stories.tsx +45 -62
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +20 -9
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +14 -4
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +9 -8
- package/src/components/Breadcrumb/Breadcrumb.tsx +173 -65
- package/src/components/Breadcrumb/BreadcrumbCompound.test.tsx +84 -0
- package/src/components/Button/Button.stories.tsx +13 -22
- package/src/components/Button/Button.test.tsx +97 -81
- package/src/components/Button/Button.tsx +46 -14
- package/src/components/Button/ButtonGroup.stories.tsx +37 -32
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +166 -918
- package/src/components/Callout/Callout.tsx +196 -84
- package/src/components/Callout/CalloutCompound.test.tsx +72 -0
- package/src/components/Card/Card.stories.tsx +67 -36
- package/src/components/Card/Card.tsx +30 -14
- package/src/components/Chart/AreaChart.tsx +1 -1
- package/src/components/Chart/CandlestickChart.tsx +23 -16
- package/src/components/Chart/Chart.stories.tsx +4 -9
- package/src/components/Chart/Chart.tsx +40 -44
- package/src/components/Chart/ChartRenderer.tsx +39 -12
- package/src/components/Chart/ChartToolbar.tsx +21 -5
- package/src/components/Chart/DonutChart.tsx +1 -1
- package/src/components/Chart/FunnelChart.tsx +4 -1
- package/src/components/Chart/GaugeChart.tsx +3 -1
- package/src/components/Chart/HeatmapChart.tsx +50 -37
- package/src/components/Chart/LineChart.tsx +3 -2
- package/src/components/Chart/MultiAxisChart.tsx +24 -16
- package/src/components/Chart/RadarChart.tsx +19 -17
- package/src/components/Chart/ScatterChart.tsx +29 -21
- package/src/components/ColorModeToggle/ColorModeToggle.stories.tsx +6 -2
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +7 -7
- package/src/components/DataTable/DataTable.stories.tsx +43 -38
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +32 -47
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +2 -5
- package/src/components/Dropdown/Dropdown.tsx +425 -298
- package/src/components/Dropdown/DropdownCompound.test.tsx +64 -0
- package/src/components/EdgePanel/EdgePanel.stories.tsx +6 -19
- package/src/components/EdgePanel/EdgePanel.tsx +163 -113
- package/src/components/EdgePanel/EdgePanelCompound.test.tsx +53 -0
- package/src/components/Footer/Footer.stories.tsx +21 -16
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.test.tsx +49 -49
- package/src/components/Form/Checkbox.tsx +108 -100
- package/src/components/Form/Form.stories.tsx +2 -10
- package/src/components/Form/Input.stories.tsx +22 -39
- package/src/components/Form/Input.test.tsx +38 -44
- package/src/components/Form/Radio.stories.tsx +6 -12
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +23 -0
- package/src/components/Form/Select.test.tsx +99 -0
- package/src/components/Form/Select.tsx +239 -186
- package/src/components/Form/SelectOption.tsx +88 -0
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +93 -23
- package/src/components/Hero/Hero.test.tsx +142 -0
- package/src/components/Hero/Hero.tsx +343 -58
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.test.tsx +62 -0
- package/src/components/List/List.tsx +32 -25
- package/src/components/List/ListItem.tsx +20 -0
- package/src/components/Modal/Modal.stories.tsx +67 -2
- package/src/components/Modal/Modal.tsx +208 -125
- package/src/components/Modal/ModalCompound.test.tsx +94 -0
- package/src/components/Navigation/Menu/MegaMenu.tsx +70 -70
- package/src/components/Navigation/Nav/NavDropdown.tsx +1 -5
- package/src/components/Navigation/SideMenu/SideMenu.stories.tsx +128 -28
- package/src/components/Navigation/SideMenu/SideMenu.tsx +5 -7
- package/src/components/Navigation/SideMenu/SideMenuItem.tsx +4 -5
- package/src/components/Pagination/Pagination.stories.tsx +7 -4
- package/src/components/Pagination/Pagination.tsx +199 -202
- package/src/components/PhotoViewer/PhotoViewer.tsx +4 -1
- package/src/components/Popover/Popover.stories.tsx +99 -192
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +35 -44
- package/src/components/River/River.stories.tsx +2 -1
- package/src/components/SectionIntro/SectionIntro.stories.tsx +71 -71
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +3 -1
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +8 -6
- package/src/components/Steps/Steps.tsx +124 -21
- package/src/components/Steps/StepsCompound.test.tsx +81 -0
- package/src/components/Tabs/Tabs.stories.tsx +12 -9
- package/src/components/Tabs/Tabs.tsx +230 -75
- package/src/components/Tabs/TabsCompound.test.tsx +64 -0
- package/src/components/Toggle/Toggle.stories.tsx +27 -13
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +24 -20
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +129 -127
- package/src/components/Upload/Upload.tsx +287 -283
- package/src/components/VideoPlayer/VideoPlayer.tsx +6 -1
- package/src/components/index.ts +13 -2
- package/src/layouts/Grid/Grid.stories.tsx +9 -3
- package/src/layouts/MasonryGrid/MasonryGrid.tsx +5 -1
- package/src/lib/__tests__/theme-tools.test.ts +32 -6
- package/src/lib/composables/index.ts +0 -4
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +102 -60
- package/src/lib/composables/useChartExport.ts +1 -1
- package/src/lib/composables/useDataTable.ts +29 -17
- package/src/lib/composables/useHero.ts +58 -14
- package/src/lib/composables/useHeroBackgroundSlider.ts +2 -9
- package/src/lib/composables/useInput.ts +10 -8
- package/src/lib/composables/useSideMenu.ts +6 -5
- package/src/lib/composables/useTooltip.ts +1 -2
- package/src/lib/composables/useVideoPlayer.ts +44 -35
- package/src/lib/config/index.ts +154 -154
- package/src/lib/constants/cssVariables.ts +29 -29
- package/src/lib/hooks/__tests__/useComponentCustomization.test.ts +2 -6
- package/src/lib/hooks/index.ts +1 -1
- package/src/lib/hooks/useComponentCustomization.ts +11 -17
- package/src/lib/hooks/usePerformanceMonitor.ts +6 -7
- package/src/lib/patterns/__tests__/slots.test.ts +1 -1
- package/src/lib/patterns/index.ts +1 -1
- package/src/lib/patterns/slots.tsx +8 -13
- package/src/lib/storybook/InteractiveDemo.tsx +13 -18
- package/src/lib/storybook/PreviewContainer.tsx +1 -1
- package/src/lib/storybook/VariantsGrid.tsx +3 -7
- package/src/lib/storybook/index.ts +1 -1
- package/src/lib/theme/adapters/cssVariableMapper.ts +47 -74
- package/src/lib/theme/adapters/index.ts +3 -9
- package/src/lib/theme/adapters/themeAdapter.ts +41 -26
- package/src/lib/theme/config/index.ts +1 -1
- package/src/lib/theme/config/types.ts +2 -2
- package/src/lib/theme/config/validator.ts +10 -5
- package/src/lib/theme/constants/constants.ts +2 -2
- package/src/lib/theme/constants/index.ts +1 -2
- package/src/lib/theme/core/__tests__/createTheme.test.ts +20 -22
- package/src/lib/theme/core/composeTheme.ts +32 -26
- package/src/lib/theme/core/createTheme.ts +1 -1
- package/src/lib/theme/core/createThemeObject.ts +308 -301
- package/src/lib/theme/core/index.ts +3 -3
- package/src/lib/theme/devtools/CLI.ts +105 -111
- package/src/lib/theme/devtools/Comparator.tsx +50 -32
- package/src/lib/theme/devtools/DesignTokensCustomizer.stories.tsx +50 -48
- package/src/lib/theme/devtools/DesignTokensCustomizer.tsx +257 -63
- package/src/lib/theme/devtools/Inspector.tsx +75 -60
- package/src/lib/theme/devtools/LiveEditor.tsx +97 -76
- package/src/lib/theme/devtools/Preview.tsx +150 -106
- package/src/lib/theme/devtools/ThemeValidator.ts +29 -21
- package/src/lib/theme/devtools/index.ts +3 -9
- package/src/lib/theme/devtools/useHistory.ts +23 -21
- package/src/lib/theme/errors/errors.ts +12 -11
- package/src/lib/theme/errors/index.ts +2 -7
- package/src/lib/theme/generators/generateCSS.ts +9 -13
- package/src/lib/theme/generators/generateCSSNested.ts +1 -6
- package/src/lib/theme/generators/generateCSSVariables.ts +673 -630
- package/src/lib/theme/generators/index.ts +1 -4
- package/src/lib/theme/i18n/index.ts +1 -1
- package/src/lib/theme/i18n/rtl.ts +13 -13
- package/src/lib/theme/index.ts +7 -16
- package/src/lib/theme/runtime/ThemeApplicator.ts +4 -4
- package/src/lib/theme/runtime/ThemeContext.tsx +1 -1
- package/src/lib/theme/runtime/ThemeErrorBoundary.tsx +19 -23
- package/src/lib/theme/runtime/ThemeProvider.tsx +230 -239
- package/src/lib/theme/runtime/__tests__/ThemeProvider.integration.test.tsx +1 -1
- package/src/lib/theme/runtime/__tests__/ThemeProvider.test.tsx +24 -29
- package/src/lib/theme/runtime/index.ts +2 -5
- package/src/lib/theme/runtime/useTheme.ts +18 -18
- package/src/lib/theme/runtime/useThemeTokens.ts +22 -22
- package/src/lib/theme/test/testTheme.ts +15 -16
- package/src/lib/theme/tokens/index.ts +2 -7
- package/src/lib/theme/tokens/tokens.ts +25 -24
- package/src/lib/theme/types.ts +428 -411
- package/src/lib/theme/utils/__tests__/themeValidation.test.ts +3 -3
- package/src/lib/theme/utils/componentTheming.ts +18 -18
- package/src/lib/theme/utils/domUtils.ts +277 -289
- package/src/lib/theme/utils/index.ts +1 -2
- package/src/lib/theme/utils/injectCSS.ts +10 -14
- package/src/lib/theme/utils/naming.ts +20 -16
- package/src/lib/theme/utils/themeHelpers.ts +10 -12
- package/src/lib/theme/utils/themeUtils.ts +85 -86
- package/src/lib/theme/utils/themeValidation.ts +82 -33
- package/src/lib/theme-tools.ts +8 -6
- package/src/lib/types/components.ts +180 -73
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/componentUtils.test.ts +57 -2
- package/src/lib/utils/__tests__/csv.test.ts +1 -1
- package/src/lib/utils/__tests__/themeNaming.test.ts +117 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +3 -1
- package/src/lib/utils/dataTableExport.ts +1 -5
- package/src/lib/utils/fontPreloader.ts +10 -19
- package/src/lib/utils/icons.ts +4 -1
- package/src/lib/utils/index.ts +2 -6
- package/src/lib/utils/memoryMonitor.ts +10 -8
- package/src/lib/utils/themeNaming.ts +3 -3
- package/src/styles/01-settings/_index.scss +0 -1
- package/src/styles/01-settings/_settings.colors.scss +8 -8
- package/src/styles/01-settings/_settings.design-tokens.scss +61 -50
- package/src/styles/01-settings/_settings.navbar.scss +1 -1
- package/src/styles/01-settings/_settings.spacing.scss +3 -4
- package/src/styles/01-settings/_settings.tooltip.scss +1 -1
- package/src/styles/01-settings/_settings.typography.scss +1 -1
- package/src/styles/02-tools/_tools.breakpoints.scss +1 -1
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +36 -24
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.atomix-glass.scss +13 -9
- package/src/styles/06-components/_components.button.scss +16 -4
- package/src/styles/06-components/_components.callout.scss +27 -21
- package/src/styles/06-components/_components.card.scss +5 -14
- package/src/styles/06-components/_components.chart.scss +22 -19
- package/src/styles/06-components/_components.checkbox.scss +3 -1
- package/src/styles/06-components/_components.color-mode-toggle.scss +3 -1
- package/src/styles/06-components/_components.edge-panel.scss +9 -2
- package/src/styles/06-components/_components.footer.scss +1 -1
- package/src/styles/06-components/_components.side-menu.scss +5 -5
- package/src/styles/06-components/_components.toggle.scss +18 -0
- package/src/styles/06-components/_index.scss +1 -1
- package/src/styles/06-components/old.chart.styles.scss +0 -2
- package/src/styles/99-utilities/_utilities.border.scss +69 -27
- package/src/styles/99-utilities/_utilities.display.scss +1 -1
- package/src/styles/99-utilities/_utilities.opacity.scss +10 -0
- package/src/styles/99-utilities/_utilities.position.scss +16 -9
- package/src/styles/99-utilities/_utilities.scss +1 -1
- package/src/styles/99-utilities/_utilities.sizes.scss +47 -18
- package/src/styles/99-utilities/_utilities.spacing.scss +118 -66
- package/src/styles/99-utilities/_utilities.text-gradient.scss +30 -30
- package/src/styles/99-utilities/_utilities.text.scss +67 -47
|
@@ -1,85 +1,206 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { memo, forwardRef } from 'react';
|
|
2
2
|
import { CalloutProps } from '../../lib/types/components';
|
|
3
3
|
import { useCallout } from '../../lib/composables/useCallout';
|
|
4
4
|
import { Icon } from '../Icon/Icon';
|
|
5
5
|
import { AtomixGlass } from '../AtomixGlass/AtomixGlass';
|
|
6
6
|
|
|
7
|
+
// Subcomponents
|
|
8
|
+
export const CalloutIcon = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
9
|
+
({ children, className = '', ...props }, ref) => (
|
|
10
|
+
<div ref={ref} className={`c-callout__icon ${className}`.trim()} {...props}>
|
|
11
|
+
{children}
|
|
12
|
+
</div>
|
|
13
|
+
)
|
|
14
|
+
);
|
|
15
|
+
CalloutIcon.displayName = 'CalloutIcon';
|
|
16
|
+
|
|
17
|
+
export const CalloutMessage = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
18
|
+
({ children, className = '', ...props }, ref) => (
|
|
19
|
+
<div ref={ref} className={`c-callout__message ${className}`.trim()} {...props}>
|
|
20
|
+
{children}
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
);
|
|
24
|
+
CalloutMessage.displayName = 'CalloutMessage';
|
|
25
|
+
|
|
26
|
+
export const CalloutTitle = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
27
|
+
({ children, className = '', ...props }, ref) => (
|
|
28
|
+
<div ref={ref} className={`c-callout__title ${className}`.trim()} {...props}>
|
|
29
|
+
{children}
|
|
30
|
+
</div>
|
|
31
|
+
)
|
|
32
|
+
);
|
|
33
|
+
CalloutTitle.displayName = 'CalloutTitle';
|
|
34
|
+
|
|
35
|
+
export const CalloutText = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
36
|
+
({ children, className = '', ...props }, ref) => (
|
|
37
|
+
<div ref={ref} className={`c-callout__text ${className}`.trim()} {...props}>
|
|
38
|
+
{children}
|
|
39
|
+
</div>
|
|
40
|
+
)
|
|
41
|
+
);
|
|
42
|
+
CalloutText.displayName = 'CalloutText';
|
|
43
|
+
|
|
44
|
+
export const CalloutActions = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
45
|
+
({ children, className = '', ...props }, ref) => (
|
|
46
|
+
<div ref={ref} className={`c-callout__actions ${className}`.trim()} {...props}>
|
|
47
|
+
{children}
|
|
48
|
+
</div>
|
|
49
|
+
)
|
|
50
|
+
);
|
|
51
|
+
CalloutActions.displayName = 'CalloutActions';
|
|
52
|
+
|
|
53
|
+
export interface CalloutCloseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
|
|
54
|
+
export const CalloutCloseButton = forwardRef<HTMLButtonElement, CalloutCloseButtonProps>(
|
|
55
|
+
({ onClick, className = '', ...props }, ref) => (
|
|
56
|
+
<button
|
|
57
|
+
ref={ref}
|
|
58
|
+
className={`c-callout__close-btn ${className}`.trim()}
|
|
59
|
+
onClick={onClick}
|
|
60
|
+
aria-label="Close"
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
63
|
+
<Icon name="X" size="md" />
|
|
64
|
+
</button>
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
CalloutCloseButton.displayName = 'CalloutCloseButton';
|
|
68
|
+
|
|
69
|
+
// Wrapper for content (icon + message)
|
|
70
|
+
export const CalloutContent = forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
71
|
+
({ children, className = '', ...props }, ref) => (
|
|
72
|
+
<div ref={ref} className={`c-callout__content ${className}`.trim()} {...props}>
|
|
73
|
+
{children}
|
|
74
|
+
</div>
|
|
75
|
+
)
|
|
76
|
+
);
|
|
77
|
+
CalloutContent.displayName = 'CalloutContent';
|
|
78
|
+
|
|
7
79
|
/**
|
|
8
80
|
* Callout component for displaying important messages, notifications, or alerts
|
|
9
81
|
*/
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
variant,
|
|
26
|
-
|
|
27
|
-
|
|
82
|
+
type CalloutComponent = React.FC<CalloutProps> & {
|
|
83
|
+
Icon: typeof CalloutIcon;
|
|
84
|
+
Message: typeof CalloutMessage;
|
|
85
|
+
Title: typeof CalloutTitle;
|
|
86
|
+
Text: typeof CalloutText;
|
|
87
|
+
Actions: typeof CalloutActions;
|
|
88
|
+
CloseButton: typeof CalloutCloseButton;
|
|
89
|
+
Content: typeof CalloutContent;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const Callout: CalloutComponent = memo(
|
|
93
|
+
({
|
|
94
|
+
title,
|
|
95
|
+
children,
|
|
96
|
+
icon,
|
|
97
|
+
variant = 'primary',
|
|
98
|
+
onClose,
|
|
99
|
+
actions,
|
|
100
|
+
compact = false,
|
|
101
|
+
isToast = false,
|
|
28
102
|
glass,
|
|
29
103
|
className,
|
|
30
104
|
style,
|
|
31
|
-
|
|
105
|
+
...props
|
|
106
|
+
}: CalloutProps) => {
|
|
107
|
+
const { generateCalloutClass, handleClose } = useCallout({
|
|
108
|
+
variant,
|
|
109
|
+
compact,
|
|
110
|
+
isToast,
|
|
111
|
+
glass,
|
|
112
|
+
className,
|
|
113
|
+
style,
|
|
114
|
+
});
|
|
32
115
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
116
|
+
// Determine appropriate ARIA attributes based on variant
|
|
117
|
+
const getAriaAttributes = () => {
|
|
118
|
+
const baseAttributes: Record<string, string> = {
|
|
119
|
+
role: 'region',
|
|
120
|
+
};
|
|
38
121
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
122
|
+
// For toast notifications or alerts, use appropriate role and live region
|
|
123
|
+
if (isToast) {
|
|
124
|
+
baseAttributes.role = 'alert';
|
|
125
|
+
baseAttributes['aria-live'] = 'polite';
|
|
126
|
+
} else if (['warning', 'error'].includes(variant)) {
|
|
127
|
+
baseAttributes.role = 'alert';
|
|
128
|
+
baseAttributes['aria-live'] = 'assertive';
|
|
129
|
+
} else if (['info', 'success'].includes(variant)) {
|
|
130
|
+
baseAttributes.role = 'status';
|
|
131
|
+
baseAttributes['aria-live'] = 'polite';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return baseAttributes;
|
|
135
|
+
};
|
|
50
136
|
|
|
51
|
-
|
|
52
|
-
|
|
137
|
+
// Check for compound usage
|
|
138
|
+
const hasCompoundComponents = React.Children.toArray(children).some((child) =>
|
|
139
|
+
React.isValidElement(child) &&
|
|
140
|
+
[
|
|
141
|
+
'CalloutIcon',
|
|
142
|
+
'CalloutMessage',
|
|
143
|
+
'CalloutTitle',
|
|
144
|
+
'CalloutText',
|
|
145
|
+
'CalloutActions',
|
|
146
|
+
'CalloutContent',
|
|
147
|
+
].includes((child.type as any).displayName)
|
|
148
|
+
);
|
|
53
149
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<div className="c-
|
|
59
|
-
{
|
|
60
|
-
|
|
150
|
+
const calloutContent = hasCompoundComponents ? (
|
|
151
|
+
children
|
|
152
|
+
) : (
|
|
153
|
+
<>
|
|
154
|
+
<div className="c-callout__content">
|
|
155
|
+
{icon && <div className="c-callout__icon">{icon}</div>}
|
|
156
|
+
<div className="c-callout__message">
|
|
157
|
+
{title && <div className="c-callout__title">{title}</div>}
|
|
158
|
+
{children && <div className="c-callout__text">{children}</div>}
|
|
159
|
+
</div>
|
|
61
160
|
</div>
|
|
62
|
-
</div>
|
|
63
161
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
162
|
+
{actions && <div className="c-callout__actions">{actions}</div>}
|
|
163
|
+
|
|
164
|
+
{onClose && (
|
|
165
|
+
<button
|
|
166
|
+
className="c-callout__close-btn"
|
|
167
|
+
onClick={handleClose(onClose)}
|
|
168
|
+
aria-label="Close"
|
|
169
|
+
>
|
|
170
|
+
<Icon name="X" size="md" />
|
|
171
|
+
</button>
|
|
172
|
+
)}
|
|
173
|
+
</>
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
if (glass) {
|
|
177
|
+
// Default glass settings for callouts
|
|
178
|
+
const defaultGlassProps = {
|
|
179
|
+
displacementScale: 30,
|
|
180
|
+
cornerRadius: 8,
|
|
181
|
+
elasticity: 0,
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const glassProps = glass === true ? defaultGlassProps : { ...defaultGlassProps, ...glass };
|
|
81
185
|
|
|
82
|
-
|
|
186
|
+
return (
|
|
187
|
+
<div
|
|
188
|
+
className={generateCalloutClass({ variant, compact, isToast, glass, className })}
|
|
189
|
+
{...getAriaAttributes()}
|
|
190
|
+
{...props}
|
|
191
|
+
style={style}
|
|
192
|
+
>
|
|
193
|
+
<AtomixGlass {...glassProps}>
|
|
194
|
+
<div
|
|
195
|
+
className="c-callout__glass-content"
|
|
196
|
+
style={{ borderRadius: glassProps.cornerRadius }}
|
|
197
|
+
>
|
|
198
|
+
{calloutContent}
|
|
199
|
+
</div>
|
|
200
|
+
</AtomixGlass>
|
|
201
|
+
</div>
|
|
202
|
+
);
|
|
203
|
+
}
|
|
83
204
|
|
|
84
205
|
return (
|
|
85
206
|
<div
|
|
@@ -88,32 +209,23 @@ export const Callout: React.FC<CalloutProps> = ({
|
|
|
88
209
|
{...props}
|
|
89
210
|
style={style}
|
|
90
211
|
>
|
|
91
|
-
|
|
92
|
-
<div
|
|
93
|
-
className="c-callout__glass-content"
|
|
94
|
-
style={{ borderRadius: glassProps.cornerRadius }}
|
|
95
|
-
>
|
|
96
|
-
{calloutContent}
|
|
97
|
-
</div>
|
|
98
|
-
</AtomixGlass>
|
|
212
|
+
{calloutContent}
|
|
99
213
|
</div>
|
|
100
214
|
);
|
|
101
215
|
}
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
<div
|
|
105
|
-
className={generateCalloutClass({ variant, compact, isToast, glass, className })}
|
|
106
|
-
{...getAriaAttributes()}
|
|
107
|
-
{...props}
|
|
108
|
-
style={style}
|
|
109
|
-
>
|
|
110
|
-
{calloutContent}
|
|
111
|
-
</div>
|
|
112
|
-
);
|
|
113
|
-
};
|
|
216
|
+
) as unknown as CalloutComponent;
|
|
114
217
|
|
|
115
218
|
Callout.displayName = 'Callout';
|
|
116
219
|
|
|
220
|
+
// Attach subcomponents
|
|
221
|
+
Callout.Icon = CalloutIcon;
|
|
222
|
+
Callout.Message = CalloutMessage;
|
|
223
|
+
Callout.Title = CalloutTitle;
|
|
224
|
+
Callout.Text = CalloutText;
|
|
225
|
+
Callout.Actions = CalloutActions;
|
|
226
|
+
Callout.CloseButton = CalloutCloseButton;
|
|
227
|
+
Callout.Content = CalloutContent;
|
|
228
|
+
|
|
117
229
|
export type { CalloutProps };
|
|
118
230
|
|
|
119
231
|
export default Callout;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { render, screen, fireEvent } from '@testing-library/react';
|
|
2
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
3
|
+
import { Callout } from './Callout';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
|
|
6
|
+
describe('Callout Component', () => {
|
|
7
|
+
it('renders correctly with legacy props', () => {
|
|
8
|
+
render(
|
|
9
|
+
<Callout title="Legacy Title" icon={<span>Icon</span>}>
|
|
10
|
+
Legacy Content
|
|
11
|
+
</Callout>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
expect(screen.getByText('Legacy Title')).toBeInTheDocument();
|
|
15
|
+
expect(screen.getByText('Legacy Content')).toBeInTheDocument();
|
|
16
|
+
expect(screen.getByText('Icon')).toBeInTheDocument();
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('renders correctly with compound components', () => {
|
|
20
|
+
render(
|
|
21
|
+
<Callout>
|
|
22
|
+
<Callout.Content>
|
|
23
|
+
<Callout.Icon>
|
|
24
|
+
<span>Compound Icon</span>
|
|
25
|
+
</Callout.Icon>
|
|
26
|
+
<Callout.Message>
|
|
27
|
+
<Callout.Title>Compound Title</Callout.Title>
|
|
28
|
+
<Callout.Text>Compound Text</Callout.Text>
|
|
29
|
+
</Callout.Message>
|
|
30
|
+
</Callout.Content>
|
|
31
|
+
<Callout.Actions>
|
|
32
|
+
<button>Action</button>
|
|
33
|
+
</Callout.Actions>
|
|
34
|
+
<Callout.CloseButton onClick={() => {}} />
|
|
35
|
+
</Callout>
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(screen.getByText('Compound Icon')).toBeInTheDocument();
|
|
39
|
+
expect(screen.getByText('Compound Title')).toBeInTheDocument();
|
|
40
|
+
expect(screen.getByText('Compound Text')).toBeInTheDocument();
|
|
41
|
+
expect(screen.getByText('Action')).toBeInTheDocument();
|
|
42
|
+
expect(screen.getByLabelText('Close')).toBeInTheDocument();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('prioritizes compound components over legacy props', () => {
|
|
46
|
+
render(
|
|
47
|
+
<Callout title="Legacy Title">
|
|
48
|
+
<Callout.Content>
|
|
49
|
+
<Callout.Message>
|
|
50
|
+
<Callout.Text>Compound Text</Callout.Text>
|
|
51
|
+
</Callout.Message>
|
|
52
|
+
</Callout.Content>
|
|
53
|
+
</Callout>
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
expect(screen.getByText('Compound Text')).toBeInTheDocument();
|
|
57
|
+
expect(screen.queryByText('Legacy Title')).not.toBeInTheDocument();
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('renders close button when used as compound', () => {
|
|
61
|
+
const onClose = vi.fn();
|
|
62
|
+
render(
|
|
63
|
+
<Callout>
|
|
64
|
+
<Callout.CloseButton onClick={onClose} />
|
|
65
|
+
</Callout>
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
const button = screen.getByLabelText('Close');
|
|
69
|
+
fireEvent.click(button);
|
|
70
|
+
expect(onClose).toHaveBeenCalled();
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -130,64 +130,64 @@ Cards are flexible containers for displaying content with optional headers, imag
|
|
|
130
130
|
defaultValue: { summary: 'none' },
|
|
131
131
|
},
|
|
132
132
|
},
|
|
133
|
-
row: {
|
|
134
|
-
control: 'boolean',
|
|
133
|
+
row: {
|
|
134
|
+
control: 'boolean',
|
|
135
135
|
description: 'Whether to arrange content horizontally',
|
|
136
136
|
table: {
|
|
137
137
|
type: { summary: 'boolean' },
|
|
138
138
|
defaultValue: { summary: false },
|
|
139
139
|
},
|
|
140
140
|
},
|
|
141
|
-
flat: {
|
|
142
|
-
control: 'boolean',
|
|
141
|
+
flat: {
|
|
142
|
+
control: 'boolean',
|
|
143
143
|
description: 'Whether to remove border radius',
|
|
144
144
|
table: {
|
|
145
145
|
type: { summary: 'boolean' },
|
|
146
146
|
defaultValue: { summary: false },
|
|
147
147
|
},
|
|
148
148
|
},
|
|
149
|
-
active: {
|
|
150
|
-
control: 'boolean',
|
|
149
|
+
active: {
|
|
150
|
+
control: 'boolean',
|
|
151
151
|
description: 'Whether the card is in active state',
|
|
152
152
|
table: {
|
|
153
153
|
type: { summary: 'boolean' },
|
|
154
154
|
defaultValue: { summary: false },
|
|
155
155
|
},
|
|
156
156
|
},
|
|
157
|
-
disabled: {
|
|
158
|
-
control: 'boolean',
|
|
157
|
+
disabled: {
|
|
158
|
+
control: 'boolean',
|
|
159
159
|
description: 'Whether the card is disabled',
|
|
160
160
|
table: {
|
|
161
161
|
type: { summary: 'boolean' },
|
|
162
162
|
defaultValue: { summary: false },
|
|
163
163
|
},
|
|
164
164
|
},
|
|
165
|
-
loading: {
|
|
166
|
-
control: 'boolean',
|
|
165
|
+
loading: {
|
|
166
|
+
control: 'boolean',
|
|
167
167
|
description: 'Whether the card is in loading state',
|
|
168
168
|
table: {
|
|
169
169
|
type: { summary: 'boolean' },
|
|
170
170
|
defaultValue: { summary: false },
|
|
171
171
|
},
|
|
172
172
|
},
|
|
173
|
-
selected: {
|
|
174
|
-
control: 'boolean',
|
|
173
|
+
selected: {
|
|
174
|
+
control: 'boolean',
|
|
175
175
|
description: 'Whether the card is selected',
|
|
176
176
|
table: {
|
|
177
177
|
type: { summary: 'boolean' },
|
|
178
178
|
defaultValue: { summary: false },
|
|
179
179
|
},
|
|
180
180
|
},
|
|
181
|
-
interactive: {
|
|
182
|
-
control: 'boolean',
|
|
181
|
+
interactive: {
|
|
182
|
+
control: 'boolean',
|
|
183
183
|
description: 'Whether the card responds to interactions',
|
|
184
184
|
table: {
|
|
185
185
|
type: { summary: 'boolean' },
|
|
186
186
|
defaultValue: { summary: false },
|
|
187
187
|
},
|
|
188
188
|
},
|
|
189
|
-
className: {
|
|
190
|
-
control: 'text',
|
|
189
|
+
className: {
|
|
190
|
+
control: 'text',
|
|
191
191
|
description: 'Additional CSS class names',
|
|
192
192
|
table: {
|
|
193
193
|
type: { summary: 'string' },
|
|
@@ -381,12 +381,14 @@ export const WithGlassEffect: Story = {
|
|
|
381
381
|
parameters: {
|
|
382
382
|
docs: {
|
|
383
383
|
description: {
|
|
384
|
-
story:
|
|
384
|
+
story:
|
|
385
|
+
'Demonstrates a card with glass morphism effect applied, creating a translucent, frosted appearance that works well over colorful backgrounds.',
|
|
385
386
|
},
|
|
386
387
|
},
|
|
387
388
|
},
|
|
388
389
|
render: args => (
|
|
389
|
-
<div
|
|
390
|
+
<div
|
|
391
|
+
className="u-bg-cover u-h-80vh u-w-90vw u-grid u-rounded-xl u-overflow-hidden"
|
|
390
392
|
style={{
|
|
391
393
|
backgroundImage: `url(https://picsum.photos/id/128/1920/1024)`,
|
|
392
394
|
}}
|
|
@@ -720,7 +722,8 @@ export const AllGlassModesComparison: Story = {
|
|
|
720
722
|
parameters: {
|
|
721
723
|
docs: {
|
|
722
724
|
description: {
|
|
723
|
-
story:
|
|
725
|
+
story:
|
|
726
|
+
'Side-by-side comparison of all available glass morphism modes (standard, polar, prominent, shader) to help you choose the right effect for your design.',
|
|
724
727
|
},
|
|
725
728
|
},
|
|
726
729
|
},
|
|
@@ -966,7 +969,8 @@ export const GlassCardGallery: Story = {
|
|
|
966
969
|
// Glass Card Layouts
|
|
967
970
|
export const GlassCardLayouts: Story = {
|
|
968
971
|
render: () => (
|
|
969
|
-
<div
|
|
972
|
+
<div
|
|
973
|
+
className="u-bg-cover u-bg-center u-p-12 u-rounded-xl u-min-h-95vh u-min-w-95vw u-overflow-auto"
|
|
970
974
|
style={{
|
|
971
975
|
backgroundImage: 'url(https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?w=1920)',
|
|
972
976
|
}}
|
|
@@ -979,9 +983,7 @@ export const GlassCardLayouts: Story = {
|
|
|
979
983
|
<div className="u-flex u-gap-8">
|
|
980
984
|
{/* Standard Layout */}
|
|
981
985
|
<div className="u-w-50">
|
|
982
|
-
<h3 className="u-text-white u-mb-4 u-text-shadow">
|
|
983
|
-
Standard Layout
|
|
984
|
-
</h3>
|
|
986
|
+
<h3 className="u-text-white u-mb-4 u-text-shadow">Standard Layout</h3>
|
|
985
987
|
<Card
|
|
986
988
|
title="Standard Glass Card"
|
|
987
989
|
text="This is a standard glass card with vertical layout."
|
|
@@ -999,9 +1001,7 @@ export const GlassCardLayouts: Story = {
|
|
|
999
1001
|
|
|
1000
1002
|
{/* Row Layout */}
|
|
1001
1003
|
<div className="u-w-50">
|
|
1002
|
-
<h3 className="u-text-white u-mb-4 u-text-shadow">
|
|
1003
|
-
Row Layout
|
|
1004
|
-
</h3>
|
|
1004
|
+
<h3 className="u-text-white u-mb-4 u-text-shadow">Row Layout</h3>
|
|
1005
1005
|
<Card
|
|
1006
1006
|
title="Row Glass Card"
|
|
1007
1007
|
text="This is a row glass card with horizontal layout."
|
|
@@ -1024,9 +1024,7 @@ export const GlassCardLayouts: Story = {
|
|
|
1024
1024
|
|
|
1025
1025
|
{/* Flat Layout */}
|
|
1026
1026
|
<div className="u-w-50">
|
|
1027
|
-
<h3 className="u-text-white u-mb-4 u-text-shadow">
|
|
1028
|
-
Flat Layout
|
|
1029
|
-
</h3>
|
|
1027
|
+
<h3 className="u-text-white u-mb-4 u-text-shadow">Flat Layout</h3>
|
|
1030
1028
|
<Card
|
|
1031
1029
|
title="Flat Glass Card"
|
|
1032
1030
|
text="This is a flat glass card with edge-to-edge image."
|
|
@@ -1081,7 +1079,13 @@ export const SizeVariants: Story = {
|
|
|
1081
1079
|
// Color Variants
|
|
1082
1080
|
export const ColorVariants: Story = {
|
|
1083
1081
|
render: () => (
|
|
1084
|
-
<div
|
|
1082
|
+
<div
|
|
1083
|
+
style={{
|
|
1084
|
+
display: 'grid',
|
|
1085
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
|
|
1086
|
+
gap: '1rem',
|
|
1087
|
+
}}
|
|
1088
|
+
>
|
|
1085
1089
|
<Card variant="primary" title="Primary Card" text="Primary variant card." />
|
|
1086
1090
|
<Card variant="secondary" title="Secondary Card" text="Secondary variant card." />
|
|
1087
1091
|
<Card variant="success" title="Success Card" text="Success variant card." />
|
|
@@ -1097,11 +1101,37 @@ export const ColorVariants: Story = {
|
|
|
1097
1101
|
// Appearance Variants
|
|
1098
1102
|
export const AppearanceVariants: Story = {
|
|
1099
1103
|
render: () => (
|
|
1100
|
-
<div
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1104
|
+
<div
|
|
1105
|
+
style={{
|
|
1106
|
+
display: 'grid',
|
|
1107
|
+
gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))',
|
|
1108
|
+
gap: '1rem',
|
|
1109
|
+
}}
|
|
1110
|
+
>
|
|
1111
|
+
<Card
|
|
1112
|
+
appearance="filled"
|
|
1113
|
+
variant="primary"
|
|
1114
|
+
title="Filled Card"
|
|
1115
|
+
text="Filled appearance with solid background."
|
|
1116
|
+
/>
|
|
1117
|
+
<Card
|
|
1118
|
+
appearance="outlined"
|
|
1119
|
+
variant="primary"
|
|
1120
|
+
title="Outlined Card"
|
|
1121
|
+
text="Outlined appearance with border only."
|
|
1122
|
+
/>
|
|
1123
|
+
<Card
|
|
1124
|
+
appearance="ghost"
|
|
1125
|
+
variant="primary"
|
|
1126
|
+
title="Ghost Card"
|
|
1127
|
+
text="Ghost appearance with minimal styling."
|
|
1128
|
+
/>
|
|
1129
|
+
<Card
|
|
1130
|
+
appearance="elevated"
|
|
1131
|
+
variant="primary"
|
|
1132
|
+
title="Elevated Card"
|
|
1133
|
+
text="Elevated appearance with shadow."
|
|
1134
|
+
/>
|
|
1105
1135
|
</div>
|
|
1106
1136
|
),
|
|
1107
1137
|
};
|
|
@@ -1188,7 +1218,8 @@ export const Comprehensive: Story = {
|
|
|
1188
1218
|
parameters: {
|
|
1189
1219
|
docs: {
|
|
1190
1220
|
description: {
|
|
1191
|
-
story:
|
|
1221
|
+
story:
|
|
1222
|
+
'A comprehensive example demonstrating various card features including sizes, variants, appearances, elevations, and states in a grid layout.',
|
|
1192
1223
|
},
|
|
1193
1224
|
},
|
|
1194
1225
|
},
|
|
@@ -96,7 +96,24 @@ export const Card = React.memo(
|
|
|
96
96
|
]
|
|
97
97
|
.filter(Boolean)
|
|
98
98
|
.join(' '),
|
|
99
|
-
[
|
|
99
|
+
[
|
|
100
|
+
size,
|
|
101
|
+
variant,
|
|
102
|
+
appearance,
|
|
103
|
+
elevation,
|
|
104
|
+
hoverable,
|
|
105
|
+
hoverElevation,
|
|
106
|
+
row,
|
|
107
|
+
flat,
|
|
108
|
+
active,
|
|
109
|
+
disabled,
|
|
110
|
+
loading,
|
|
111
|
+
selected,
|
|
112
|
+
interactive,
|
|
113
|
+
isClickable,
|
|
114
|
+
glass,
|
|
115
|
+
className,
|
|
116
|
+
]
|
|
100
117
|
);
|
|
101
118
|
|
|
102
119
|
// Determine ARIA role
|
|
@@ -239,11 +256,7 @@ export const Card = React.memo(
|
|
|
239
256
|
|
|
240
257
|
if (glass) {
|
|
241
258
|
const glassProps = glass === true ? {} : glass;
|
|
242
|
-
return
|
|
243
|
-
<AtomixGlass {...{ ...glassProps, elasticity: 0 }}>
|
|
244
|
-
{anchorElement}
|
|
245
|
-
</AtomixGlass>
|
|
246
|
-
);
|
|
259
|
+
return <AtomixGlass {...{ ...glassProps, elasticity: 0 }}>{anchorElement}</AtomixGlass>;
|
|
247
260
|
}
|
|
248
261
|
|
|
249
262
|
return anchorElement;
|
|
@@ -258,11 +271,7 @@ export const Card = React.memo(
|
|
|
258
271
|
|
|
259
272
|
if (glass) {
|
|
260
273
|
const glassProps = glass === true ? {} : glass;
|
|
261
|
-
return
|
|
262
|
-
<AtomixGlass {...{ ...glassProps, elasticity: 0 }}>
|
|
263
|
-
{divElement}
|
|
264
|
-
</AtomixGlass>
|
|
265
|
-
);
|
|
274
|
+
return <AtomixGlass {...{ ...glassProps, elasticity: 0 }}>{divElement}</AtomixGlass>;
|
|
266
275
|
}
|
|
267
276
|
|
|
268
277
|
return divElement;
|
|
@@ -327,10 +336,16 @@ export interface CardBodyProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
327
336
|
|
|
328
337
|
export const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(
|
|
329
338
|
({ scrollable = false, maxHeight, children, className = '', style, ...props }, ref) => {
|
|
330
|
-
const bodyClasses =
|
|
339
|
+
const bodyClasses =
|
|
340
|
+
`${CARD.SELECTORS.BODY.substring(1)} ${scrollable ? 'c-card__body--scrollable' : ''} ${className}`.trim();
|
|
331
341
|
const bodyStyle: React.CSSProperties = {
|
|
332
342
|
...style,
|
|
333
|
-
...(scrollable && maxHeight
|
|
343
|
+
...(scrollable && maxHeight
|
|
344
|
+
? {
|
|
345
|
+
maxHeight: typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight,
|
|
346
|
+
overflowY: 'auto',
|
|
347
|
+
}
|
|
348
|
+
: {}),
|
|
334
349
|
};
|
|
335
350
|
|
|
336
351
|
return (
|
|
@@ -352,7 +367,8 @@ export interface CardFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
352
367
|
|
|
353
368
|
export const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(
|
|
354
369
|
({ align, children, className = '', style, ...props }, ref) => {
|
|
355
|
-
const footerClasses =
|
|
370
|
+
const footerClasses =
|
|
371
|
+
`${CARD.SELECTORS.FOOTER.substring(1)} ${align ? `c-card__footer--align-${align}` : ''} ${className}`.trim();
|
|
356
372
|
|
|
357
373
|
return (
|
|
358
374
|
<div ref={ref} className={footerClasses} style={style} {...props}>
|