Vaul

An unstyled, physics-based drawer component for React, built on Radix UI's Dialog primitive.

Library
npm
v1.1.2
8,594stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
48/100Fair
Development Activity0
Maintenance44
Community56
Maturity52
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
74/100Good
Architecture78
Code Quality72
Innovation82
Learning Curve65

Vaul is a React component library for building drawers — bottom sheets, side panels, and swipeable overlays — modeled after the drawer interaction popularized by iOS. It wraps Radix UI’s Dialog primitive with pointer-based drag tracking, velocity-aware snap points, and background scaling so the resulting drawer feels physically responsive rather than purely CSS-animated.

The library ships as a small set of composable components (Root, Trigger, Content, Overlay, Handle, NestedRoot, Portal) that mirror Radix’s own API shape, and it is unstyled by default, leaving all visual styling to the consuming application while vaul handles the gesture physics, focus management, and scroll-locking behavior.

What You Get

  • Drawer.Root/Trigger/Content/Overlay/Handle/NestedRoot components with a Radix-like compound API
  • Pointer-based drag tracking with velocity thresholds, dampening, and directional (top/bottom/left/right) support
  • Configurable snap points (percentage or pixel) with fade-from-index background overlay control
  • Built-in scroll locking, iOS Safari viewport/keyboard handling, and background scaling on open
  • Nested drawer support via Drawer.NestedRoot for stacked sheet flows

Common Use Cases

  • Mobile-style bottom sheets for menus, filters, or action lists in a responsive web app
  • Side-panel drawers for cart, settings, or detail views triggered by a click
  • Multi-step snap-point sheets, e.g. a half-open preview that expands to full height
  • shadcn/ui-style drawer components layered on top of Radix + Tailwind design systems

Under The Hood

Architecture — Vaul is a single-package React component library (~2,300 lines across 12 TS/TSX files under src/) that wraps Radix UI’s Dialog primitive (DialogPrimitive.Root/Content/Overlay/Trigger/Portal/Close/Title/Description) with pointer-event-based drag physics. The core Root component (src/index.tsx) owns all interaction state (isDragging, activeSnapPoint, drawer/overlay refs) via React state and refs, and exposes it through a DrawerContext (src/context.ts) that Content/Overlay/Handle subcomponents consume via useDrawerContext(). Dragging is handled with native pointer events rather than a gesture library, translating the drawer’s DOM node directly via CSS transforms (helpers.ts: set/getTranslate/dampenValue) for smooth movement, then handing off to Radix’s own open/close state machine on release. Snap points are computed as a separate concern in use-snap-points.ts, converting percentage/pixel snap definitions into pixel offsets relative to the window or a custom container, and deciding on release whether to snap to the nearest point or fling based on velocity thresholds. Two hooks handle platform quirks: use-position-fixed.ts works around iOS Safari’s viewport/scroll bugs by pinning body position while a modal drawer is open, and use-prevent-scroll.ts (adapted from Adobe’s react-spectrum) blocks background touch-scrolling on iOS during drag.

Tech Stack — TypeScript (96% of the codebase) targeting React 16.8 through 19 as peer dependencies, with a single runtime dependency: @radix-ui/react-dialog (^1.1.1), which supplies accessible dialog semantics (focus trap, ARIA, escape-to-close) that Vaul layers drag/snap behavior on top of. The package is built with bunchee into dual ESM/CJS output with generated .d.ts files, and the monorepo uses pnpm workspaces + Turborepo to coordinate the library package and a separate test/ Next.js app used for Playwright e2e tests. Styling ships as a small style.css file for defaults rather than a CSS-in-JS runtime, keeping the library unopinionated about the consumer’s styling approach.

Code Quality — There is a real, if end-to-end rather than unit, test suite: test/tests/*.spec.ts uses Playwright against a dedicated Next.js app covering base behavior, controlled mode, nested drawers, snap points, scaled/unscaled backgrounds, non-dismissible drawers, and handle interactions — a meaningful signal given how gesture-heavy this code is. Source files are consistently typed with explicit prop interfaces (DialogProps, HandleProps, ContentProps) and use React.forwardRef correctly, though several internal call sites use @ts-ignore and any casts around vendor-prefixed CSS properties and a WeakMap-cached style object in helpers.ts. Naming is consistent and descriptive, but the core Root component in index.tsx is a single ~700-line function with many closures and refs, concentrating most of the library’s complexity in one file. Error handling is minimal by design, with most edge cases guarded by early-return checks and one explicit thrown Error in NestedRoot for genuine misuse (nesting outside a parent drawer).

API Design — The public API is a small, Radix-shaped compound-component object (Drawer.Root, .Trigger, .Content, .Overlay, .Handle, .NestedRoot, .Portal, .Close, .Title, .Description) that developers already familiar with Radix Dialog or shadcn/ui can pick up with near-zero new concepts — Trigger/Close/Title/Description are literally re-exported from @radix-ui/react-dialog. A basic drawer needs only a trigger and content wrapped in Root, with sensible defaults (modal=true, dismissible=true, direction=‘bottom’) covering the common case, while advanced behavior (snap points, custom container, handle-only dragging, fade-from-index) is opt-in via JSDoc comments directly on each prop that double as inline editor documentation. The main weakness is that project-level documentation lives almost entirely outside the repo, on the official docs site, since the README is now reduced to a single unmaintained-status notice — so newcomers exploring the repo itself have to read prop JSDoc and the Playwright tests to understand behavior.

Used by 47 apps in this directory

TypeScript
99%
Other

Activepieces

Automation · AI Assistants

24,298

Open-source AI automation platform that converts 280+ workflow integrations into MCP servers for LLMs, with no-code builders and TypeScript extensibility.

View details
92
Repo Health
85
Technical
64
Dependency
Built with
TypeScript99%
Updated today
TypeScript
87%
Other

AFFiNE

Productivity · Project Management · Note Taking

72,238

Write, draw, and plan in one infinite canvas — the open-source alternative to Notion and Miro that keeps your data yours.

View details
91
Repo Health
87
Technical
67
Dependency
Built with
TypeScript87%
Updated yesterday
TypeScript
88%
MIT

Amical

Note Taking · AI Assistants

1,522

Local-first AI dictation that understands your active app — private, offline, and built for speed.

View details
81
Repo Health
82
Technical
67
Dependency
Built with
TypeScript88%
Updated 2 days ago
Python
67%
Other

AutoGPT

Automation · Productivity · AI Assistants

187,177

Build, deploy, and run autonomous AI agents that automate complex multi-step workflows using a visual block-based graph editor.

View details
93
Repo Health
78
Technical
66
Dependency
Built with
Python67%
TypeScript32%
Updated today
TypeScript
100%
AGPL 3.0

BaseBuddy

CMS

7

A self-hosted content editor for existing Postgres or Supabase schemas — maps the tables you already have into a WordPress-like TipTap editor instead of requiring you to reshape your database around a CMS.

View details
35
Repo Health
64
Technical
76
Dependency
Built with
TypeScript100%
Updated 2 weeks ago
TypeScript
99%
AGPL 3.0

Cherry Studio

AI Assistants

51,521

All-in-one AI desktop client with 300+ assistants and multi-model support

View details
89
Repo Health
84
Technical
71
Dependency
Built with
TypeScript99%
Updated today
TypeScript
98%
Apache 2.0

Cline

AI Code Assistants

67,585

An open-source AI coding agent that lives in your editor and terminal — reads and edits your codebase, runs commands, browses the web, and requires human approval for every action by default.

View details
89
Repo Health
74
Technical
65
Dependency
Built with
TypeScript98%
Updated 2 days ago
TypeScript
100%
Other

Dub

Marketing · Analytics

24,676

The open-source link attribution platform for short links, conversion tracking, and affiliate programs — powering 100M+ clicks monthly.

View details
80
Repo Health
78
Technical
62
Dependency
Built with
TypeScript100%
Updated 2 days ago
TypeScript
96%
Other

Dyad

AI Development · Productivity · AI Code Assistants

21,390

Build AI-powered apps locally with your own keys, your own models, and zero cloud lock-in.

View details
88
Repo Health
83
Technical
69
Dependency
Built with
TypeScript96%
Updated yesterday

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search