NUIv3.0.7

Resizable

A composable, accessible Resizable component for modern React applications.

tsx
import { Resizable } from '@nofinite/nui';

Interactive Preview

Drag handle to resize me

A layout primitive that enables users to resize adjacent panels via drag or keyboard interaction. It supports horizontal and vertical orientations, flexible panel constraints, and WAI-ARIA compliant separator behavior.

The component is composed of:

  • Resizable (root container)
  • Resizable.Panel
  • Resizable.Handle

Usage

Basic horizontal split

tsx
import { Resizable } from '@nofinite/nui';

export function Example() {
  return (
    <Resizable>
      <Resizable.Panel defaultSize={50}>Left</Resizable.Panel>
      <Resizable.Handle />
      <Resizable.Panel defaultSize={50}>Right</Resizable.Panel>
    </Resizable>
  );
}

Vertical split

tsx
<Resizable direction="vertical">
  <Resizable.Panel defaultSize={30}>Top</Resizable.Panel>
  <Resizable.Handle />
  <Resizable.Panel defaultSize={70}>Bottom</Resizable.Panel>
</Resizable>

With constraints

tsx
<Resizable>
  <Resizable.Panel minSize={20} maxSize={80} defaultSize={40} />
  <Resizable.Handle />
  <Resizable.Panel />
</Resizable>

With grip icon

tsx
<Resizable.Handle withIcon />

Layout change callback

tsx
<Resizable onLayout={(sizes) => console.log(sizes)} />


Resizable.Panel

PropTypeDefaultDescription
defaultSizenumberInitial flex grow percentage
minSizenumber0Minimum size percentage
maxSizenumber100Maximum size percentage
classNamestringAdditional class names

Resizable.Handle

PropTypeDefaultDescription
withIconbooleanfalseShows grip icon inside handle
classNamestring Additional class names

Variants

Direction

tsx
<Resizable direction="horizontal" />
<Resizable direction="vertical" />

Available variants

  • horizontal
  • vertical

Guidelines

  • Use horizontal for sidebars and split editors
  • Use vertical for stacked panes and dashboards
  • Prefer consistent orientation across a workspace

Handle visual variant

tsx
<Resizable.Handle />
<Resizable.Handle withIcon />

Available variants

  • default
  • withIcon

Guidelines

  • Use icon grip for discoverability
  • Use default for minimal UI
  • Prefer icon when drag affordance is unclear

States

  • Default
  • Hover (handle highlight)
  • Focus visible (keyboard)
  • Dragging
  • Constraint-limited resize
  • Keyboard resize
  • Orientation-dependent cursor

Keyboard Interaction

KeyBehavior
Arrow keysResize panels based on orientation
Shift + ArrowResize by 10% step
HomeMove toward minimum bound
EndMove toward maximum bound

Handles follow separator interaction pattern.


Accessibility

  • Uses role="separator" on handle
  • Orientation via aria-orientation
  • Dynamic aria-valuenow updates
  • Keyboard operable resizing
  • Focusable handle with visible focus ring
  • Pointer drag does not remove keyboard operability (manual focus restoration)


Best Practices

Do

  • Define min/max constraints for predictable layouts
  • Use icon grips in complex editors
  • Persist layout using onLayout
  • Ensure panels contain overflow-safe content
  • Use consistent panel sizing strategy

Don’t

  • Nest many resizable groups without performance consideration
  • Omit constraints in critical layouts
  • Place scroll containers directly on handles
  • Use vertical + horizontal nesting without UX clarity

API Reference

PropTypeDefaultDescription
directionenumhorizontalThe flex layout direction. Defaults to 'horizontal'.
onLayout((sizes: number[]) => void)Callback fired when the user completes a resize action, providing an array of panel sizes (percentages)