Phoundry UI

CollapsibleSection

Expandable/collapsible content section with a clickable header, optional icon, and extra action buttons. Supports both controlled and uncontrolled open state.

import { CollapsibleSection } from 'phoundry-ui';

Basic (Default Open)

Details

This content is visible by default.

Show code
<CollapsibleSection title="Details">
  <p>This content is visible by default.</p>
</CollapsibleSection>

Starting Closed

Advanced Settings
Show code
<CollapsibleSection title="Advanced Settings" defaultOpen={false}>
  <p>Hidden until expanded.</p>
</CollapsibleSection>

With Icon

Configuration

Section with a leading icon in the header.

Show code
<CollapsibleSection title="Configuration" icon={PhiIcons.edit}>
  <p>Section with a leading icon.</p>
</CollapsibleSection>

Header actions (extraButtons)

stopPropagation on the extra button wrapper keeps header toggles separate from actions.

Tasks
Show code
<CollapsibleSection
  title="Tasks"
  icon={PhiIcons.add}
  extraButtons={[
    {
      showWhenCollapsed: true,
      button: {
        variant: 'ghost',
        size: 'sm',
        icon: PhiIcons.add,
        iconOnly: true,
        title: 'Quick add',
        onclick: () => addTask(),
      },
    },
  ]}
>
  ...
</CollapsibleSection>

Controlled

Controlled

Externally controlled open state.

Show code
<script>
  let open = $state(true);
</script>

<button onclick={() => open = !open}>
  {open ? 'Collapse' : 'Expand'}
</button>

<CollapsibleSection title="Controlled" open={open} onToggle={() => open = !open}>
  <p>Externally controlled section.</p>
</CollapsibleSection>

Props

PropTypeDefaultDescription
title requiredstringHeader text.
defaultOpen booleantrueInitial open state (uncontrolled mode).
open booleanControlled open state — overrides internal state when provided.
onToggle () => voidCalled on toggle. When provided, component becomes fully controlled.
onOpenChange (open: boolean) => voidCalled with the new open state after toggle.
children requiredSnippetSection content.
icon stringIconify icon shown before the title.
extraButtons { button: ButtonProps; showWhenCollapsed: boolean }[]Small `Button` instances beside the chevron. `showWhenCollapsed` chooses visibility when the section is collapsed vs expanded.
contentPadding booleantrueApply default padding to the content area.
fullHeight booleanfalseStretch to fill parent height when open.

Usage tips

  • The header row uses role="button" with keyboard activation — ensure titles stay concise for screen readers.
  • Use uncontrolled mode (just defaultOpen) for simple cases; use open + onToggle for external control.
  • The extraButtons prop lets you add action buttons (e.g. “Add”, “Edit”) to the header row alongside the toggle.
  • Set contentPadding={false} when embedding full-bleed content like tables or lists.
  • Use fullHeight inside flex layouts where the section should stretch to fill remaining space.