Skip to content

CollapsibleSection

<CollapsibleSection> is a titled page section with a built-in disclosure chevron. Each section’s open/closed state persists per route in localStorage so the user’s preference survives reloads.

import from "@na/ui/components/CollapsibleSection" ▶ Open in Storybook packages/ui/src/components/CollapsibleSection.tsx

When to use

  • Settings / detail pages with optional or advanced sub-sections that the user wants to keep collapsed.
  • Long forms where some sections are “skip on first read”.
  • Detail pages with sub-areas the user toggles per-task.

Don’t use CollapsibleSection for: critical state the user must see (just render it), top-level page titles (PageHeader), or simple titled groups without a disclosure (ContentSection).

Default

Required fields for every agent.
Form body…
<CollapsibleSection
sectionId="basics"
title="Basics"
description="Required fields for every agent."
>
…form rows…
</CollapsibleSection>
<CollapsibleSection
sectionId="advanced"
title="Advanced"
defaultOpen={false}
badge={<Badge variant="secondary">3</Badge>}
>
…optional knobs…
</CollapsibleSection>

API

Prop Type Default Description
sectionId * string Stable id, combined with the route to key localStorage. Each route keeps its own per-section state.
title * string Section title rendered next to the chevron.
description string Optional muted helper text below the title.
actions ReactNode Right-aligned actions next to the title row (Edit, Add).
badge ReactNode Trailing badge next to the title (counts, status).
defaultOpen boolean true Initial state when no persisted state exists.
open boolean Controlled open state — bypasses persistence.
onOpenChange (open: boolean) => void Fires on every toggle.

Design guidelines

✓ Do

  • Use sectionId verbosely — "agent-settings:advanced" beats "advanced". The id is part of the localStorage key.
  • defaultOpen={false} for sections most users skip; defaultOpen={true} (the default) for sections most users edit.
  • Pair with a count badge when the section's contents vary in size ("3 tools").

✗ Don't

  • Use CollapsibleSection to hide errors or warnings. The user will collapse them.
  • Override open/onOpenChange unless you need cross-component sync. Persistence handles single-section state for free.
  • Nest CollapsibleSections more than one level deep. The hierarchy collapses.

Accessibility

  • Built on Radix Collapsible — trigger is <button aria-expanded aria-controls>.
  • Animations respect prefers-reduced-motion.

▶ Open CollapsibleSection stories in Storybook