Resizable
Resizable panel layouts with accessible handles for dashboards.
Overview
Resizable wraps react-resizable-panels with Vinyaas styling for sidebars, split editors, and stacked dashboard panes. Prefer percentage strings for sizes ("30%").
Use orientation="horizontal" for side-by-side panels and orientation="vertical" for stacked panels. Nest groups when a pane needs its own axis — for example an explorer beside an editor/terminal split.
Handles stay visually thin with an expanded hit target. Single-axis cursors follow separator orientation; when horizontal and vertical handles cross, the library shows a two-dimensional resize cursor. Install with vinyaas add resizable or via vinyaas add --catalog dashboard.
Preview
Customize
Installation
Add the component with the CLI. It copies the files in and installs anything they depend on.
npx vinyaas add resizableUsage
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable";
export function Workspace() {
return (
<ResizablePanelGroup orientation="horizontal" className="min-h-[240px] rounded-md border">
<ResizablePanel defaultSize="30%" minSize="20%">
<div className="p-4">Sidebar</div>
</ResizablePanel>
<ResizableHandle withHandle aria-label="Resize sidebar" />
<ResizablePanel defaultSize="70%">
<div className="p-4">Main</div>
</ResizablePanel>
</ResizablePanelGroup>
);
}Examples
Horizontal split
Sidebar + content. Horizontal resize uses a padded 2×3 secondary grip; drag or focus and use arrow keys.
Vertical split
Editor above terminal. Vertical resize uses the same 2×3 grip rotated 90°.
Separate blocks
variant="blocks" turns each panel into its own bordered block with a small gutter between them. The gutter is the drag target; add withHandle to mark it with a three-dot grip, which rotates for vertical groups.
Dashboard
Sidebar navigation with a main column: header card, metrics, and scrollable content. Uses Card, Badge, Button, Separator, and Scroll Area.
Workspace
LiveResize the sidebar. Arrow keys work when the handle is focused.
Active projects
Open issues
In practice
Prefer nested groups when a pane needs its own axis. Label every handle and set minSize so panels stay usable. IDE and editor shells usually omit withHandle — keep the divider thin.
Explorer
Terminal
API
Other attributes for the underlying element are passed through.
| Name | Type | Default | Description |
|---|---|---|---|
orientation | "horizontal" | "vertical" | "horizontal" | ResizablePanelGroup layout axis. Matches ARIA orientation conventions. |
defaultSize / minSize / maxSize | number | string | — | Panel size constraints from react-resizable-panels. Prefer percentage strings such as "30%". |
variant | "default" | "blocks" | "default" | ResizablePanelGroup: default splits one surface with a thin line. blocks renders each panel as its own bordered block with a small gutter, which is the drag target. |
withHandle | boolean | false | ResizableHandle: show a visible grip affordance — the dot grip in a default group, the three-dot grip in the blocks gutter. |
aria-label | string | — | ResizableHandle: accessible name for the separator when panels are unlabeled. |
disabled | boolean | — | Group or Handle: disables resize interaction for that surface. |
disableCursor | boolean | false | Group: turn off library cursor management. Leave false so crossing handles can show a 2D resize cursor. |
Accessibility
Handles render as ARIA separators from react-resizable-panels. Focus a handle and use arrow keys to resize. There is no keyboard trap around the handle.
- Provide an
aria-labelon eachResizableHandlewhen neighboring panels are not otherwise named. - Focused handles show a visible
focus-visiblering. disabledmarks the handlearia-disabledand dims pointer interaction.- Hit targets stay larger than the visible bar via a centered
::afterregion; the library also enforces a minimum resize target size for fine and coarse pointers. - Leave
disableCursorunset so crossing horizontal and vertical handles can announce a 2D resize affordance. - Non-essential motion respects
prefers-reduced-motionviamotion-reduce:transition-none.