AccordionItem represents a single expandable section within an Accordion. It composes an AccordionHeader (clickable trigger) and AccordionPanel (collapsible content) into a single component.
Basics
Each AccordionItem requires a unique itemKey to identify it within the parent Accordion, and a title for the header text. The children become the collapsible content.
<Accordion>
<AccordionItem itemKey="1" title="What is Coinbase?">
<Text as="p" font="body" color="fgMuted">
Coinbase is a secure online platform for buying, selling, transferring, and storing digital
currency.
</Text>
</AccordionItem>
</Accordion>
Title and Subtitle
Use the title prop for the main header text and subtitle for secondary information.
<Accordion>
<AccordionItem
itemKey="1"
title="Account Settings"
subtitle="Manage your profile, security, and preferences"
>
<VStack gap={2}>
<Text as="p" font="body" color="fgMuted">
Configure your account settings here.
</Text>
<Button variant="secondary" compact>
Edit profile
</Button>
</VStack>
</AccordionItem>
</Accordion>
Add icons, avatars, or other media to the header using the media prop. This commonly uses CellMedia for consistent styling.
<Accordion>
<AccordionItem
itemKey="1"
title="Bitcoin"
subtitle="BTC"
media={<CellMedia active type="icon" name="wallet" title="BTC" />}
>
<VStack gap={2}>
<HStack justifyContent="space-between">
<Text font="body" color="fgMuted">
Balance
</Text>
<Text font="body">0.5 BTC</Text>
</HStack>
<HStack justifyContent="space-between">
<Text font="body" color="fgMuted">
Value
</Text>
<Text font="body">$21,500.00</Text>
</HStack>
</VStack>
</AccordionItem>
</Accordion>
Click Handling
Use the onClick callback to respond when an item is clicked. It receives the itemKey as an argument.
function ClickExample() {
const [lastClicked, setLastClicked] = useState(null);
return (
<VStack gap={3}>
{lastClicked && (
<Text font="label2" color="fgMuted">
Last clicked: {lastClicked}
</Text>
)}
<Accordion>
<AccordionItem itemKey="first" title="First Item" onClick={(key) => setLastClicked(key)}>
<Text as="p" font="body" color="fgMuted">
Content for the first item.
</Text>
</AccordionItem>
<AccordionItem itemKey="second" title="Second Item" onClick={(key) => setLastClicked(key)}>
<Text as="p" font="body" color="fgMuted">
Content for the second item.
</Text>
</AccordionItem>
</Accordion>
</VStack>
);
}
Panel Content
Rich Content
AccordionItem children can contain any React content—forms, lists, buttons, or other components.
<Accordion>
<AccordionItem itemKey="1" title="Payment Details" subtitle="Enter your payment information">
<VStack gap={3}>
<TextInput compact label="Card Number" placeholder="1234 5678 9012 3456" />
<HStack gap={2}>
<Box flex={1}>
<TextInput compact label="Expiry" placeholder="MM/YY" />
</Box>
<Box flex={1}>
<TextInput compact label="CVV" placeholder="123" />
</Box>
</HStack>
<HStack gap={2} justifyContent="flex-end">
<Button variant="secondary">Cancel</Button>
<Button>Save Card</Button>
</HStack>
</VStack>
</AccordionItem>
</Accordion>
Max Height
Use maxHeight to limit the panel height for items with potentially long content. The content will scroll if it exceeds this height.
<Accordion defaultActiveKey="1">
<AccordionItem itemKey="1" title="Terms and Conditions" maxHeight={150}>
<VStack gap={2}>
<Text as="p" font="body" color="fgMuted">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut
labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi ut aliquip ex ea commodo consequat.
</Text>
<Text as="p" font="body" color="fgMuted">
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
mollit anim id est laborum.
</Text>
<Text as="p" font="body" color="fgMuted">
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque
laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi
architecto beatae vitae dicta sunt explicabo.
</Text>
</VStack>
</AccordionItem>
</Accordion>
Multiple Items
When using multiple AccordionItems, only one can be expanded at a time (controlled by the parent Accordion). Use defaultActiveKey on the Accordion to specify which item starts expanded.
<Accordion defaultActiveKey="faq-2">
<AccordionItem itemKey="faq-1" title="How do I get started?">
<Text as="p" font="body" color="fgMuted">
Download the app, create an account, and verify your identity to start trading.
</Text>
</AccordionItem>
<AccordionItem itemKey="faq-2" title="Is my crypto secure?">
<Text as="p" font="body" color="fgMuted">
Yes, we use industry-leading security measures including cold storage and two-factor
authentication to protect your assets.
</Text>
</AccordionItem>
<AccordionItem itemKey="faq-3" title="What are the fees?">
<Text as="p" font="body" color="fgMuted">
Fees vary based on your payment method and transaction size. See our pricing page for details.
</Text>
</AccordionItem>
</Accordion>
Accessibility
AccordionItem automatically provides accessible behavior:
- The header uses proper ARIA attributes (
aria-expanded, aria-controls)
- Content is wrapped in a
region role with aria-labelledby pointing to the header
- Full keyboard navigation is supported via the parent Accordion
For items with complex content, ensure any interactive elements inside the panel are keyboard accessible.
<Accordion>
<AccordionItem
itemKey="1"
title="Accessibility Settings"
subtitle="Customize your experience"
testID="accessibility-accordion"
>
<VStack gap={2}>
<Text as="p" font="body" color="fgMuted">
Adjust settings to make the app more accessible.
</Text>
<Button variant="secondary" compact accessibilityLabel="Open accessibility preferences">
Open Preferences
</Button>
</VStack>
</AccordionItem>
</Accordion>
Refs
Use headerRef and panelRef to get references to the header button and panel elements for programmatic focus management or measurements.
function RefExample() {
const headerRef = useRef(null);
const panelRef = useRef(null);
const focusHeader = useCallback(() => {
headerRef.current?.focus();
}, []);
return (
<Accordion>
<AccordionItem itemKey="1" title="Focusable Item" headerRef={headerRef} panelRef={panelRef}>
<Text as="p" font="body" color="fgMuted">
Panel content
</Text>
</AccordionItem>
</Accordion>
);
}