Skip to content

TwoColumnLayout

<TwoColumnLayout> is a desktop two-column shell with a resizable handle. Left for a tree / outline; right for the main content. On mobile (< md), the left collapses into a top-disclosure trigger.

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

When to use

  • Curriculum / hierarchical content where a tree on the left navigates the body.
  • Documentation viewers, code-editor-style layouts.
  • Any “navigation rail + reading area” pattern.

Don’t use TwoColumnLayout for: forms with side hints (use SplitContent), detail pages with right-side properties (use RightPanel), or layouts where both columns scroll independently (use SplitScrollContent).

Default

Curriculum
Module 1
Module 2 (active)
Module 3
Module 2 detail content…
<TwoColumnLayout
leftPanel={<CurriculumTree />}
showHandle
>
<ModuleDetail />
</TwoColumnLayout>

API

Prop Type Default Description
leftPanel * ReactNode Left column content — typically a tree or outline.
children * ReactNode Right column content.
defaultLeftPanelSize number 25 Initial left-panel width as percentage 0–100.
minLeftPanelSize number 15 Smallest the left panel can shrink to.
maxLeftPanelSize number 50 Largest the left panel can grow to.
showHandle boolean false Render a visible drag affordance on the resizer.
leftPanelClassName string Forwarded to the left column.
rightPanelClassName string Forwarded to the right column.
className string Forwarded to the root.

Design guidelines

✓ Do

  • Set showHandle=true so users can find the resizer. Without it, the affordance is invisible.
  • Default leftPanelSize=25–35% — the tree is reference, not the focus.
  • Use TwoColumnLayout when both panels are persistent. For overlay panels, use Sheet or RightPanel.

✗ Don't

  • Use TwoColumnLayout on mobile-first surfaces. The pattern is desktop-shaped.
  • Put forms on the right side. Forms want vertical space, not split screens.
  • Stack two TwoColumnLayouts. Use Resizable for nested splits.

Accessibility

  • Composes Resizable — the handle is a <button role="separator"> with arrow-key resize.
  • Mobile disclosure is a real <button> with aria-expanded.

▶ Open TwoColumnLayout stories in Storybook