Fluxo UIFluxo UIv0.4.93

Drawer

A slide-in panel component with four positions, focus trapping, backdrop, and customizable header/footer.

Basic Usage

Default Drawer

A right-side drawer with header and close button.

import { Drawer, Button } from 'fluxo-ui';

const [open, setOpen] = useState(false);

<Button onClick={() => setOpen(true)}>Open Drawer</Button>

<Drawer
  open={open}
  onClose={() => setOpen(false)}
  header="Drawer Title"
>
  <p>Drawer body content goes here.</p>
</Drawer>

Positions

Use the position prop to slide the drawer in from any edge.

Drawer Positions

Drawers can slide in from any edge: left, right, top, or bottom.

import { Drawer } from 'fluxo-ui';
import type { DrawerPosition } from 'fluxo-ui';

<Drawer open={open} onClose={close} position="left" header="Left Drawer">
  ...
</Drawer>

<Drawer open={open} onClose={close} position="top" header="Top Drawer" size="300px">
  ...
</Drawer>

<Drawer open={open} onClose={close} position="bottom" header="Bottom Drawer" size="300px">
  ...
</Drawer>

Bottom Sheet

Set variant="sheet" with position="bottom" (or "top") to get a drag handle, rounded corners, snap points, and drag-to-dismiss — ideal for mobile flows.

Snap points

A bottom sheet with three snap points (30%, 60%, 90% of viewport). Drag the handle up or down — the sheet settles on the nearest snap.

Last settled snap index: 1
import { Drawer } from 'fluxo-ui';

const [open, setOpen] = useState(false);

<Drawer
    open={open}
    onClose={() => setOpen(false)}
    position="bottom"
    variant="sheet"
    snapPoints={[0.3, 0.6, 0.9]}
    initialSnap={1}
    title="Select an option"
>
    {/* sheet body */}
</Drawer>

Drag-to-dismiss

Sheet without snap points — drag down past 40% of its height or fast-swipe down to dismiss.

Top sheet

Sheets aren't limited to the bottom — the same drag/snap behavior works with position='top'.

Custom Content

Add a header and footer to create structured drawer layouts with action buttons.

Custom Header & Footer

A drawer with a form, custom header, and action buttons in the footer.

import { Drawer, Button, TextInput } from 'fluxo-ui';

<Drawer
  open={open}
  onClose={() => setOpen(false)}
  header="Edit Profile"
  footer={
    <div className="flex gap-2 justify-end">
      <Button variant="default" onClick={() => setOpen(false)}>Cancel</Button>
      <Button variant="primary" onClick={handleSave}>Save</Button>
    </div>
  }
  size="480px"
>
  <form className="space-y-4">
    <TextInput label="Full Name" value={name} onChange={setName} />
    <TextInput label="Email" value={email} onChange={setEmail} />
  </form>
</Drawer>

Import

import { Drawer } from 'fluxo-ui';
import type { DrawerProps, DrawerPosition } from 'fluxo-ui';

Props

openreq
boolean

Whether the drawer is visible.

onClosereq
() => void

Called when the drawer should close.

position
'left' | 'right' | 'top' | 'bottom'"'right'"

Edge from which the drawer slides in.

size
string"'400px'"

Width (horizontal) or height (vertical) of the drawer. Ignored when snapPoints is provided.

variant
'panel' | 'sheet'

Visual variant. 'sheet' adds rounded top corners, drag handle, and drag-to-dismiss behavior — ideal for mobile bottom sheets. Auto-resolves to 'sheet' when position='bottom' and any sheet feature is set.

showDragHandle
boolean

Show a drag handle at the top of the drawer. Defaults to true for sheet variant on top/bottom positions.

draggable
boolean

Enable drag-to-dismiss / drag-between-snap-points gestures. Defaults to true for sheet variant on top/bottom positions.

snapPoints
(number | string)[]

List of snap point heights (e.g. [0.3, 0.6, 0.9] or ['30%', '60vh', '600px']). Numeric <=1 is treated as a viewport ratio.

initialSnap
number"0"

Index of the snap point used when the drawer opens.

onSnapChange
(index: number) => void

Called when the drawer settles on a new snap point.

rounded
boolean

Round the corners that face the viewport center. Defaults to true for the sheet variant.

backdrop
boolean"true"

Show a dark backdrop behind the drawer.

pushContent
boolean"false"

Push the main content instead of overlaying.

pushContentSelector
string

CSS selector for the element to push when pushContent is enabled. Defaults to '#root' or the first body child.

closeOnEscape
boolean"true"

Close drawer on Escape key press.

closeOnBackdropClick
boolean"true"

Close drawer when clicking the backdrop.

title
string

Plain-text title rendered as the drawer header (when no custom header is supplied) and used as the dialog's accessible name.

ariaLabel
string

Accessible name for the dialog. Use when there's no visible title.

ariaLabelledBy
string

ID of an element that labels the dialog. Overrides ariaLabel/title when set.

header
ReactNode

Header content. When provided, shows a header bar with close button.

footer
ReactNode

Footer content rendered at the bottom.

childrenreq
ReactNode

Main body content of the drawer.

className
string

Additional CSS class for the drawer panel.

Features

Four Positions

Slide in from left, right, top, or bottom with smooth CSS transitions.

Focus Trap

Tab key cycles through focusable elements within the drawer.

Push Content

Optionally push main content aside instead of overlaying.

Header & Footer

Optional header with close button and footer for action buttons.

Backdrop Control

Toggle backdrop visibility and close-on-click behavior.

Accessibility

ARIA modal role, focus restoration, and escape key handling.