Vaul

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

Library
npm
v1.1.2
8,556stars
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

23,887

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
65
Dependency
Built with
TypeScript99%
Updated today
TypeScript
88%
Other

AFFiNE

Productivity · Project Management · Note Taking

71,668

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
68
Dependency
Built with
TypeScript88%
Updated today
TypeScript
84%
MIT

Amical

Note Taking · AI Assistants

1,495

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

View details
79
Repo Health
82
Technical
67
Dependency
Built with
TypeScript84%
Updated 3 weeks ago
Python
68%
Other

AutoGPT

Automation · Productivity · AI Assistants

186,687

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
67
Dependency
Built with
Python68%
TypeScript31%
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
46
Repo Health
64
Technical
76
Dependency
Built with
TypeScript100%
Updated 1 weeks ago
TypeScript
99%
AGPL 3.0

Cherry Studio

AI Assistants

50,753

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

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

Cline

AI Code Assistants

66,453

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
90
Repo Health
74
Technical
67
Dependency
Built with
TypeScript97%
Updated today
TypeScript
100%
Other

Dub

Marketing · Analytics

24,521

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

View details
81
Repo Health
78
Technical
65
Dependency
Built with
TypeScript100%
Updated today
TypeScript
96%
Other

Dyad

AI Development · Productivity · AI Code Assistants

21,279

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

View details
88
Repo Health
83
Technical
70
Dependency
Built with
TypeScript96%
Updated today

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