Mục lục tham khảo

Thành phần

Drawer

Drawer on Base UI: paper panel from any edge, heavy 3px ink rule as the handle, swipe to dismiss, focus trapped.

Nội dung tham khảo viết bằng tiếng Anh; mục “Vietnamese” có ví dụ tiếng Việt.

Xem trước

Install

bash

npx shadcn add @eloquent/drawer

Usage

tsx

import { Button } from "@/components/ui/button";
import {
  Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger,
} from "@/components/ui/drawer";

<Drawer>
  <DrawerTrigger render={<Button variant="outline" />}>Open the edition</DrawerTrigger>
  <DrawerContent closeLabel="Close">
    <DrawerHeader>
      <DrawerTitle>Today's edition</DrawerTitle>
      <DrawerDescription>Sections in this morning's paper.</DrawerDescription>
    </DrawerHeader>
    <DrawerFooter>
      <DrawerClose render={<Button />}>Done</DrawerClose>
    </DrawerFooter>
  </DrawerContent>
</Drawer>

swipeDirection on Drawer sets the edge: down (default, a bottom drawer), up, left or right. The corner ✕ renders only when you pass closeLabel.

This is built on Base UI's own Drawer (stable in @base-ui/react 1.9.0), so there is no vaul dependency.

States

From the bottom
From the right
From the left
From the top
StateTreatment
OpenPaper panel, heavy 3px ink rule on the edge facing the page; backdrop paper at 85%, no blur
SwipingThe panel follows the pointer, then fades out
Focus2px ink outline, 2px offset
Close pressedtint-1 fill on the 44px ✕; no hover effect

Keyboard

KeyAction
Tab / Shift+TabFrom the page, reach the trigger. While open, move between the drawer's controls; focus wraps and never leaves the drawer
Enter / SpaceOpen from the trigger; activate a control
EscClose; focus returns to the trigger

Swiping is an extra gesture. Esc, DrawerClose and the corner ✕ do everything it does.

Vietnamese

Ink adaptation

Upstream shadcn's grab pill, shadow, rounded top corners and dark overlay are removed. The heavy 3px rule on the edge that faces the page is the handle; the backdrop is paper at 85% with no blur. Entering and leaving are an opacity fade (none under reduced motion); the swipe still moves the panel with the pointer. Built on Base UI Drawer.