HyAccordion
Usage examples on this page are written for Lit / plain HTML (
<hy-accordion>). The same component ships asHyAccordionin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
An accordion component using CSS Grid animation for smooth expand/collapse transitions.
CSS Grid Animation Approach
This implementation uses CSS Grid's grid-template-rows property to create smooth expand/collapse animations:
- Collapsed State:
grid-template-rows: 0fr(zero height) - Expanded State:
grid-template-rows: 1fr(content height) - Browser Handled: Height calculations are managed by the browser
- Content Adaptive: Automatically adjusts when content changes
- Clean Implementation: No JavaScript height measurements required
Technical Benefits
- Eliminates need for ResizeObserver height tracking
- No manual animation frame management
- Automatic content size adaptation
- Smooth CSS transitions
- Reduced code complexity
Accessibility Features
- Full keyboard navigation (Enter/Space to toggle, Tab to focus)
- ARIA live regions for screen reader announcements
- Proper ARIA attributes and relationships
- High contrast mode support
- Reduced motion support with instant transitions
- Visible focus indicators
Browser Compatibility
CSS Grid animation is supported in:
- Chrome 57+ (March 2017)
- Firefox 52+ (March 2017)
- Safari 10.1+ (March 2017)
- Edge 16+ (October 2017)
Examples
Basic Usage
<hy-accordion title="Settings" expanded>
<p>Configure your application settings here.</p>
</hy-accordion>Flat / borderless presentation (emphasis="plain")
<hy-accordion emphasis="plain" title="Neutral">
<p>
Chromeless header — no box, no border, no radius. Add a `border-block-end` rule consumer-side
for a section divider.
</p>
</hy-accordion>With All Features
<hy-accordion
title="Email Settings"
subtitle="Configure notifications and preferences"
optional-text="Last updated today"
prefix-icon-name="mail"
size="medium"
announce-state-changes="true"
animation-duration="400"
>
<div>
<h3>Notification Settings</h3>
<p>Choose how you want to receive notifications.</p>
</div>
</hy-accordion>Custom Header with Slots
<hy-accordion size="large">
<div slot="header">
<strong>Project Status</strong>
<small style="color: green; margin-left: 0.5em;">âœ" Complete</small>
</div>
<hy-icon slot="expand-icon" name="keyboard-arrow-down"></hy-icon>
<p>Project details and completion information.</p>
</hy-accordion>Programmatic Control
<hy-accordion id="myAccordion" title="API Example">
<p>Content that can be controlled via JavaScript.</p>
</hy-accordion>
<script>
const accordion = document.getElementById('myAccordion');
// Listen for state changes
accordion.addEventListener('toggle', (e) => {
console.log('State changed:', e.detail.expanded);
});
// Programmatic control
accordion.expand(); // Expand with animation
accordion.collapse(); // Collapse with animation
accordion.toggle(); // Toggle current state
</script>Custom Animation Timing
You can customize animation via CSS custom properties:
hy-accordion {
--hy-accordion-expand-duration: 500ms;
--hy-accordion-expand-easing: cubic-bezier(0.25, 0.46, 0.45, 0.94);
}API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
headerId | header-id | string | '' | Auto-generated unique identifier for the header button element. Used to establish ARIA relationships between header and content. |
contentId | content-id | string | '' | Auto-generated unique identifier for the content region element. Used to establish ARIA relationships between header and content. |
title | title | string | 'Accordion Title' | The primary title text displayed in the accordion header. Appears alongside prefix and optional text, properly aligned with the expand/collapse icon. Ignored when the header slot is used. |
subtitle | subtitle | string | '' | Secondary descriptive text displayed below the main title. Provides additional context with smaller, lighter typography. Only shown when no header slot content is provided. |
optionalText | optional-text | string | '' | Brief supplementary text displayed after the main title. Useful for status indicators, timestamps, or brief metadata. Uses smaller, muted styling and prevents line wrapping. |
size | size | 'small' | 'medium' | 'large' | 'medium' | Size variant that controls typography, spacing, and visual hierarchy. - small: Compact presentation with reduced spacing - medium: Standard size for most use cases (default) - large: Prominent display with increased spacing |
emphasis | emphasis | 'solid' | 'outlined' | 'tinted' | 'plain' | 'solid' | Visual chrome weight — solid (default) / outlined / tinted / plain. - solid: surface fill + border + radius (the historic baseline — unchanged) - outlined: transparent fill, keep the border - tinted: subtle surface fill, no border - plain: chromeless (no fill, no border) — the flat / borderless presentation (industry "ghost" / "flush"); add a border-block-end rule consumer-side for a section divider. |
expanded | expanded | boolean | false | Whether the accordion is currently expanded (content visible) or collapsed (content hidden). Changes trigger CSS Grid-based animations. Reflected as an attribute for CSS styling and external state queries. |
disabled | disabled | boolean | false | Disables all accordion interactions and applies disabled styling. When disabled, interactions are prevented and visual styling indicates disabled state. |
animationDuration | animation-duration | number | 300 | Duration in milliseconds for CSS Grid expand/collapse animations. Controls the transition speed of the grid-template-rows animation. |
prefixIconName | prefix-icon-name | string | undefined | — | Icon name for the prefix indicator displayed before the title. Only shown when the prefix slot is not used and this property has a value. |
iconName | icon-name | string | 'chevron-down' | Icon name for the default expand/collapse indicator. The icon automatically rotates 180 degrees when the accordion expands. Ignored when the icon slot contains custom content. |
announceStateChanges | announce-state-changes | boolean | true | Whether to announce state changes to screen readers via ARIA live regions. Uses optimized timing for compatibility with different screen readers. |
announcementPriority | announcement-priority | 'polite' | 'assertive' | 'polite' | ARIA live region politeness level for screen reader announcements. - polite: Announcements wait for current reading to complete (recommended) - assertive: Announcements interrupt current reading |
Events
| Event | Detail | Description |
|---|---|---|
toggle | — | Fired when the accordion state changes (expand or collapse). Detail: { expanded: boolean } |
expand | — | Fired specifically when the accordion expands. Detail: { expanded: boolean } |
collapse | — | Fired specifically when the accordion collapses. Detail: { expanded: boolean } |
transition-end | — | Fired when the CSS Grid animation completes. Detail: { expanded: boolean } |
Slots
| Slot | Description |
|---|---|
default | The main content displayed when the accordion is expanded |
prefix | Custom prefix content that overrides the prefix-icon-name property |
header | Custom header content that overrides title, subtitle, and optional-text properties |
expand-icon | Custom expand/collapse indicator that overrides the icon-name property |
CSS Parts
| Part | Description |
|---|---|
base | The accordion's root container element |
header | The clickable header button element |
title | The title area container (present only when the header slot is used) |
prefix | The prefix icon container (only present when prefix content exists) |
icon | The expand/collapse icon container |
content | The CSS Grid animated content container |
live-region | The ARIA live region for screen reader announcements (visually hidden) |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-accordion-border-default-rest | Border color at rest |
--hy-accordion-border-subtle-rest | Subtle border color |
--hy-accordion-stroke | Border width |
--hy-accordion-radius | Border radius (all four corners) |
--hy-accordion-radius-top-start | Top-start corner radius override. Defaults to --hy-radius-row-list-md-top-start; cascades through --hy-accordion-radius so a single radius override still shapes all four corners. |
--hy-accordion-radius-top-end | Top-end corner radius override. See top-start. |
--hy-accordion-radius-bottom-start | Bottom-start corner radius override. See top-start. |
--hy-accordion-radius-bottom-end | Bottom-end corner radius override. See top-start. |
--hy-accordion-padding-header-block | Header block padding |
--hy-accordion-padding-inline | Inline padding |
--hy-accordion-gap-size-sm | Gap for small size |
--hy-accordion-gap-size-md | Gap for medium size |
--hy-accordion-gap-size-lg | Gap for large size |
--hy-accordion-header-gap | Gap between header elements |
--hy-accordion-text-transform | Text transform for accordion title |
--hy-accordion-expand-duration | Transition duration for the expand/collapse panel animation |
--hy-accordion-expand-easing | Transition easing for the expand/collapse panel animation |
Methods
toggle()
Toggles the accordion between expanded and collapsed states. Triggers CSS Grid animation and appropriate events.
expand()
Expands the accordion to show its content. Uses CSS Grid animation for smooth transition.
collapse()
Collapses the accordion to hide its content. Uses CSS Grid animation for smooth transition.
focus()
Sets focus on the accordion header button for keyboard navigation.
blur()
Removes focus from the accordion header button.