import type { Meta, StoryObj } from '@storybook/web-components-vite'; import { html } from 'lit'; import './index.ts'; import type { USAButtonGroup } from './usa-button-group.js'; const meta: Meta = { title: 'Actions/Button Group', component: 'usa-button-group', parameters: { layout: 'padded', docs: { description: { component: ` The Button Group component groups related actions together with consistent spacing and styling. It supports both programmatic button configuration and slotted content for maximum flexibility. Features: - Multiple button variants (primary, secondary, outline, base) - Support for different button types (button, submit, reset) - Segmented group styling option - Individual button state management (disabled) - Custom event handling for user interactions - Form integration support `, }, }, }, argTypes: { type: { control: { type: 'select' }, options: ['default', 'segmented'], description: 'Button group layout style', }, buttons: { control: 'object', description: 'Array of button configurations', }, }, }; export default meta; type Story = StoryObj; // Basic button group examples export const Default: Story = { args: { type: 'default', buttons: [ { text: 'Primary Action', variant: 'primary', type: 'button' }, { text: 'Secondary Action', variant: 'secondary', type: 'button' }, { text: 'Cancel', variant: 'outline', type: 'button' }, ], }, }; export const Segmented: Story = { args: { type: 'segmented', activeIndex: 0, buttons: [ { text: 'View', type: 'button' }, { text: 'Edit', type: 'button' }, { text: 'Delete', type: 'button' }, ], }, render: (args) => html`

Interactive Segmented Button Group

Click buttons to switch between modes. The active button shows in filled style (primary), while inactive buttons show in outline style.

{ const { button, index } = e.detail; console.log(`Switched to: ${button.text} (index: ${index})`); }} >

How It Works:

  • Click any button to activate it
  • Active button displays in filled (primary) style
  • Other buttons display in outline style
  • Only one button can be active at a time
  • Perfect for view switchers, tabs, or mode selectors
`, }; export const AllVariants: Story = { args: { type: 'default', buttons: [ { text: 'Primary', variant: 'primary', type: 'button' }, { text: 'Secondary', variant: 'secondary', type: 'button' }, { text: 'Outline', variant: 'outline', type: 'button' }, { text: 'Base', variant: 'base', type: 'button' }, ], }, }; export const WithDisabled: Story = { args: { type: 'default', buttons: [ { text: 'Save', variant: 'primary', type: 'button' }, { text: 'Save Draft', variant: 'secondary', type: 'button' }, { text: 'Preview', variant: 'outline', type: 'button', disabled: true }, { text: 'Cancel', variant: 'base', type: 'button' }, ], }, }; // Form integration example export const FormActions: Story = { args: { type: 'default', buttons: [ { text: 'Submit', variant: 'primary', type: 'submit' }, { text: 'Save Draft', variant: 'secondary', type: 'button' }, { text: 'Clear Form', variant: 'outline', type: 'reset' }, ], }, render: (args) => html`

Sample Form

{ const { button } = e.detail; console.log('Form action:', button.text, 'Type:', button.type); if (button.type === 'submit') { e.preventDefault(); // Prevent actual form submission for demo alert('Form submitted! (Demo mode)'); } else if (button.type === 'reset') { if (confirm('Are you sure you want to clear the form?')) { alert('Form cleared'); } else { e.preventDefault(); } } else { alert(`${button.text} clicked`); } }} >

Form Integration: This example shows how button groups work within forms with submit, reset, and save draft functionality.

`, }; // Layout and styling examples export const LayoutComparison: Story = { parameters: { controls: { disable: true }, // Static demo - no interactive controls needed }, render: () => html`

Default Layout

Segmented Layout

Layout Differences:

  • Default: Standard spacing between buttons
  • Segmented: Connected buttons with shared borders
`, }; export const InteractiveDemo: Story = { args: { type: 'default', buttons: [ { text: 'Action 1', variant: 'primary', type: 'button' }, { text: 'Action 2', variant: 'secondary', type: 'button' }, { text: 'Action 3', variant: 'outline', type: 'button' }, { text: 'Disabled', variant: 'base', type: 'button', disabled: true }, ], }, render: (args) => html`

Try clicking the buttons! Each button dispatches a custom event with details about the clicked button.

{ const { button, index } = e.detail; console.log('Button clicked:', { button, index }); if (button.disabled) { alert('This button is disabled'); return; } alert( `Clicked: "${button.text}" (Index: ${index}, Variant: ${button.variant}, Type: ${button.type})` ); }} >

Event Details:

Each button click fires a button-click event with:

  • button: Complete button configuration object
  • index: Button position in the array

Check the browser console for full event data.

`, }; export const CustomContent: Story = { parameters: { controls: { disable: true }, // Static demo - no interactive controls needed }, render: () => html`

Using Custom Content

  • Custom Content vs Programmatic:

    The button group supports both approaches:

    • Programmatic: Use the buttons property for data-driven buttons
    • Custom Content: Use the default slot for complete control over HTML structure

    Note: Programmatic buttons take precedence when both are present.

    `, }; export const AccessibilityDemo: Story = { args: { type: 'default', buttons: [ { text: 'Accessible Action', variant: 'primary', type: 'button' }, { text: 'Secondary Action', variant: 'secondary', type: 'button' }, { text: 'Disabled Action', variant: 'outline', type: 'button', disabled: true }, ], }, render: (args) => html`

    Accessibility Features:

    • Semantic Structure: Uses proper list markup with button elements
    • Keyboard Navigation: Tab through buttons, Space/Enter to activate
    • Screen Reader Support: Proper button semantics and disabled state
    • Focus Management: Clear visual focus indicators

    Test: Use Tab key to navigate between buttons, then Space or Enter to activate.

    `, }; export const ComplexConfiguration: Story = { parameters: { controls: { disable: true }, // Static demo - no interactive controls needed }, render: () => html`

    Complex Button Configuration

    console.log('Custom click handler for submit'), }, { text: 'Save Draft', variant: 'secondary', type: 'button', onclick: () => console.log('Custom click handler for draft'), }, { text: 'Preview', variant: 'outline', type: 'button', disabled: true, }, { text: 'Cancel', variant: 'base', type: 'button', onclick: () => console.log('Custom click handler for cancel'), }, ]} @button-click=${(e: CustomEvent) => { const { button, index } = e.detail; console.log(`Global handler: ${button.text} at index ${index}`); }} >

    Advanced Features Demonstrated:

    • Multiple button types (submit, button)
    • All button variants (primary, secondary, outline, base)
    • Individual onclick handlers + global event handler
    • Mixed enabled/disabled states

    Note: Both individual onclick handlers and global button-click events are fired.

    `, }; export const MobileFriendly: Story = { args: { type: 'default', buttons: [ { text: 'Submit', variant: 'primary', type: 'button' }, { text: 'Save', variant: 'secondary', type: 'button' }, { text: 'Cancel', variant: 'outline', type: 'button' }, ], }, render: (args) => html`

    Mobile Device Simulation

    Button groups adapt to mobile layouts

    Mobile Considerations:

    • Touch-friendly button sizes
    • Adequate spacing for finger taps
    • Responsive button text
    `, };