Accordion
Collapsible content panels using the native HTML <details> / <summary> elements, styled automatically by @primus/ui-core. No JavaScript required โ the browser handles open/close natively.
Codeโ
- HTML ยท @primus/ui-core
- React
- Angular
<!-- Basic accordion item -->
<details>
<summary>What is multi-tenancy?</summary>
<p>Multi-tenancy allows a single application to serve multiple customers...</p>
</details>
<!-- Open by default -->
<details open>
<summary>How is data isolated?</summary>
<p>Each tenant's data is isolated via row-level security...</p>
</details>
<!-- Grouped accordion (use CSS to connect borders) -->
<div style="border:1px solid var(--border);border-radius:8px;overflow:hidden">
<details style="border-bottom:1px solid var(--border)">
<summary style="padding:1rem 1.25rem">Question one</summary>
<div style="padding:0 1.25rem 1rem">Answer one</div>
</details>
<details style="border-bottom:1px solid var(--border)">
<summary style="padding:1rem 1.25rem">Question two</summary>
<div style="padding:0 1.25rem 1rem">Answer two</div>
</details>
<details>
<summary style="padding:1rem 1.25rem">Question three</summary>
<div style="padding:0 1.25rem 1rem">Answer three</div>
</details>
</div>
interface AccordionItem {
question: string;
answer: string;
defaultOpen?: boolean;
}
function Accordion({ items }: { items: AccordionItem[] }) {
return (
<div style={{ border: '1px solid var(--border)', borderRadius: 8, overflow: 'hidden' }}>
{items.map((item, i) => (
<details
key={i}
open={item.defaultOpen}
style={{ borderBottom: i < items.length - 1 ? '1px solid var(--border)' : 'none' }}
>
<summary style={{ padding: '1rem 1.25rem', fontWeight: 600, cursor: 'pointer' }}>
{item.question}
</summary>
<div style={{ padding: '0 1.25rem 1rem', color: 'var(--muted-foreground)' }}>
{item.answer}
</div>
</details>
))}
</div>
);
}
<!-- faq.component.html -->
<div style="border:1px solid var(--border);border-radius:8px;overflow:hidden">
<details
*ngFor="let item of faqItems; let last = last"
[open]="item.defaultOpen"
[style.border-bottom]="last ? 'none' : '1px solid var(--border)'">
<summary style="padding:1rem 1.25rem;font-weight:600;cursor:pointer">
{{ item.question }}
</summary>
<div style="padding:0 1.25rem 1rem;color:var(--muted-foreground)">
{{ item.answer }}
</div>
</details>
</div>
Propsโ
<details> and <summary> are native HTML elements โ no custom props. @primus/ui-core styles them automatically.
| Attribute | Element | Description |
|---|---|---|
open | <details> | Boolean โ panel is open by default |
| No attributes needed | <summary> | Styled automatically โ click to toggle |
Version history
See the Changelog for version history and breaking changes.