Accordion

Divide content into collapsible sections
Import

Usage

Colors, fonts, shadows and many other parts are customizable to fit your design needs
Radius
xs
sm
md
lg
xl
ChevronPosition
import { Accordion } from '@mantine/core';
function Demo() {
return (
<Accordion defaultValue="customization">
<Accordion.Item value="customization">
<Accordion.Control>Customization</Accordion.Control>
<Accordion.Panel>Colors, fonts, shadows and many other parts are customizable to fit your design needs</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="flexibility">
<Accordion.Control>Flexibility</Accordion.Control>
<Accordion.Panel>Configure components appearance and behavior with vast amount of settings or overwrite any part of component styles</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="focus-ring">
<Accordion.Control>No annoying focus ring</Accordion.Control>
<Accordion.Panel>With new :focus-visible pseudo-class focus ring appears only when user navigates with keyboard</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
}

Custom control label

Change chevron

import { Accordion } from '@mantine/core';
import { IconPlus } from '@tabler/icons-react';
function Demo() {
return (
<Accordion
chevron={<IconPlus size="1rem" />}
styles={{
chevron: {
'&[data-rotate]': {
transform: 'rotate(45deg)',
},
},
}}
>
{/* ... content */}
</Accordion>
);
}

With icons

Change transition

To change transition duration, set transitionDuration prop:

import { Accordion } from '@mantine/core';
function Demo() {
return (
<Accordion transitionDuration={1000}>
{/* ...content */}
</Accordion>
)
}

To disable transitions, set transitionDuration to 0:

import { Accordion } from '@mantine/core';
function Demo() {
return (
<Accordion transitionDuration={0}>
{/* ...content */}
</Accordion>
)
}

Default opened items

When multiple={false}, set defaultValue as string:

import { Accordion } from '@mantine/core';
function Demo() {
// Second item will be opened by default
return (
<Accordion defaultValue="item-2">
<Accordion.Item value="item-1">
<Accordion.Control>control-1</Accordion.Control>
<Accordion.Panel>panel-1</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="item-2">
<Accordion.Control>control-2</Accordion.Control>
<Accordion.Panel>panel-2</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
}

When multiple={true}, set defaultValue as an array of strings:

import { Accordion } from '@mantine/core';
function Demo() {
// Both items will be opened by default
return (
<Accordion multiple defaultValue={['item-1', 'item-2']}>
<Accordion.Item value="item-1">
<Accordion.Control>control-1</Accordion.Control>
<Accordion.Panel>panel-1</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="item-2">
<Accordion.Control>control-2</Accordion.Control>
<Accordion.Panel>panel-2</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
}

Control state

When multiple={false}, set value as string:

import { useState } from 'react';
import { Accordion } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<string | null>(null);
return (
<Accordion value={value} onChange={setValue}>
<Accordion.Item value="item-1">
<Accordion.Control>control-1</Accordion.Control>
<Accordion.Panel>panel-1</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="item-2">
<Accordion.Control>control-2</Accordion.Control>
<Accordion.Panel>panel-2</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
}

When multiple={true}, set value as an array of strings:

import { useState } from 'react';
import { Accordion } from '@mantine/core';
function Demo() {
const [value, setValue] = useState<string[]>([]);
return (
<Accordion multiple value={value} onChange={setValue}>
<Accordion.Item value="item-1">
<Accordion.Control>control-1</Accordion.Control>
<Accordion.Panel>panel-1</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="item-2">
<Accordion.Control>control-2</Accordion.Control>
<Accordion.Panel>panel-2</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
}

Compose controls

You can add any additional elements that will be displayed next to Accordion.Control, for example, you can add ActionIcon or Menu:

import { Accordion, ActionIcon, AccordionControlProps, Box } from '@mantine/core';
import { IconDots } from '@tabler/icons-react';
function AccordionControl(props: AccordionControlProps) {
return (
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<Accordion.Control {...props} />
<ActionIcon size="lg">
<IconDots size="1rem" />
</ActionIcon>
</Box>
);
}
function Demo() {
return (
<Accordion chevronPosition="left" maw={400} mx="auto">
<Accordion.Item value="item-1">
<AccordionControl>Control 1</AccordionControl>
<Accordion.Panel>Panel 1</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="item-2">
<AccordionControl>Control 2</AccordionControl>
<Accordion.Panel>Panel 2</Accordion.Panel>
</Accordion.Item>
<Accordion.Item value="item-3">
<AccordionControl>Control 3</AccordionControl>
<Accordion.Panel>Panel 3</Accordion.Panel>
</Accordion.Item>
</Accordion>
);
}

Disabled items

Set disabled prop on Accordion.Control component to disable it. Disabled items cannot be activated with mouse or keyboard, will be skipped when user navigates with arrow keys:

Unstyled Accordion

Set unstyled prop on Accordion component to remove all non-essential library styles. It can be used to style component with Styles API without overriding any styles.

Styles API

Use Styles API to customize Accordion styles:

Colors, fonts, shadows and many other parts are customizable to fit your design needs

Data attributes

Accordion elements have data- attributes that can be used with Styles API:

  • data-active attribute is added to Accordion.Item root element when associated panel is expanded
  • data-rotate attribute is added to chevron icon when icon should rotate (controlled by disableChevronRotation and expanded state of associated panel)
import { Accordion, rem } from '@mantine/core';
function Demo() {
return (
<Accordion
styles={{
item: {
// styles added to all items
backgroundColor: '#fff',
border: `${rem(1)} solid #ededed`,
// styles added to expanded item
'&[data-active]': {
backgroundColor: '#ccc',
},
},
chevron: {
// styles added to chevron when it should rotate
'&[data-rotate]': {
transform: 'rotate(-90deg)',
},
},
}}
>
{/* ... Accordion items */}
</Accordion>
);
}

TypeScript

AccordionProps type exported from @mantine/core is a generic, it accepts boolean type that describes multiple state:

import type { AccordionProps } from '@mantine/core';
type MultipleAccordionProps = AccordionProps<true>;
type DefaultAccordionProps = AccordionProps<false>;

Accessibility

Accordion component follows WAI-ARIA recommendations on accessibility.

Notes

Set order on Accordion component to wrap accordion controls with h2-h6 heading. The following example will wrap controls with h3 tag:

import { Accordion } from '@mantine/core';
function Demo() {
return <Accordion order={3}>{/* ...items */}</Accordion>;
}

Keyboard interactions

KeyDescription
ArrowDownMoves focus to next item
ArrowUpMoves focus to previous item
HomeMoves focus to first item
EndMoves focus to last item
Space/EnterToggles focused item opened state

Accordion component props

NameTypeDescription
chevron
ReactNode
Replaces chevron on all items
chevronPosition
"left" | "right"
Determines position of the chevron
chevronSize
string | number
Chevron size
children *
ReactNode
Accordion content
defaultValue
string | string[]
Default value for uncontrolled component
disableChevronRotation
boolean
Determines whether chevron rotation should be disabled
id
string
Base id, used to generate ids that connect labels with controls, by default generated randomly
loop
boolean
Determines whether arrow key presses should loop though items (first to last and last to first)
multiple
boolean
Determines whether multiple items can be opened at a time
onChange
(value: AccordionValue<Multiple>) => void
Callback for controlled component
order
2 | 3 | 4 | 5 | 6
Heading order, has no effect on visuals
radius
number | "xs" | "sm" | "md" | "lg" | "xl"
Key of theme.radius or any valid CSS value to set border-radius, ignored when variant="default"
transitionDuration
number
Transition duration in ms, set 0 to disable transitions
value
string | string[]
Value for controlled component
variant
"default" | "contained" | "filled" | "separated"
Controls visuals

AccordionControl component props

NameTypeDescription
chevron
ReactNode
Custom chevron icon
children
ReactNode
Control label
disabled
boolean
Disables control button
icon
ReactNode
Icon rendered next to label

AccordionItem component props

NameTypeDescription
value *
string
Value that is used to manage accordion state

AccordionPanel component props

NameTypeDescription
children
ReactNode
Panel content

Accordion component Styles API

NameStatic selectorDescription
item.mantine-Accordion-itemAccordion item wrapper
itemTitle.mantine-Accordion-itemTitleOptional heading element wrapping control
control.mantine-Accordion-controlControl root
label.mantine-Accordion-labelControl label
icon.mantine-Accordion-iconControl icon
chevron.mantine-Accordion-chevronControl chevron icon
panel.mantine-Accordion-panelPanel root
content.mantine-Accordion-contentPanel content