Styling
Headless accordion exposes stable slot and state hooks on the root, item, trigger, and panel. Those hooks are the intended styling API for both CSS selectors and utility wrappers.
Slot and state hooks
| Selector | When it appears | Typical use |
|---|---|---|
[data-slot="accordion"] | Always on the root directive. | Shell border, radius, background, and group spacing. |
[data-type="single|multiple"] | Always on the root directive. | Mode-specific accents or density shifts. |
[data-slot="accordion-item"] | Always on each item. | Item separators and disabled section treatment. |
[data-slot="accordion-trigger"] | Always on the trigger. | Header layout, icon alignment, hover, and focus treatment. |
[data-slot="accordion-panel"] | Always on the panel host. | Panel padding, typography, and inner content layout. |
[data-state="open|closed"] | On item, trigger, and panel. | Chevron rotation, emphasized headers, or motion classes. |
[data-disabled="true|false"] | On root, item, and trigger. | Lower emphasis and blocked-pointer styling. |
[data-mounted="true|false"] | On the panel. | Differentiate lazy unmounted panels from closed-but-mounted panels. |
CSS starter
Headless accordion starter CSS
css
[data-slot="accordion"] {
border: 1px solid var(--tng-semantic-border-subtle);
border-radius: 1rem;
overflow: hidden;
}
[data-slot="accordion-trigger"] {
width: 100%;
text-align: left;
}
[data-slot="accordion-trigger"][data-state="open"] {
color: var(--tng-semantic-foreground-primary);
}
[data-slot="accordion-panel"][data-mounted="false"] {
display: none;
}
[data-slot="accordion-item"][data-disabled="true"] {
opacity: 0.55;
}
Practical guidance
- Put chevrons or status badges inside the trigger so they can react to
data-state. - Style panel inner layout separately from the panel host if you need complex grid or prose content.
- Use
data-mountedwhen lazy panels should skip expensive descendants until first open. - When using utility CSS, scope selectors to the wrapper around your accordion instead of the root itself.