A collapsible is a row that opens and closes to show more content, used for FAQ lists and filters. The header can carry a descriptive text, icons, a toggle switch and a number badge. The content animates open.
Tokens, sizes, measurements, states and requirements. Values come from the live token package and from Figma: Base / Collapsible.
Resolved from the live token package.
| State | Part | Token | Value |
|---|
Two sizes. Large changes at 769px, Small has the same values at every breakpoint.
| Part | Large | Small |
|---|---|---|
| Header height | Minimum 72px | Minimum 56px |
| Header padding | 24px top and bottom | 16px top and bottom |
| Gap, text to the right group | 16px | 16px |
| Gap, icon to text | 8px | 8px |
| Gap, title to descriptive text | 2px | 2px |
| Leading and trailing icon, chevron | 24px | 20px |
| Toggle switch | 48 × 24px (Large) | 32 × 16px (X-Small) |
| Number badge | badge-number--md: 20px desktop, 18px mobile | badge-number--sm: 16px desktop, 14px mobile |
| Line under the row | 1px | 1px |
| Open row, space below the content | 32px | 32px |
| Header text to content text | 24px (header padding 24px) | 24px (header padding 16px + 8px) |
| Boxed: body padding | 24px on all sides | 16px on all sides |
| Filled: content top | 24px between the grey header and the content text | 16px between the grey header and the content text |
| Part | Value |
|---|---|
| Frame | 1px border-primary around the row |
| Header padding | 24px on all sides (Large), 16px (Small) |
| Open: header | No background of its own (grey only with the Header background option), with a 1px line under it (an inset shadow, so it takes no space) |
| Open: body | White (background-primary), padding 24px (Large) or 16px (Small) on all sides, on desktop and mobile, 12px between the parts |
The header uses min-height, not height, so it can grow when the title wraps.
Padding of the header at each size. The shaded areas are the padding. The numbers are read from the real component.
| Attribute | Value |
|---|---|
| Padding, Large | 24px top and bottom, none at the sides |
| Padding, Small | 16px top and bottom, none at the sides |
| Padding, Boxed | 24px on all sides (Large), 16px (Small) |
| Minimum height | 72px (Large and Boxed Large), 56px (Small and Boxed Small) |
| Gap, text to right group | 16px |
| Gap, icon to text | 8px |
| Header text to content text | 24px in every size (--co-content-gap); boxed: header padding plus body padding, 48px (Large) or 32px (Small) |
| Open row, space below the content | 32px (Boxed: none, the body has 24px or 16px padding) |
| Line | 1px |
| Corners | Square |
The same distances as spacing tokens.
| Part | Value |
|---|---|
| Padding, Large | space-24 |
| Padding, Boxed Large | space-24 |
| Padding, Small and Boxed Small | space-16 |
| Gap, text to right group | space-16 |
| Gap, icon to text | space-8 |
| Open row, space below | space-32 |
| Checkbox list: gap, bottom | space-24, space-24 |
| Header text to content text | space-24 in every size; boxed: 48px / 32px |
The title, the descriptive text, the icons and the chevron turn to the action hover color (dark theme: the title, the descriptive text and the icons dim, the helper text does not). An open row turns the chevron 180° and adds 32px of space below. Hover is forced on this page; in your code it comes from :hover.
| State | Closed | Open |
|---|
Disabled is defined once in Figma, under Theme Dark, with the disabled text color and the light line (border-primary). Here it is shown on both themes. Focus: a 2px ring on keyboard focus (border-focus).
| Element | Token | Mobile | Desktop (769px+) | Color |
|---|---|---|---|---|
| Title, Large | title-md, weight 600 | 18/22, 0 | 20/24, 0 | text-primary, hover text-action-primary-hover |
| Descriptive text, Large | regular, same size as the title | 18/24, 0 | 20/24, 0 | same as the title |
| Title, Small | title-sm, weight 600 | 16/18, 0 | 16/18, 0 | same as the title |
| Descriptive text, Small | body-md, weight 400 | 16/22, 0.32px | 17/24, 0.32px | same as the title |
| Helper text | body-sm, weight 400 | 14/20, 0.36px | 14/20, 0.36px | text-secondary, hover text-tertiary; dark text-primary-inverted (no hover change) |
| Content | body-md, weight 400 | 16/22, 0.32px | 17/24, 0.32px | text-primary; 12px between paragraphs |
| Note under a list | body-sm | 14/20, 0.36px | 14/20, 0.36px | text-tertiary |
| Count beside a checkbox | 16/22 | 16/22, 0.32px | 16/22, 0.32px | text-tertiary |
| “Show more” | body-md, weight 600 | 16/22, 0.32px | 17/24, 0.32px | text-primary, underlined on hover |
Breuer Condensed. The CSS weight is Figma minus 100.
| Element | Class | Notes |
|---|---|---|
| Row | collapsible-wrap | One row, with the line under it. --open when open; --small, --boxed, --filled, --divider-top, --divider-bottom, --no-divider-bottom, --dark, --disabled are modifiers. |
| Header | collapsible-item | A <button> (recommended). The older <div onclick> still works. Not a button when it holds a switch. |
| Left group | collapsible-item__left | The icon, the text and the trailing icon. |
| Text group | collapsible-item__text, __line | Title and descriptive text on one line, helper text under it. Optional. |
| Title | collapsible-item__label | Bold. |
| Descriptive text | collapsible-item__info | Regular, after the title. |
| Helper text | collapsible-item__helper | Optional. |
| Right group | collapsible-item__end | The switch, the badge and the chevron. |
| Chevron | collapsible-item__chevron | An expand_more icon (ms). Leave it out for a row that does not open. |
| Content | collapsible-item__content | Must follow the header directly: the script reads nextElementSibling. |
| Boxed body | collapsible-item__body | Inside the content of a boxed row. |
| Content patterns | collapsible-item__list, __row, __count, __support, __note, __more | A checkbox list with counts, supporting text and a “Show more” action. |
| Type | Markup | Use |
|---|---|---|
| Large | Default | FAQ lists and page sections. |
| Small | collapsible-wrap--small | Dense layouts such as filters. |
| Boxed | collapsible-wrap--boxed (Large), collapsible-wrap--small collapsible-wrap--boxed (Small) | A framed row. The header is grey only with --filled. |
| Top divider | collapsible-wrap--divider-top | A 1px line above the row (off by default). |
| No bottom divider | collapsible-wrap--no-divider-bottom | Removes the line under the row (on by default). |
| Bottom divider forced | collapsible-wrap--divider-bottom | Keeps the line under the last row in a section, for example a section with one collapsible. |
| Filled | collapsible-wrap--filled | A surface-raised-secondary background on the header. The content stays white. |
| Dark | collapsible-wrap--dark | On a black surface. |
| Disabled | collapsible-wrap--disabled and disabled on the button | A row that cannot be opened. |
As wide as the container.
| Property | Duration | Easing |
|---|---|---|
Content max-height | duration-fast-4 (200ms), set through --co-duration | ease-standard, set through --co-ease |
Chevron transform | the same | the same |
Row padding-bottom | the same | the same |
Title, text and icon color on hover | duration-fast-3 (150ms) | ease-standard |
Opening is a state change on the spot, so it uses standard easing and a short duration (eco-motion). With prefers-reduced-motion: reduce every transition is off. Compare other values in the live Motion section on Examples & Guidelines.
| Input | Result |
|---|---|
| Click the header, Enter or Space | toggleCollapsible(this) toggles .collapsible-wrap--open, sets aria-expanded and sets max-height to the content’s scrollHeight. CSS cannot animate to auto. |
| Click the toggle switch | Changes the switch only. A click on a link or on an element with data-collapsible-ignore in the header does the same. |
| Hover | Title, text and icons change color. |
| Disabled | No hover, no click, no Tab. |
| Several rows | Independent: opening one does not close another. |
| Breakpoint | Large changes size at 769px. |
| Window resize while open | Open point. The height is set once, when the row opens. If the text wraps differently after a resize, the height is not updated. |
| Topic | Requirement |
|---|---|
| Header element | Use a button, so it is reached with Tab and works with Enter and Space (WCAG 2.1.1, 4.1.2). Older pages still use a div with onclick: it cannot take focus. |
| State | Set aria-expanded on the header; the script keeps it in sync. Link it to the content with aria-controls. |
| Switch in the header | A button cannot hold another control. A row with a toggle switch uses a div and has no chevron, or the switch moves out of the header. Open point: Figma shows a switch and a chevron together. |
| Focus | A 2px ring on keyboard focus (border-focus), 2px outside the header. |
| Content | Closed content is visibility: hidden, so it is not read and cannot be focused. |
| Contrast | The disabled text color is exempt (WCAG 1.4.3). Helper text and counts use text-tertiary (4.5:1 on white). |
| Motion | Reduced motion: all transitions are off. |