Patterns

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.).

Updated Aug 13, 2026 by Leonardo Posada

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

Section content (chart cards, tables, or any sub-blocks)
  1. 1
    Section 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.

  2. 2
    Header 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.

  3. 3
    Title

    <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).

  4. 4
    Actions 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.

  5. 5
    Caret 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.

  6. 6
    Content 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

Static (always open)

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

Always-visible section (Real time status on Health)
<SectionHeader title="Real time status" first collapsible={false}>
  {/* Section content — always visible, no caret */}
</SectionHeader>
Expandable (default)

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

Collapsible content — click the caret on the right to hide
<SectionHeader title="Fraud screening" first>
  {/* Section content — hidden when collapsed */}
</SectionHeader>
With actions slot

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

Section content with actions next to the title
<SectionHeader
  title="Approval rate by provider"
  first
  actions={
    <Button variant="outline" size="sm">
      <Funnel weight="light" />
      Filter
    </Button>
  }
>
  {/* Section content */}
</SectionHeader>
Multiple stacked sections

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

First section

3DS

Second section (mt-8 above)

Chargebacks

Third section (mt-8 above)
<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.

SectionHeader is a wrapper — it owns the header row + collapse behavior + content stacking. The section's inner content stacks with flex-col gap-6 (24px), so most consumers can just drop ChartCards / TableCards / any sub-blocks as direct children without adding their own outer container.
import { SectionHeader } from "@/components/patterns/section-header";

Props

Everything else is forwarded to the underlying elements via ...props.

PropTypeDefaultDescription
titlestring (required)Section title. Rendered as <Title as="h2">.
actionsReactNodeRight-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.
firstbooleanfalseWhen 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.
collapsiblebooleantrueWhen 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).
openbooleanControlled open state (only relevant when collapsible).
defaultOpenbooleantrueUncontrolled default open state. Section opens on mount by default.
onOpenChange(open: boolean) => voidFires when the open state toggles.
childrenReactNode (required)Content of the section. Sub-blocks stack with gap-6 (24px).
classNamestringExtra 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).