NUIv3.0.7

Drawer

A composable, accessible Drawer component for modern React applications.

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

Interactive Preview


A controlled overlay panel that slides from an edge of the viewport. Implements focus trapping, scroll locking, inert background handling, escape key support, and animated mount/unmount lifecycle.


Usage

Basic (Right side)

tsx
import { Drawer } from '@nofinite/nui';
const [open, setOpen] = useState(false);

<>
  <button onClick={() => setOpen(true)}>Open</button>
  <Drawer open={open} onClose={() => setOpen(false)}>
    Drawer content
  </Drawer>
</>;

Left position

tsx
<Drawer open={open} onClose={close} position="left">
  Sidebar content
</Drawer>

Bottom sheet

tsx
<Drawer open={open} onClose={close} position="bottom">
  Mobile sheet content
</Drawer>

Disable Escape + Outside click

tsx
<Drawer open={open} onClose={close} disableEsc disableClickOutside>
  Forced interaction
</Drawer>


Subcomponents

None exposed.


Variants

Drawer supports structural and behavioral variants.

tsx
<Drawer position="right" />
<Drawer position="left" />
<Drawer position="top" />
<Drawer position="bottom" />
<Drawer disableEsc />
<Drawer disableClickOutside />

Available variants:

  • right (default)
  • left
  • top
  • bottom
  • escape-disabled
  • outside-click-disabled

Guidelines:

  • Use right/left for navigation or contextual panels
  • Use bottom for mobile sheet patterns
  • Avoid disabling both escape and outside click unless required by workflow

Sizes

Drawer width/height is position-dependent:

PositionDefault Dimension
left/rightmax-width: 320px
top/bottommin-height: 250px, max-height: 90vh

Width/height should be customized via className and layout utilities.


Shapes / Modes

Positions

  • Left
  • Right
  • Top
  • Bottom

States

  • Mounted (in DOM)
  • Visible (animated open)
  • Closed (animated exit)
  • Escape-triggered close
  • Outside-click close
  • Scroll-locked background
  • Focus-trapped
  • Inert-applied siblings

Z-index stack:

  • Overlay: 9998
  • Drawer: 9999

Overlay uses backdrop blur + 0.5 opacity.


Accessibility

Implemented behavior:

  • role="dialog"
  • aria-modal="true"
  • Focus trapped while open
  • Previous focus restored on close
  • Escape key close (configurable)
  • Background content inert while open
  • Scroll lock applied to body
  • Click outside detection (configurable)
  • prefers-reduced-motion respected

Note: Overlay is aria-hidden="true" because it is non-interactive.


Animation Model

Two-phase state system:

  • isMounted → Controls DOM presence
  • isVisible → Controls CSS transition state

Exit animation delay: 300ms
Entrance delay before activation: ~15ms (transition trigger)

Uses GPU-accelerated transform transitions.


Best practices

Do

  • Control open state from parent
  • Use semantic heading inside drawer
  • Provide a visible close button
  • Keep drawer width constrained

Don’t

  • Use Drawer for full-screen modal (use Modal)
  • Disable escape without strong reason
  • Mount heavy trees inside if frequent toggling
  • Stack multiple drawers without z-index management

API Reference

PropTypeDefaultDescription
open*booleanControls the open/closed state of the drawer
onClose*() => voidCallback fired when the drawer requests to be closed (e.g., Escape key, outside click)
positionenumrightThe edge of the screen the drawer attaches to. Defaults to 'right'
disableEscbooleanfalsePrevents the drawer from closing when the Escape key is pressed
disableClickOutsidebooleanfalsePrevents the drawer from closing when a click occurs outside the content area
overlayClassNamestringCustom class name applied to the backdrop overlay
titleReactNodeOptional title displayed at the top of the Drawer
descriptionReactNodeOptional description displayed below the title
hideCloseButtonbooleanfalseIf true, hides the default close 'X' button
transitionDurationnumber0.3Transition duration in seconds. Defaults to 0.3