Action Group

An action group is a row of related action buttons that can collapse to an overflow menu when horizontal space is constrained.

Use it to surface a closely related set of bulk or context actions — formatting controls, view toggles, or shortcut commands — where the collection should be perceived as one logical unit. When space is tight, overflow items move into a menu behind a single trigger.

Example

ActionGroup
Show demo markup
<div class="action-group" aria-label="a group of action buttons that can collapse to an overflow menu when space is constrained">ActionGroup</div>
Usage example
<script lang="ts">
  import ActionGroup from './ActionGroup.svelte';

  let open = $state(false);
</script>

<ActionGroup
  label="Editing actions"
  overflowOpen={open}
  overflowLabel="More actions"
  onOverflowToggle={() => (open = !open)}
>
  <button type="button">Cut</button>
  <button type="button">Copy</button>
  <button type="button">Paste</button>

  {#snippet overflow()}
    <ul role="menu">
      <li role="menuitem"><button>Find</button></li>
      <li role="menuitem"><button>Replace</button></li>
    </ul>
  {/snippet}
</ActionGroup>
Show Svelte source
// In your Svelte component:
import ActionGroup from "lily-design-system-svelte-headless/components/ActionGroup/ActionGroup.svelte";

<ActionGroup>
  <!-- list children -->
</ActionGroup>

Usage

<ActionGroup
  label="Text formatting"
  overflowOpen={open}
  overflowLabel="More actions"
  onOverflowToggle={handleToggle}
  overflow={<Menu>...</Menu>}
>
  <Button label="Bold">B</Button>
  <Button label="Italic">I</Button>
  <Button label="Underline">U</Button>
</ActionGroup>

Props

  • label: string (required) -- aria-label for the group
  • overflowOpen: boolean (default false) -- whether the overflow menu is open
  • overflowLabel: string (optional) -- aria-label for the overflow button (e.g., "More actions")
  • onOverflowToggle / onoverflowtoggle: callback (optional) -- overflow trigger click handler
  • children: slot -- the visible action buttons
  • overflow: slot/snippet/ReactNode (optional) -- content for the overflow menu
  • ...restProps: any additional HTML attributes

Keyboard Interactions

  • Tab: Move focus into and out of the group
  • Arrow keys: (Consumer-provided) roving tabindex among action buttons is recommended
  • Enter / Space: Activate the focused action button or toggle the overflow menu
  • Escape: (Consumer-provided) close the overflow menu when open

ARIA

  • role="group" on the container
  • aria-label provides the accessible name (required)
  • Overflow trigger has aria-haspopup="menu" and aria-expanded
  • Overflow menu container is hidden via the hidden attribute when closed

When to Use

  • Use to group a small set of related actions that share context
  • Use when overflow behavior is needed for narrow viewports
  • Use to give a logical grouping its own accessible name

When Not to Use

  • Do not use for primary navigation — use a NavigationMenu or TabBar
  • Do not use for unrelated actions — they belong in separate groups or in a ToolBar
  • Do not use when only one or two actions are present and overflow is not needed

Composition

Action groups commonly contain Button, ToggleButton, or ActionBarButton children, and pair with a Menu for overflow content.

<ActionGroup label="Alignment" overflow={<Menu>...</Menu>}>
  <ToggleButton label="Left">L</ToggleButton>
  <ToggleButton label="Center">C</ToggleButton>
  <ToggleButton label="Right">R</ToggleButton>
</ActionGroup>

Headless

Renders a <div role="group"> with aria-label and optional overflow trigger plus overflow panel. Open/close state, positioning, animation, and visual treatment are entirely the consumer's responsibility.

Styles

Consumer CSS targets the action-group class. The overflow trigger uses action-group-overflow-trigger and the overflow menu uses action-group-overflow-menu. Provide a clear focus indicator on every interactive descendant.

Testing

  • Verify the component renders a <div> with role="group" and class action-group
  • Verify aria-label equals the label prop
  • Verify visible children are rendered before any overflow trigger
  • Verify the overflow trigger renders only when overflow is provided
  • Verify aria-expanded on the overflow trigger reflects overflowOpen
  • Verify the overflow panel uses hidden when overflowOpen is false
  • Verify onOverflowToggle fires when the overflow trigger is activated

Advice

  • Designers: Establish a clear primary-to-secondary order; promote the most-used actions and demote infrequent actions to the overflow menu.
  • Developers: Manage overflowOpen state in the consumer; close it on outside click and on Escape.

Implementation Notes

  • Uses a <div> with role="group" and a required aria-label
  • overflow is an optional slot/snippet/ReactNode for the overflow menu content (typically a Menu of hidden actions)
  • The overflow trigger button renders only when overflow is provided
  • The overflow trigger has aria-haspopup="menu" and reflects open state via aria-expanded
  • The overflow menu container uses the hidden attribute when closed
  • Visible action buttons are children — typically Button, ActionBarButton, or ToggleButton components

Related components

  • button-group — a wrapper that groups related buttons together
  • tool-bar — a horizontal bar of tool actions

References

  • WAI-ARIA Group: https://www.w3.org/TR/wai-aria-1.2/#group
  • Adobe Spectrum Action Group: https://spectrum.adobe.com/page/action-group/
  • WCAG 4.1.2 Name, Role, Value: https://www.w3.org/WAI/WCAG22/Understanding/name-role-value

Canonical contract

Generated from this component's canonical metadata — the machine-checked source the implementations are held to.

Metadata

  • Component: action-group
  • PascalCase: ActionGroup
  • Description: a group of action buttons that can collapse to an overflow menu when space is constrained
  • Status: beta — implemented and unit-tested in all seven frameworks with an axe-clean demo page; not yet exercised in composed flows
  • HTML tag: <div> with role="group"
  • CSS class: .action-group
  • Interactive: yes (when overflow is used)

ARIA

  • role="group" on the container
  • aria-label is the accessible name (required)
  • Overflow trigger: aria-haspopup="menu", aria-expanded, optional aria-label via overflowLabel
  • Overflow panel uses the hidden attribute when closed

Keyboard

  • Tab: Move focus into and out of the group
  • Arrow keys: (Consumer-provided) recommended roving tabindex among buttons
  • Enter / Space: Activate focused button or toggle overflow
  • Escape: (Consumer-provided) close the overflow menu when open

Props

  • label: string (REQUIRED) -- aria-label for the group
  • overflowOpen: boolean (default false)
  • overflowLabel: string (optional)
  • onOverflowToggle / onoverflowtoggle: callback (optional)
  • children: slot -- visible action buttons
  • overflow: slot/snippet/ReactNode (optional) -- overflow menu content
  • ...restProps: any additional HTML attributes