@shohojdhara/atomix 0.3.14 → 0.4.0
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 +20 -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 +44 -0
- package/build-tools/index.js +88 -0
- package/build-tools/package.json +50 -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 +21044 -2618
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +77 -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 +44 -0
- package/dist/build-tools/index.js +88 -0
- package/dist/build-tools/package.json +50 -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 +1 -1
- package/dist/charts.js +86 -57
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +136 -112
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +2 -5
- package/dist/forms.js +140 -128
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +1 -1
- package/dist/heavy.js +136 -112
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +152 -78
- package/dist/index.esm.js +346 -340
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +359 -353
- 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 +23 -8
- package/scripts/atomix-cli.js +170 -73
- 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 +161 -0
- package/scripts/cli/component-generator.js +253 -299
- package/scripts/cli/dependency-checker.js +355 -0
- package/scripts/cli/interactive-init.js +46 -5
- package/scripts/cli/template-manager.js +0 -2
- package/scripts/cli/templates/common-templates.js +636 -0
- package/scripts/cli/templates/composable-templates.js +148 -126
- package/scripts/cli/templates/index.js +23 -16
- package/scripts/cli/templates/project-templates.js +151 -23
- package/scripts/cli/templates/react-templates.js +280 -210
- package/scripts/cli/templates/scss-templates.js +90 -91
- package/scripts/cli/templates/testing-templates.js +206 -27
- package/scripts/cli/templates/testing-utils.js +278 -0
- package/scripts/cli/templates/types-templates.js +70 -56
- package/scripts/cli/theme-bridge.js +8 -2
- package/scripts/cli/token-manager.js +318 -206
- package/scripts/cli/utils.js +0 -1
- package/src/components/Accordion/Accordion.stories.tsx +358 -850
- package/src/components/Accordion/Accordion.test.tsx +70 -50
- package/src/components/Accordion/Accordion.tsx +99 -94
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +1 -1
- package/src/components/AtomixGlass/AtomixGlass.tsx +80 -39
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +103 -81
- package/src/components/AtomixGlass/GlassFilter.tsx +9 -16
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +8 -7
- package/src/components/AtomixGlass/glass-utils.ts +6 -5
- package/src/components/AtomixGlass/shader-utils.ts +133 -52
- package/src/components/AtomixGlass/stories/Customization.stories.tsx +131 -0
- package/src/components/AtomixGlass/stories/Examples.stories.tsx +2957 -2853
- 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 +51 -36
- package/src/components/AtomixGlass/stories/{ShaderVariants.stories.tsx → Shaders.stories.tsx} +2 -2
- package/src/components/AtomixGlass/stories/shared-components.tsx +90 -190
- package/src/components/Avatar/Avatar.stories.tsx +195 -0
- package/src/components/Avatar/Avatar.tsx +58 -56
- package/src/components/Badge/Badge.stories.tsx +122 -352
- package/src/components/Badge/Badge.test.tsx +41 -41
- package/src/components/Badge/Badge.tsx +64 -62
- package/src/components/Block/Block.stories.tsx +30 -11
- package/src/components/Breadcrumb/Breadcrumb.stories.tsx +142 -23
- package/src/components/Breadcrumb/Breadcrumb.tsx +62 -60
- package/src/components/Button/Button.stories.tsx +454 -1126
- package/src/components/Button/Button.test.tsx +123 -0
- package/src/components/Button/Button.tsx +88 -60
- package/src/components/Button/ButtonGroup.stories.tsx +376 -215
- package/src/components/Button/ButtonGroup.tsx +4 -15
- package/src/components/Callout/Callout.stories.tsx +316 -568
- package/src/components/Card/Card.stories.tsx +292 -81
- 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 +153 -16
- 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 +152 -66
- package/src/components/ColorModeToggle/ColorModeToggle.tsx +15 -3
- package/src/components/Countdown/Countdown.stories.tsx +114 -7
- package/src/components/DataTable/DataTable.stories.tsx +349 -144
- package/src/components/DataTable/DataTable.test.tsx +26 -148
- package/src/components/DataTable/DataTable.tsx +485 -456
- package/src/components/DatePicker/DatePicker.stories.tsx +310 -1066
- package/src/components/DatePicker/DatePicker.tsx +31 -26
- package/src/components/Dropdown/Dropdown.stories.tsx +153 -36
- package/src/components/Dropdown/Dropdown.tsx +313 -299
- package/src/components/EdgePanel/EdgePanel.stories.tsx +221 -25
- package/src/components/EdgePanel/EdgePanel.tsx +1 -3
- package/src/components/Footer/Footer.stories.tsx +396 -327
- package/src/components/Footer/Footer.tsx +130 -128
- package/src/components/Footer/FooterLink.tsx +2 -2
- package/src/components/Form/Checkbox.stories.tsx +140 -6
- package/src/components/Form/Checkbox.test.tsx +63 -0
- package/src/components/Form/Checkbox.tsx +122 -78
- package/src/components/Form/Form.stories.tsx +110 -19
- package/src/components/Form/FormGroup.stories.tsx +127 -4
- 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 +146 -17
- package/src/components/Form/Radio.tsx +68 -66
- package/src/components/Form/Select.stories.tsx +140 -8
- package/src/components/Form/Select.tsx +184 -182
- package/src/components/Form/Textarea.stories.tsx +149 -6
- package/src/components/Form/Textarea.test.tsx +27 -32
- package/src/components/Hero/Hero.stories.tsx +372 -38
- package/src/components/Hero/Hero.tsx +201 -55
- package/src/components/Icon/index.ts +7 -1
- package/src/components/List/List.stories.tsx +141 -3
- package/src/components/List/List.tsx +19 -23
- package/src/components/Modal/Modal.stories.tsx +183 -43
- package/src/components/Modal/Modal.tsx +130 -127
- 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 +354 -97
- package/src/components/Popover/Popover.tsx +41 -37
- package/src/components/Progress/Progress.stories.tsx +160 -7
- package/src/components/River/River.stories.tsx +3 -2
- package/src/components/SectionIntro/SectionIntro.stories.tsx +239 -47
- package/src/components/Slider/Slider.stories.tsx +12 -4
- package/src/components/Spinner/Spinner.stories.tsx +104 -8
- package/src/components/Spinner/Spinner.test.tsx +23 -23
- package/src/components/Spinner/Spinner.tsx +43 -46
- package/src/components/Steps/Steps.stories.tsx +173 -42
- package/src/components/Tabs/Tabs.stories.tsx +141 -12
- package/src/components/Tabs/Tabs.tsx +74 -72
- package/src/components/Testimonial/Testimonial.stories.tsx +120 -3
- package/src/components/Todo/Todo.stories.tsx +198 -9
- package/src/components/Toggle/Toggle.stories.tsx +137 -36
- package/src/components/Toggle/Toggle.test.tsx +65 -70
- package/src/components/Toggle/Toggle.tsx +4 -1
- package/src/components/Tooltip/Tooltip.stories.tsx +194 -100
- package/src/components/Tooltip/Tooltip.tsx +104 -106
- package/src/components/Upload/Upload.stories.tsx +241 -150
- 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/README.md +2 -2
- package/src/lib/__tests__/theme-tools.test.ts +219 -0
- package/src/lib/composables/index.ts +2 -2
- package/src/lib/composables/shared-mouse-tracker.ts +13 -14
- package/src/lib/composables/useAtomixGlass.ts +126 -97
- package/src/lib/composables/useChartExport.ts +3 -8
- package/src/lib/composables/useDataTable.ts +72 -43
- 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/components.ts +9 -32
- 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 +107 -105
- 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 +172 -71
- package/src/lib/types/partProps.ts +1 -1
- package/src/lib/utils/__tests__/csv.test.ts +45 -0
- package/src/lib/utils/componentUtils.ts +8 -12
- package/src/lib/utils/csv.ts +19 -0
- package/src/lib/utils/dataTableExport.ts +2 -15
- 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 +2 -2
- package/src/styles/01-settings/_index.scss +1 -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.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 +4 -4
- package/src/styles/02-tools/_tools.button.scss +51 -21
- package/src/styles/02-tools/_tools.utility-api.scss +38 -12
- package/src/styles/03-generic/_generic.root.scss +4 -3
- package/src/styles/06-components/_components.accordion.scss +56 -14
- 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 +25 -17
- 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/_index.scss +2 -0
- 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 +2 -0
- 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 +45 -0
- package/src/styles/99-utilities/_utilities.text.scss +67 -46
- 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/templates-original-backup.js +0 -1655
- package/scripts/cli/templates_backup.js +0 -684
- 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
|
@@ -1,17 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ButtonGroup.stories.tsx
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive Storybook stories for ButtonGroup
|
|
5
|
+
*
|
|
6
|
+
* @package Atomix
|
|
7
|
+
* @component ButtonGroup
|
|
8
|
+
*/
|
|
9
|
+
|
|
1
10
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
11
|
+
import { useState } from 'react';
|
|
2
12
|
import { ButtonGroup } from './ButtonGroup';
|
|
3
13
|
import { Button } from './Button';
|
|
4
14
|
import { SIZES } from '../../lib/constants/components';
|
|
5
15
|
|
|
6
|
-
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// TYPE DEFINITIONS
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Type helper for story props without children requirement
|
|
22
|
+
*/
|
|
23
|
+
type ButtonGroupStoryProps = Omit<React.ComponentProps<typeof ButtonGroup>, 'children'> & {
|
|
24
|
+
children?: React.ReactNode;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// ============================================================================
|
|
28
|
+
// SHARED UTILITIES & CONSTANTS
|
|
29
|
+
// ============================================================================
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Sample data for stories
|
|
33
|
+
*/
|
|
34
|
+
const sampleButtonTitles = {
|
|
35
|
+
basic: ['Left', 'Middle', 'Right'],
|
|
36
|
+
actions: ['Cancel', 'Save Draft', 'Publish'],
|
|
37
|
+
navigation: ['First', 'Previous', 'Next', 'Last'],
|
|
38
|
+
filters: ['All', 'Active', 'Completed'],
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// META CONFIGURATION
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
const meta: Meta<typeof ButtonGroup> = {
|
|
7
46
|
title: 'Components/ButtonGroup',
|
|
8
47
|
component: ButtonGroup,
|
|
9
48
|
parameters: {
|
|
10
49
|
layout: 'centered',
|
|
11
50
|
docs: {
|
|
12
51
|
description: {
|
|
13
|
-
component:
|
|
14
|
-
|
|
52
|
+
component: `
|
|
53
|
+
# ButtonGroup
|
|
54
|
+
|
|
55
|
+
The ButtonGroup component groups multiple buttons together, creating a visually connected set of buttons with proper border radius handling. Buttons in a group share borders and have rounded corners only on the outer edges.
|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- Connects multiple buttons with shared borders
|
|
60
|
+
- Proper border-radius handling for first and last buttons
|
|
61
|
+
- Supports all Button component variants and sizes
|
|
62
|
+
- Maintains accessibility features
|
|
63
|
+
- Responsive design
|
|
64
|
+
|
|
65
|
+
## Accessibility
|
|
66
|
+
|
|
67
|
+
- Keyboard support: Tab to focus, Enter/Space to activate buttons
|
|
68
|
+
- Screen reader: Announces button labels and group context
|
|
69
|
+
- ARIA support: Role and labeling options
|
|
70
|
+
- Focus management: Visual focus indicators
|
|
71
|
+
|
|
72
|
+
## Usage Examples
|
|
73
|
+
|
|
74
|
+
### Basic Usage
|
|
75
|
+
|
|
76
|
+
\`\`\`tsx
|
|
77
|
+
<ButtonGroup>
|
|
78
|
+
<Button label="Left" />
|
|
79
|
+
<Button label="Middle" />
|
|
80
|
+
<Button label="Right" />
|
|
81
|
+
</ButtonGroup>
|
|
82
|
+
\`\`\`
|
|
83
|
+
|
|
84
|
+
### With Variants
|
|
85
|
+
|
|
86
|
+
\`\`\`tsx
|
|
87
|
+
<ButtonGroup>
|
|
88
|
+
<Button label="Cancel" variant="secondary" />
|
|
89
|
+
<Button label="Save" variant="primary" />
|
|
90
|
+
</ButtonGroup>
|
|
91
|
+
\`\`\`
|
|
92
|
+
|
|
93
|
+
## API Reference
|
|
94
|
+
|
|
95
|
+
### Props
|
|
96
|
+
|
|
97
|
+
| Prop | Type | Default | Description |
|
|
98
|
+
| ---- | ---- | ------- | ----------- |
|
|
99
|
+
| vertical | boolean | false | Whether to stack buttons vertically |
|
|
100
|
+
| className | string | - | Additional CSS classes |
|
|
101
|
+
| children | ReactNode | - | Button elements to group |
|
|
102
|
+
|
|
103
|
+
## Design Tokens
|
|
104
|
+
|
|
105
|
+
Used design tokens:
|
|
106
|
+
|
|
107
|
+
- \`--atomix-btn-group-gap\`: Gap between buttons in group
|
|
108
|
+
- \`--atomix-btn-group-border-radius\`: Border radius for button groups
|
|
109
|
+
|
|
110
|
+
## Notes
|
|
111
|
+
|
|
112
|
+
When using ButtonGroup, ensure that all child buttons are of the same size for consistent appearance.
|
|
113
|
+
`,
|
|
15
114
|
},
|
|
16
115
|
},
|
|
17
116
|
},
|
|
@@ -19,15 +118,10 @@ const meta = {
|
|
|
19
118
|
argTypes: {
|
|
20
119
|
className: {
|
|
21
120
|
control: 'text',
|
|
22
|
-
description: 'Additional CSS
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
description: 'ARIA label for accessibility',
|
|
27
|
-
},
|
|
28
|
-
role: {
|
|
29
|
-
control: 'text',
|
|
30
|
-
description: 'ARIA role for the button group',
|
|
121
|
+
description: 'Additional CSS classes for the button group',
|
|
122
|
+
table: {
|
|
123
|
+
type: { summary: 'string' },
|
|
124
|
+
},
|
|
31
125
|
},
|
|
32
126
|
},
|
|
33
127
|
} satisfies Meta<typeof ButtonGroup>;
|
|
@@ -35,281 +129,348 @@ const meta = {
|
|
|
35
129
|
export default meta;
|
|
36
130
|
type Story = StoryObj<typeof meta>;
|
|
37
131
|
|
|
38
|
-
//
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
<ButtonGroup>
|
|
42
|
-
<Button label="Left" />
|
|
43
|
-
<Button label="Middle" />
|
|
44
|
-
<Button label="Right" />
|
|
45
|
-
</ButtonGroup>
|
|
46
|
-
),
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
export const TwoButtons: Story = {
|
|
50
|
-
render: () => (
|
|
51
|
-
<ButtonGroup>
|
|
52
|
-
<Button label="Cancel" variant="secondary" />
|
|
53
|
-
<Button label="Save" variant="primary" />
|
|
54
|
-
</ButtonGroup>
|
|
55
|
-
),
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export const ThreeButtons: Story = {
|
|
59
|
-
render: () => (
|
|
60
|
-
<ButtonGroup>
|
|
61
|
-
<Button label="Previous" variant="secondary" />
|
|
62
|
-
<Button label="Next" variant="primary" />
|
|
63
|
-
<Button label="Finish" variant="success" />
|
|
64
|
-
</ButtonGroup>
|
|
65
|
-
),
|
|
66
|
-
};
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// BASIC USAGE STORIES
|
|
134
|
+
// ============================================================================
|
|
67
135
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
136
|
+
export const BasicUsage: Story = {
|
|
137
|
+
args: {
|
|
138
|
+
children: (
|
|
139
|
+
<>
|
|
140
|
+
<Button label="Left" variant="primary" />
|
|
141
|
+
<Button label="Middle" variant="primary" />
|
|
142
|
+
<Button label="Right" variant="primary" />
|
|
143
|
+
</>
|
|
144
|
+
),
|
|
145
|
+
},
|
|
77
146
|
};
|
|
78
147
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
<Button label="One" variant="secondary" />
|
|
83
|
-
<Button label="Two" variant="secondary" />
|
|
84
|
-
<Button label="Three" variant="secondary" />
|
|
85
|
-
</ButtonGroup>
|
|
86
|
-
),
|
|
87
|
-
};
|
|
148
|
+
// ============================================================================
|
|
149
|
+
// VARIANTS & STATES STORIES
|
|
150
|
+
// ============================================================================
|
|
88
151
|
|
|
89
|
-
export const
|
|
152
|
+
export const HorizontalGroup: Story = {
|
|
90
153
|
render: () => (
|
|
91
154
|
<ButtonGroup>
|
|
92
|
-
<Button label="
|
|
93
|
-
<Button label="
|
|
94
|
-
<Button label="
|
|
155
|
+
<Button label="Left" variant="primary" />
|
|
156
|
+
<Button label="Middle" variant="secondary" />
|
|
157
|
+
<Button label="Right" variant="success" />
|
|
95
158
|
</ButtonGroup>
|
|
96
159
|
),
|
|
97
160
|
};
|
|
98
161
|
|
|
99
|
-
export const
|
|
162
|
+
export const VerticalGroup: Story = {
|
|
100
163
|
render: () => (
|
|
101
|
-
<ButtonGroup>
|
|
102
|
-
<Button label="
|
|
103
|
-
<Button label="
|
|
104
|
-
<Button label="
|
|
164
|
+
<ButtonGroup vertical={true}>
|
|
165
|
+
<Button label="Top" variant="primary" />
|
|
166
|
+
<Button label="Middle" variant="secondary" />
|
|
167
|
+
<Button label="Bottom" variant="success" />
|
|
105
168
|
</ButtonGroup>
|
|
106
169
|
),
|
|
107
170
|
};
|
|
108
171
|
|
|
109
|
-
|
|
110
|
-
export const SmallSize: Story = {
|
|
172
|
+
export const GroupWithSizes: Story = {
|
|
111
173
|
render: () => (
|
|
112
174
|
<ButtonGroup>
|
|
113
|
-
<Button label="Small" size="sm" />
|
|
114
|
-
<Button label="
|
|
115
|
-
<Button label="
|
|
175
|
+
<Button label="Small" variant="primary" size="sm" />
|
|
176
|
+
<Button label="Medium" variant="primary" size="md" />
|
|
177
|
+
<Button label="Large" variant="primary" size="lg" />
|
|
116
178
|
</ButtonGroup>
|
|
117
179
|
),
|
|
118
180
|
};
|
|
119
181
|
|
|
120
|
-
export const
|
|
121
|
-
render: () =>
|
|
122
|
-
|
|
123
|
-
<
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
182
|
+
export const GroupWithIcons: Story = {
|
|
183
|
+
render: () => {
|
|
184
|
+
const Icon = () => (
|
|
185
|
+
<svg
|
|
186
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
187
|
+
width="16"
|
|
188
|
+
height="16"
|
|
189
|
+
viewBox="0 0 24 24"
|
|
190
|
+
fill="none"
|
|
191
|
+
stroke="currentColor"
|
|
192
|
+
strokeWidth="2"
|
|
193
|
+
strokeLinecap="round"
|
|
194
|
+
strokeLinejoin="round"
|
|
195
|
+
>
|
|
196
|
+
<circle cx="12" cy="12" r="10" />
|
|
197
|
+
<path d="M12 8v4M12 16h.01" />
|
|
198
|
+
</svg>
|
|
199
|
+
);
|
|
129
200
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
// With Icons
|
|
141
|
-
export const WithIcons: Story = {
|
|
142
|
-
render: () => (
|
|
143
|
-
<ButtonGroup>
|
|
144
|
-
<Button label="Previous" iconName="ArrowLeft" iconPosition="start" />
|
|
145
|
-
<Button label="Next" iconName="ArrowRight" iconPosition="end" />
|
|
146
|
-
</ButtonGroup>
|
|
147
|
-
),
|
|
201
|
+
return (
|
|
202
|
+
<ButtonGroup>
|
|
203
|
+
<Button label="First" icon={<Icon />} variant="primary" />
|
|
204
|
+
<Button label="Second" icon={<Icon />} variant="secondary" />
|
|
205
|
+
<Button label="Third" icon={<Icon />} variant="success" />
|
|
206
|
+
</ButtonGroup>
|
|
207
|
+
);
|
|
208
|
+
},
|
|
148
209
|
};
|
|
149
210
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
<Button iconName="CaretLeft" iconOnly aria-label="Previous" />
|
|
154
|
-
<Button iconName="CaretRight" iconOnly aria-label="Next" />
|
|
155
|
-
</ButtonGroup>
|
|
156
|
-
),
|
|
157
|
-
};
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// INTEGRATION EXAMPLES
|
|
213
|
+
// ============================================================================
|
|
158
214
|
|
|
159
|
-
|
|
160
|
-
export const WithDisabled: Story = {
|
|
215
|
+
export const InFormIntegration: Story = {
|
|
161
216
|
render: () => (
|
|
162
|
-
<
|
|
163
|
-
<
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
217
|
+
<form className="u-flex u-flex-col u-gap-4">
|
|
218
|
+
<input
|
|
219
|
+
type="text"
|
|
220
|
+
placeholder="Username"
|
|
221
|
+
className="u-p-2 u-mb-2 u-border u-border-gray-300 u-rounded u-w-full"
|
|
222
|
+
/>
|
|
223
|
+
<input
|
|
224
|
+
type="password"
|
|
225
|
+
placeholder="Password"
|
|
226
|
+
className="u-p-2 u-mb-2 u-border u-border-gray-300 u-rounded u-w-full"
|
|
227
|
+
/>
|
|
228
|
+
<ButtonGroup className="u-justify-end">
|
|
229
|
+
<Button label="Cancel" variant="secondary" />
|
|
230
|
+
<Button label="Submit" variant="primary" />
|
|
231
|
+
</ButtonGroup>
|
|
232
|
+
</form>
|
|
167
233
|
),
|
|
168
234
|
};
|
|
169
235
|
|
|
170
|
-
export const
|
|
236
|
+
export const InCardIntegration: Story = {
|
|
171
237
|
render: () => (
|
|
172
|
-
<
|
|
173
|
-
<
|
|
174
|
-
<
|
|
175
|
-
<
|
|
176
|
-
|
|
238
|
+
<div className="u-p-6 u-bg-white u-rounded-lg u-shadow-lg u-w-80">
|
|
239
|
+
<h3 className="u-mt-0 u-mb-3">Confirm Action</h3>
|
|
240
|
+
<p className="u-mb-4">Are you sure you want to perform this action?</p>
|
|
241
|
+
<ButtonGroup>
|
|
242
|
+
<Button label="No" variant="secondary" size="sm" />
|
|
243
|
+
<Button label="Yes" variant="danger" size="sm" />
|
|
244
|
+
</ButtonGroup>
|
|
245
|
+
</div>
|
|
177
246
|
),
|
|
178
247
|
};
|
|
179
248
|
|
|
180
|
-
export const
|
|
249
|
+
export const WithOtherComponents: Story = {
|
|
181
250
|
render: () => (
|
|
182
|
-
<
|
|
183
|
-
<
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
251
|
+
<div className="u-flex u-flex-col u-gap-4 u-w-full">
|
|
252
|
+
<div className="u-flex u-items-center u-gap-2 u-mb-4">
|
|
253
|
+
<h4 className="u-m-0">Filters:</h4>
|
|
254
|
+
<ButtonGroup>
|
|
255
|
+
<Button label="All" variant="outline-primary" />
|
|
256
|
+
<Button label="Active" variant="outline-primary" />
|
|
257
|
+
<Button label="Inactive" variant="outline-primary" />
|
|
258
|
+
</ButtonGroup>
|
|
259
|
+
</div>
|
|
189
260
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
261
|
+
<div className="u-flex u-justify-between u-items-center">
|
|
262
|
+
<div className="u-text-sm u-text-gray-600">Showing 1-10 of 42 results</div>
|
|
263
|
+
<ButtonGroup>
|
|
264
|
+
<Button label="Prev" variant="outline-secondary" />
|
|
265
|
+
<Button label="Next" variant="outline-secondary" />
|
|
266
|
+
</ButtonGroup>
|
|
267
|
+
</div>
|
|
268
|
+
</div>
|
|
197
269
|
),
|
|
198
270
|
};
|
|
199
271
|
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
<ButtonGroup>
|
|
204
|
-
<Button label="Delete" variant="danger" />
|
|
205
|
-
<Button label="Edit" variant="warning" />
|
|
206
|
-
<Button label="View" variant="info" />
|
|
207
|
-
</ButtonGroup>
|
|
208
|
-
),
|
|
209
|
-
};
|
|
272
|
+
// ============================================================================
|
|
273
|
+
// RESPONSIVE EXAMPLES
|
|
274
|
+
// ============================================================================
|
|
210
275
|
|
|
211
|
-
export const
|
|
276
|
+
export const ResponsiveButtonGroup: Story = {
|
|
212
277
|
render: () => (
|
|
213
|
-
<
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
278
|
+
<div className="u-w-full">
|
|
279
|
+
<ButtonGroup className="u-flex-col md:u-flex-row u-gap-0">
|
|
280
|
+
<Button
|
|
281
|
+
label="Home"
|
|
282
|
+
variant="outline-primary"
|
|
283
|
+
className="u-w-full md:u-w-auto u-rounded-none md:u-rounded-l md:u-rounded-r-none"
|
|
284
|
+
/>
|
|
285
|
+
<Button
|
|
286
|
+
label="About"
|
|
287
|
+
variant="outline-primary"
|
|
288
|
+
className="u-w-full md:u-w-auto u-rounded-none"
|
|
289
|
+
/>
|
|
290
|
+
<Button
|
|
291
|
+
label="Services"
|
|
292
|
+
variant="outline-primary"
|
|
293
|
+
className="u-w-full md:u-w-auto u-rounded-none"
|
|
294
|
+
/>
|
|
295
|
+
<Button
|
|
296
|
+
label="Contact"
|
|
297
|
+
variant="outline-primary"
|
|
298
|
+
className="u-w-full md:u-w-auto u-rounded-none md:u-rounded-r md:u-rounded-l-none"
|
|
299
|
+
/>
|
|
300
|
+
</ButtonGroup>
|
|
301
|
+
</div>
|
|
219
302
|
),
|
|
220
303
|
};
|
|
221
304
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
<Button label="All" selected />
|
|
226
|
-
<Button label="Active" />
|
|
227
|
-
<Button label="Completed" />
|
|
228
|
-
</ButtonGroup>
|
|
229
|
-
),
|
|
230
|
-
};
|
|
305
|
+
// ============================================================================
|
|
306
|
+
// EDGE CASES
|
|
307
|
+
// ============================================================================
|
|
231
308
|
|
|
232
|
-
|
|
233
|
-
export const MultipleGroups: Story = {
|
|
309
|
+
export const LongText: Story = {
|
|
234
310
|
render: () => (
|
|
235
|
-
<div style={{
|
|
236
|
-
<ButtonGroup>
|
|
237
|
-
<Button label="Group 1 - Button 1" />
|
|
238
|
-
<Button label="Group 1 - Button 2" />
|
|
239
|
-
<Button label="Group 1 - Button 3" />
|
|
240
|
-
</ButtonGroup>
|
|
311
|
+
<div style={{ maxWidth: '400px' }}>
|
|
241
312
|
<ButtonGroup>
|
|
242
|
-
<Button label="
|
|
243
|
-
<Button label="
|
|
313
|
+
<Button label="Very Long Text Button" />
|
|
314
|
+
<Button label="Another Long Button Label" />
|
|
315
|
+
<Button label="Third Extra Long Label" />
|
|
244
316
|
</ButtonGroup>
|
|
245
317
|
</div>
|
|
246
318
|
),
|
|
319
|
+
parameters: {
|
|
320
|
+
docs: {
|
|
321
|
+
description: {
|
|
322
|
+
story: 'ButtonGroup with long text buttons.',
|
|
323
|
+
},
|
|
324
|
+
},
|
|
325
|
+
},
|
|
247
326
|
};
|
|
248
327
|
|
|
249
|
-
// Accessibility
|
|
250
|
-
export const WithAriaLabel: Story = {
|
|
251
|
-
render: () => (
|
|
252
|
-
<ButtonGroup aria-label="Navigation controls">
|
|
253
|
-
<Button label="Previous" />
|
|
254
|
-
<Button label="Next" />
|
|
255
|
-
</ButtonGroup>
|
|
256
|
-
),
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
// Custom Styling
|
|
260
|
-
export const CustomClassName: Story = {
|
|
261
|
-
render: () => (
|
|
262
|
-
<ButtonGroup className="custom-button-group">
|
|
263
|
-
<Button label="Custom" />
|
|
264
|
-
<Button label="Styled" />
|
|
265
|
-
<Button label="Group" />
|
|
266
|
-
</ButtonGroup>
|
|
267
|
-
),
|
|
268
|
-
};
|
|
269
|
-
|
|
270
|
-
// Edge Cases
|
|
271
328
|
export const SingleButton: Story = {
|
|
272
329
|
render: () => (
|
|
273
330
|
<ButtonGroup>
|
|
274
331
|
<Button label="Single Button" />
|
|
275
332
|
</ButtonGroup>
|
|
276
333
|
),
|
|
334
|
+
parameters: {
|
|
335
|
+
docs: {
|
|
336
|
+
description: {
|
|
337
|
+
story: 'ButtonGroup with a single button.',
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
},
|
|
277
341
|
};
|
|
278
342
|
|
|
279
|
-
export const
|
|
343
|
+
export const WithManyButtons: Story = {
|
|
280
344
|
render: () => (
|
|
281
345
|
<ButtonGroup>
|
|
282
|
-
<Button label="1" />
|
|
283
|
-
<Button label="2" />
|
|
284
|
-
<Button label="3" />
|
|
285
|
-
<Button label="4" />
|
|
286
|
-
<Button label="5" />
|
|
287
|
-
<Button label="6" />
|
|
346
|
+
<Button label="1" size="sm" />
|
|
347
|
+
<Button label="2" size="sm" />
|
|
348
|
+
<Button label="3" size="sm" />
|
|
349
|
+
<Button label="4" size="sm" />
|
|
350
|
+
<Button label="5" size="sm" />
|
|
351
|
+
<Button label="6" size="sm" />
|
|
352
|
+
<Button label="7" size="sm" />
|
|
353
|
+
<Button label="8" size="sm" />
|
|
354
|
+
<Button label="9" size="sm" />
|
|
355
|
+
<Button label="10" size="sm" />
|
|
288
356
|
</ButtonGroup>
|
|
289
357
|
),
|
|
358
|
+
parameters: {
|
|
359
|
+
docs: {
|
|
360
|
+
description: {
|
|
361
|
+
story: 'ButtonGroup with many buttons (using smaller size).',
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
},
|
|
290
365
|
};
|
|
291
366
|
|
|
292
|
-
//
|
|
293
|
-
|
|
367
|
+
// ============================================================================
|
|
368
|
+
// ACCESSIBILITY
|
|
369
|
+
// ============================================================================
|
|
370
|
+
|
|
371
|
+
export const WithAriaLabels: Story = {
|
|
294
372
|
render: () => (
|
|
295
|
-
<ButtonGroup>
|
|
296
|
-
<Button label="
|
|
297
|
-
<Button label="
|
|
298
|
-
<Button label="
|
|
373
|
+
<ButtonGroup aria-label="Pagination controls">
|
|
374
|
+
<Button label="Previous" aria-label="Go to previous page" />
|
|
375
|
+
<Button label="1" aria-label="Go to page 1" />
|
|
376
|
+
<Button label="2" aria-label="Go to page 2" />
|
|
377
|
+
<Button label="3" aria-label="Go to page 3" />
|
|
378
|
+
<Button label="Next" aria-label="Go to next page" />
|
|
299
379
|
</ButtonGroup>
|
|
300
380
|
),
|
|
381
|
+
parameters: {
|
|
382
|
+
docs: {
|
|
383
|
+
description: {
|
|
384
|
+
story: 'ButtonGroup with proper ARIA labels for accessibility.',
|
|
385
|
+
},
|
|
386
|
+
},
|
|
387
|
+
},
|
|
301
388
|
};
|
|
302
389
|
|
|
303
|
-
|
|
304
|
-
export const FullWidth: Story = {
|
|
390
|
+
export const VerticalLayout: Story = {
|
|
305
391
|
render: () => (
|
|
306
|
-
<div
|
|
307
|
-
<
|
|
308
|
-
<Button label="
|
|
309
|
-
<Button label="
|
|
310
|
-
<Button label="
|
|
311
|
-
</
|
|
392
|
+
<div className="u-flex u-flex-col u-gap-3">
|
|
393
|
+
<div className="u-flex u-flex-col u-gap-0 u-items-start">
|
|
394
|
+
<Button label="Button 1" variant="primary" className="u-w-full u-rounded-b-none" />
|
|
395
|
+
<Button label="Button 2" variant="secondary" className="u-w-full u-rounded-none" />
|
|
396
|
+
<Button label="Button 3" variant="outline-primary" className="u-w-full u-rounded-t-none" />
|
|
397
|
+
</div>
|
|
312
398
|
</div>
|
|
313
399
|
),
|
|
400
|
+
parameters: {
|
|
401
|
+
docs: {
|
|
402
|
+
description: {
|
|
403
|
+
story: 'Vertical layout using flex-direction column.',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
},
|
|
314
407
|
};
|
|
315
408
|
|
|
409
|
+
export const WithKeyboardNavigation: Story = {
|
|
410
|
+
render: () => {
|
|
411
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
412
|
+
|
|
413
|
+
const buttons = [
|
|
414
|
+
{ label: 'Button 1', variant: 'primary' },
|
|
415
|
+
{ label: 'Button 2', variant: 'secondary' },
|
|
416
|
+
{ label: 'Button 3', variant: 'outline-primary' },
|
|
417
|
+
{ label: 'Button 4', variant: 'success' },
|
|
418
|
+
];
|
|
419
|
+
|
|
420
|
+
const handleKeyDown = (index: number, e: React.KeyboardEvent) => {
|
|
421
|
+
let newIndex = index;
|
|
422
|
+
|
|
423
|
+
switch (e.key) {
|
|
424
|
+
case 'ArrowRight':
|
|
425
|
+
case 'ArrowDown':
|
|
426
|
+
newIndex = (index + 1) % buttons.length;
|
|
427
|
+
break;
|
|
428
|
+
case 'ArrowLeft':
|
|
429
|
+
case 'ArrowUp':
|
|
430
|
+
newIndex = (index - 1 + buttons.length) % buttons.length;
|
|
431
|
+
break;
|
|
432
|
+
case 'Home':
|
|
433
|
+
newIndex = 0;
|
|
434
|
+
break;
|
|
435
|
+
case 'End':
|
|
436
|
+
newIndex = buttons.length - 1;
|
|
437
|
+
break;
|
|
438
|
+
default:
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
e.preventDefault();
|
|
443
|
+
setActiveIndex(newIndex);
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
return (
|
|
447
|
+
<div className="u-flex u-flex-col u-gap-3">
|
|
448
|
+
<div className="u-flex u-gap-0">
|
|
449
|
+
{buttons.map((btn, idx) => (
|
|
450
|
+
<Button
|
|
451
|
+
key={idx}
|
|
452
|
+
label={btn.label}
|
|
453
|
+
variant={btn.variant}
|
|
454
|
+
active={activeIndex === idx}
|
|
455
|
+
onKeyDown={(e: React.KeyboardEvent) => handleKeyDown(idx, e)}
|
|
456
|
+
className={
|
|
457
|
+
idx === 0
|
|
458
|
+
? 'u-rounded-r-none'
|
|
459
|
+
: idx === buttons.length - 1
|
|
460
|
+
? 'u-rounded-l-none'
|
|
461
|
+
: 'u-rounded-none'
|
|
462
|
+
}
|
|
463
|
+
/>
|
|
464
|
+
))}
|
|
465
|
+
</div>
|
|
466
|
+
</div>
|
|
467
|
+
);
|
|
468
|
+
},
|
|
469
|
+
parameters: {
|
|
470
|
+
docs: {
|
|
471
|
+
description: {
|
|
472
|
+
story: 'Button group with keyboard navigation support using arrow keys.',
|
|
473
|
+
},
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
};
|