Accordion
A collapsible content panel for organizing information in a compact space
Usage
import { Accordion } from '@lenso/ui';"use client";
import { ArrowsRotateLeft, Box, ChevronDown, CreditCard, PlanetEarth, Receipt, ShoppingBag,} from "@gravity-ui/icons";import { Accordion } from "@lenso/ui";import * as stylex from "@stylexjs/stylex";
const styles = stylex.create({ root: { width: "100%", maxWidth: 448 }, icon: { width: 16, height: 16, flexShrink: 0, marginInlineEnd: 12, color: "var(--muted)" },});const items = [ { title: "How do I place an order?", Icon: ShoppingBag, content: "Browse our products, add items to your cart, and proceed to checkout. You'll need to provide shipping and payment information to complete your purchase.", }, { title: "Can I modify or cancel my order?", Icon: Receipt, content: "Yes, you can modify or cancel your order before it's shipped. Once your order is processed, you can't make changes.", }, { title: "What payment methods do you accept?", Icon: CreditCard, content: "We accept all major credit cards, including Visa, Mastercard, and American Express.", }, { title: "How much does shipping cost?", Icon: Box, content: "Shipping costs vary based on your location and the size of your order. We offer free shipping for orders over $50.", }, { title: "Do you ship internationally?", Icon: PlanetEarth, content: "Yes, we ship to most countries. Please check our shipping rates and policies for more information.", }, { title: "How do I request a refund?", Icon: ArrowsRotateLeft, content: "If you're not satisfied with your purchase, you can request a refund within 30 days of purchase. Please contact our customer support team for assistance.", },];export function Basic() { return ( <Accordion xstyle={styles.root}> {items.map(({ title, content, Icon }) => ( <Accordion.Item key={title} value={title}> <Accordion.Heading> <Accordion.Trigger> <Icon aria-hidden="true" {...stylex.props(styles.icon)} /> {title} <Accordion.Indicator> <ChevronDown /> </Accordion.Indicator> </Accordion.Trigger> </Accordion.Heading> <Accordion.Panel> <Accordion.Body>{content}</Accordion.Body> </Accordion.Panel> </Accordion.Item> ))} </Accordion> );}Local adaptation source above. Derived from HeroUI v3.2.6 source.
Anatomy
import { Accordion } from '@lenso/ui';
export default () => ( <Accordion> <Accordion.Item> <Accordion.Heading> <Accordion.Trigger> <Accordion.Indicator /> </Accordion.Trigger> </Accordion.Heading> <Accordion.Panel> <Accordion.Body/> </Accordion.Panel> </Accordion.Item> </Accordion>)Examples
Surface
"use client";export { Surface } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Without Separator
"use client";export { WithoutSeparator } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Multiple Expanded
"use client";export { Multiple } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Disabled State
"use client";export { Disabled } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Controlled
"use client";export { Controlled } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Custom Indicator
"use client";export { CustomIndicator } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Render Function
"use client";export { RenderFunction } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
FAQ Layout
"use client";export { FAQ } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Customization
Tailwind CSS
"use client";export { CustomStyles } from "./source";Local adaptation source above. Derived from HeroUI v3.2.6 source.
Global CSS
To customize the Accordion component classes, you can use the @layer components directive.
Learn more.
@layer components { .accordion { @apply rounded-xl bg-gray-50; }
.accordion__trigger { @apply font-semibold text-lg; }
.accordion--outline { @apply shadow-lg border-2; }}Styling Reference
HeroUI follows the BEM methodology to ensure component variants and states are reusable and easy to customize.
CSS Classes
The Accordion component uses these CSS classes (View source styles):
Base Classes [!toc]
.accordion- Base accordion container.accordion__body- Content body container.accordion__heading- Heading wrapper.accordion__indicator- Expand/collapse indicator icon.accordion__item- Individual accordion item.accordion__panel- Collapsible panel container.accordion__trigger- Clickable trigger button
Variant Classes [!toc]
.accordion--outline- Outline variant with border and background
State Classes [!toc]
.accordion__trigger[aria-expanded="true"]- Expanded state.accordion__panel[aria-hidden="false"]- Panel visible state
Interactive States
The component supports both CSS pseudo-classes and data attributes for flexibility:
- Hover:
:hoveror[data-hovered="true"]on trigger - Focus:
:focus-visibleor[data-focus-visible="true"]on trigger - Disabled:
:disabledor[aria-disabled="true"]on trigger - Expanded:
[aria-expanded="true"]on trigger
API Reference
Accordion
| Prop | Type | Default | Description |
|---|---|---|---|
allowsMultipleExpanded | boolean | false | Whether multiple items can be expanded at once |
defaultExpandedKeys | Iterable<Key> | - | The initial expanded keys |
expandedKeys | Iterable<Key> | - | The controlled expanded keys |
onExpandedChange | (keys: Set<Key>) => void | - | Handler called when expanded keys change |
isDisabled | boolean | false | Whether the entire accordion is disabled |
variant | "default" | "surface" | "default" | The visual variant of the accordion |
hideSeparator | boolean | false | Hide separator lines between accordion items |
className | string | - | Additional CSS classes |
children | ReactNode | - | The accordion items |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, AccordionRenderProps> | - | Overrides the default DOM element with a custom render function. |
Accordion.Item
| Prop | Type | Default | Description |
|---|---|---|---|
id | Key | - | Unique identifier for the item |
isDisabled | boolean | false | Whether this item is disabled |
defaultExpanded | boolean | false | Whether item is initially expanded |
isExpanded | boolean | - | Controlled expanded state |
onExpandedChange | (isExpanded: boolean) => void | - | Handler for expanded state changes |
className | string | - | Additional CSS classes |
children | ReactNode | - | The item content |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, AccordionItemRenderProps> | - | Overrides the default DOM element with a custom render function. |
Accordion.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | RenderFunction | - | Trigger content or render function |
onPress | () => void | - | Additional press handler |
isDisabled | boolean | - | Whether trigger is disabled |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, TriggerRenderProps> | - | Overrides the default DOM element with a custom render function. |
Accordion.Panel
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | - | Panel content |
render | DOMRenderFunction<keyof React.JSX.IntrinsicElements, AccordionPanelRenderProps> | - | Overrides the default DOM element with a custom render function. |
Accordion.Indicator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | - | Custom indicator icon |
Accordion.Body
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional CSS classes |
children | ReactNode | - | Body content |