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.
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
<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.
Related
Resizable— Lower-level primitive for arbitrary splits.SplitContent— Static (non-resizable) two-column.SplitScrollContent— Two columns with independent scroll.