Accordion
Zero-jank dynamic height disclosure using CSS Grid 0fr to 1fr interpolation with morphing plus/minus icon and clean theme elevation.
Interactive Specification & Studio
Quick Start & Consumer Example
Copy-paste ready implementation for React (.tsx). Automatically updates when you modify parameters in the Workbench above.
import * as React from 'react';
import {
AccordionRoot,
AccordionItem,
AccordionTrigger,
AccordionContent,
} from './Accordion';
const FAQ_ITEMS = [
{
value: 'item-1',
question: 'How does Exhuma achieve zero-jank height transitions?',
answer: 'Exhuma uses CSS Grid row-interpolation from 0fr to 1fr. Unlike max-height approximations or continuous JS height measurements, this guarantees 120fps GPU compositing with zero layout thrashing or hitching.',
},
{
value: 'item-2',
question: 'Is it fully accessible and WCAG 2.1 AA compliant?',
answer: 'Yes. Full WAI-ARIA Accordion Pattern compliance is built-in: aria-expanded, aria-controls, aria-labelledby, region roles, inert panel states, and roving focus keyboard navigation (ArrowUp, ArrowDown, Home, End).',
},
{
value: 'item-3',
question: 'Can I customize the signature counter-rotating icon?',
answer: 'The icon uses kinetic dual-bar geometry with zero SVG or icon library dependencies. You can pass showIcon={false} or provide custom children to the trigger to customize its appearance.',
},
];
export function AccordionDemo() {
return (
<div className="w-full max-w-2xl mx-auto p-4">
<AccordionRoot
mode="single"
collapsible={true}
gap={12}
bordered={true}
shadow={true}
showNumbers={true}
showIcon={true}
duration={300}
defaultValue="item-1"
>
{FAQ_ITEMS.map((item) => (
<AccordionItem key={item.value} value={item.value}>
<AccordionTrigger>{item.question}</AccordionTrigger>
<AccordionContent>{item.answer}</AccordionContent>
</AccordionItem>
))}
</AccordionRoot>
</div>
);
}
Props & Configuration
Exhaustive parameter contract for Accordion. Validated in the live Studio workbench above and statically checked across all 13 ecosystem templates.
| Prop | Type | Default | Description |
|---|---|---|---|
mode | select | single | Single auto-collapses previous items; multiple allows independent toggles. |
collapsible | boolean | true | In single mode, allows closing the currently expanded item. |
gap | number | 12 | Spacing between accordion items. 0 forms a seamless connected panel. |
bordered | boolean | true | Render items with crisp theme borders and active accent rings. |
shadow | boolean | true | Apply subtle depth shadow and hover elevation. |
showNumbers | boolean | true | Display leading monospace index numbers (01, 02) before titles. |
showIcon | boolean | true | Signature dual-bar kinetic plus/minus counter-rotating icon. |
duration | number | 300 | CSS Grid height and icon rotation transition speed in milliseconds. |
Single auto-collapses previous items; multiple allows independent toggles.
In single mode, allows closing the currently expanded item.
Spacing between accordion items. 0 forms a seamless connected panel.
Render items with crisp theme borders and active accent rings.
Apply subtle depth shadow and hover elevation.
Display leading monospace index numbers (01, 02) before titles.
Signature dual-bar kinetic plus/minus counter-rotating icon.
CSS Grid height and icon rotation transition speed in milliseconds.
Component Source
Component source definition for React (.tsx). Toggle between the clean wrapper and the standalone ejected engine micro-kernel.
import * as React from 'react';
import {
Accordion as CoreAccordion,
AccordionRoot as CoreAccordionRoot,
AccordionItem as CoreAccordionItem,
AccordionTrigger as CoreAccordionTrigger,
AccordionIcon as CoreAccordionIcon,
AccordionContent as CoreAccordionContent,
type AccordionRootProps as CoreAccordionRootProps,
type AccordionItemProps as CoreAccordionItemProps,
type AccordionTriggerProps as CoreAccordionTriggerProps,
type AccordionIconProps as CoreAccordionIconProps,
type AccordionContentProps as CoreAccordionContentProps,
type AccordionMode,
} from '@exhuma/core';
import { clsx } from 'clsx';
export type { AccordionMode };
export interface AccordionRootProps extends CoreAccordionRootProps {
className?: string;
}
export const AccordionRoot = React.forwardRef<HTMLDivElement, AccordionRootProps>(
(
{
mode = 'single',
collapsible = true,
gap = 12,
bordered = true,
shadow = true,
showNumbers = true,
showIcon = true,
duration = 300,
className,
...props
},
ref
) => (
<CoreAccordionRoot
ref={ref}
mode={mode}
collapsible={collapsible}
gap={gap}
bordered={bordered}
shadow={shadow}
showNumbers={showNumbers}
showIcon={showIcon}
duration={duration}
className={clsx('w-full', className)}
{...props}
/>
)
);
AccordionRoot.displayName = 'AccordionRoot';
export interface AccordionItemProps extends CoreAccordionItemProps {
className?: string;
}
export const AccordionItem = React.forwardRef<HTMLDivElement, AccordionItemProps>(
({ className, ...props }, ref) => (
<CoreAccordionItem ref={ref} className={clsx(className)} {...props} />
)
);
AccordionItem.displayName = 'AccordionItem';
export interface AccordionTriggerProps extends CoreAccordionTriggerProps {
className?: string;
}
export const AccordionTrigger = React.forwardRef<HTMLButtonElement, AccordionTriggerProps>(
({ className, ...props }, ref) => (
<CoreAccordionTrigger ref={ref} className={clsx(className)} {...props} />
)
);
AccordionTrigger.displayName = 'AccordionTrigger';
export interface AccordionIconProps extends CoreAccordionIconProps {
className?: string;
}
export const AccordionIcon: React.FC<AccordionIconProps> = ({ className, ...props }) => (
<CoreAccordionIcon className={clsx(className)} {...props} />
);
AccordionIcon.displayName = 'AccordionIcon';
export interface AccordionContentProps extends CoreAccordionContentProps {
className?: string;
}
export const AccordionContent = React.forwardRef<HTMLDivElement, AccordionContentProps>(
({ className, ...props }, ref) => (
<CoreAccordionContent ref={ref} className={clsx(className)} {...props} />
)
);
AccordionContent.displayName = 'AccordionContent';
export const Accordion = {
Root: AccordionRoot,
Item: AccordionItem,
Trigger: AccordionTrigger,
Icon: AccordionIcon,
Content: AccordionContent,
};
export default Accordion;
Lifecycle Safety & Performance
Engineered for high-frequency user interactions with zero memory leaks.
Deterministic Cleanup
GPU Compositor Acceleration
will-change: transform without triggering browser layout recalculations.Accessibility Considerations
Fully compliant with WCAG guidelines and respects user motion preferences.
prefers-reduced-motion Support
prefers-reduced-motion: reduce enabled in their operating system, Exhuma components automatically disable 3D gyroscope tilt and spring animations, rendering static accessible content.