Star on GitHub
npm install react-driftkit
import { DraggableSheet } from 'react-driftkit';
Edge
Snap Point
Close on Outside Click
on
DraggableSheetDrag the handle to resize between snap points. Flick fast to skip stops. Tap the × to close.
Prop Type Default
children
Content rendered inside the sheet.
ReactNode —
edge
Edge the sheet is pinned to.
'bottom' | 'top' | 'left' | 'right' 'bottom'
snapPoints
Ordered list of stops. Mix presets ('peek', 'half', 'full', 'closed'), raw pixel numbers, and percentage strings like '40%'.
SnapPoint[] ['peek', 'half', 'full']
defaultSnap
Uncontrolled initial stop.
SnapPoint middle of snapPoints
snap
Controlled current stop. When set, parent drives transitions.
SnapPoint —
onSnapChange
Fires on drag release with the resolved stop and its pixel size.
(snap: SnapPoint, sizePx: number) => void —
draggable
Whether the user can drag the sheet.
boolean true
dragHandleSelector
CSS selector for a nested handle. When set, drag only begins inside matching elements.
string —
velocityThreshold
Flick velocity (px/ms) above which a release advances one stop in the flick direction.
number 0.5
closeOnOutsideClick
When true, a pointerdown outside the sheet collapses it to 0 and fires onSnapChange('closed', 0). Ignored while already closed or mid-drag.
boolean false
style
Additional inline styles for the wrapper.
CSSProperties {}
className
Additional CSS class for the wrapper.
string ''

The wrapper exposes data-edge, data-snap, and data-dragging so you can drive styles from CSS without re-rendering.

tsx
import { DraggableSheet } from 'react-driftkit';

function App() {
  return (
    <DraggableSheet snapPoints={['peek', 'half', 'full']} defaultSnap="half">
      <div className="my-sheet">
        <div data-handle className="sheet-handle" />
        <div className="sheet-body">Details, filters, cart...</div>
      </div>
    </DraggableSheet>
  );
}
typescript
type SheetEdge = 'bottom' | 'top' | 'left' | 'right';
type SnapPoint =
  | 'closed'
  | 'peek'
  | 'half'
  | 'full'
  | number
  | `${number}%`;

interface DraggableSheetProps {
  children: ReactNode;
  edge?: SheetEdge;
  snapPoints?: SnapPoint[];
  defaultSnap?: SnapPoint;
  snap?: SnapPoint;
  onSnapChange?: (snap: SnapPoint, sizePx: number) => void;
  draggable?: boolean;
  dragHandleSelector?: string;
  velocityThreshold?: number;
  closeOnOutsideClick?: boolean;
  style?: CSSProperties;
  className?: string;
}

Enjoying react-driftkit?

Star the repo on GitHub to help more devs discover it.

Star on GitHub