Section header
The canonical section divider inside a Dashboard page. A wrapper that owns section-to-section rhythm (mt-8 = 32px, or `first` to skip it), the header row (<Title as="h2"> + optional actions slot with a mb-6 gap to content), the sub-block stacking inside (flex-col gap-6), and — by default — collapse behavior via the kit Collapsible atom. Two visible shapes: Static (`collapsible={false}` — no caret, content always renders) and Expandable (default — caret trigger + Collapsible around children). Deliberately Dashboard-wide, not chart-card-scoped: the same rhythm applies to any page that divides content into named sections (Health, Fraud, Settings, Risks, etc.).
Anatomy
A <section> element with `mt-8` above it (skipped when `first`), wrapping an optional Collapsible. The header row is a flex justify-between with <Title as="h2"> on the left and an actions cluster on the right; a mb-6 (24px) gap separates it from the content. Inside the content area, sub-blocks stack with flex-col gap-6 (24px). In the expandable shape, a ghost icon Button holding a CaretDown sits at the far right and rotates 180° when collapsed.
Fraud screening
- 1Section wrapper
The outer <section>. Adds mt-8 (32px) above by default; pass `first` on the very first section of a page to skip that margin so it hugs the FilterRow / PageHeader above.
- 2Header row
flex items-center justify-between gap-3 mb-6. Owns the horizontal spacing between title, actions, and (in the expandable shape) the caret trigger. Anchors the visual weight of the section.
- 3Title
<Title as="h2"> on the left. Semantic heading at the section level (below the PageHeader h1 and above the ChartCard h3s inside the content area).
- 4Actions slot
Optional right-side ReactNode next to the title. Canonical: outline / ghost icon Buttons, a filter Select, a small link Button. In the collapsible shape, actions sit BEFORE the caret trigger so the caret stays as the last affordance.
- 5Caret trigger (expandable only)
Ghost icon Button holding a Phosphor CaretDown (weight light). Rotates 180° when the section is collapsed. Toggles the Collapsible; aria-label announces Expand / Collapse dynamically.
- 6Content area
flex flex-col gap-6 (24px between sub-blocks). In the expandable shape, wrapped in CollapsibleContent so it shows / hides on the trigger; in the static shape, always visible.
Recipes
Pass `collapsible={false}` for sections that must always be visible without user action. Canonical case: the Real time status section at the top of the Health tab — data the merchant needs on landing, no reason to hide it. Also useful for page-hero blocks that anchor the top of a settings page.
Real time status
<SectionHeader title="Real time status" first collapsible={false}>
{/* Section content — always visible, no caret */}
</SectionHeader>The default shape. A caret trigger appears on the right of the header; clicking it toggles a Collapsible around the content. Use on dense pages where the user might want to hide sections they don't need right now to reduce scroll (Fraud → Fraud screening / 3DS / Chargebacks, Health → Providers / Yuno).
Fraud screening
<SectionHeader title="Fraud screening" first>
{/* Section content — hidden when collapsed */}
</SectionHeader>Pass `actions` for a right-side cluster next to the title — a Filter Button, a segmented ToggleGroup, a small link, a DropdownMenu. Works with both shapes; in the expandable shape, actions render BEFORE the caret so the caret stays as the last affordance on the far right.
Approval rate by provider
<SectionHeader
title="Approval rate by provider"
first
actions={
<Button variant="outline" size="sm">
<Funnel weight="light" />
Filter
</Button>
}
>
{/* Section content */}
</SectionHeader>The pattern owns section-to-section spacing (`mt-8` = 32px). Compose several one after the other; the first gets `first` to hug the FilterRow / PageHeader above, the rest automatically pick up the 32px gap.
Fraud screening
3DS
Chargebacks
<SectionHeader title="Fraud screening" first>
{/* First section — no top margin */}
</SectionHeader>
<SectionHeader title="3DS">
{/* Second section — mt-8 (32px) automatic */}
</SectionHeader>
<SectionHeader title="Chargebacks">
{/* Third section */}
</SectionHeader>Import
Copy this import line at the top of the file where you compose this molecule.
import { SectionHeader } from "@/components/patterns/section-header";Props
Everything else is forwarded to the underlying elements via ...props.
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string (required) | — | Section title. Rendered as <Title as="h2">. |
| actions | ReactNode | — | Right-side actions slot next to the title. Canonical shapes: outline / ghost icon Buttons, a filter Select, or a small link Button. In the collapsible shape, actions sit BEFORE the caret trigger. |
| first | boolean | false | When true, the section skips its top margin (mt-8). Use on the very first section of a page so it hugs the FilterRow / PageHeader above. |
| collapsible | boolean | true | When true (default), renders the caret trigger + wraps children in a Collapsible. Set to false for sections that must always be open (Real time status on Health, page-hero blocks). |
| open | boolean | — | Controlled open state (only relevant when collapsible). |
| defaultOpen | boolean | true | Uncontrolled default open state. Section opens on mount by default. |
| onOpenChange | (open: boolean) => void | — | Fires when the open state toggles. |
| children | ReactNode (required) | — | Content of the section. Sub-blocks stack with gap-6 (24px). |
| className | string | — | Extra classes on the outer <section>. |
Related
Cross-links to the atoms this molecule composes and sibling patterns.
- CollapsibleThe primitive that powers the expandable shape. Use it directly if you need a collapse behavior that isn't a page section.
- TitleThe header uses <Title as="h2">. If you just need a section title with no wrapping / no collapse, drop Title directly.
- Page headerSibling — the page-level header above SectionHeader (h1 vs h2 semantics).