125k

Drawer

React 用のドロワー コンポーネント。

"use client"

import * as React from "react"

インストール

pnpm dlx shadcn@latest add drawer

以下をグローバル スタイルに追加してください。iOS Safari では、ドロワーのオーバーレイは絶対配置されており、ページがスクロールされた後にビューポートを覆うために body の位置指定が必要です。詳細については、Base UI のドキュメントを参照してください。

body {
  position: relative;
}

使い方

import {
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer"
<Drawer>
  <DrawerTrigger render={<Button variant="outline" />}>Open</DrawerTrigger>
  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Are you absolutely sure?</DrawerTitle>
      <DrawerDescription>This action cannot be undone.</DrawerDescription>
    </DrawerHeader>
    <div className="p-4">{/* Content here */}</div>
    <DrawerFooter>
      <Button>Submit</Button>
      <DrawerClose render={<Button variant="outline" />}>Cancel</DrawerClose>
    </DrawerFooter>
  </DrawerContent>
</Drawer>

構成

次の構成を使用して Drawer を構築します。

Drawer
├── DrawerTrigger
└── DrawerContent
    ├── DrawerHeader
    │   ├── DrawerTitle
    │   └── DrawerDescription
    └── DrawerFooter

DrawerContent は、Base UI のポータル、オーバーレイ、ビューポート、ポップアップを組み合わせたものです。より低レベルの制御が必要な場合は、DrawerPortal、DrawerOverlay、DrawerSwipeHandle もエクスポートされています。

カスタム サイズ

垂直方向のドロワーはコンテンツに合わせてサイズが決まり、デフォルトでは calc(100dvh - 6rem) が上限になります。サイド ドロワーはビューポート幅の 75%、大きな画面では 24rem を占めます。

垂直ドロワーの高さをカスタマイズするには、DrawerContent の h-* および max-h-* ユーティリティを使用します。

<DrawerContent className="h-[50vh]">

サイド ドロワーの幅をカスタマイズするには、DrawerContent の w-* および max-w-* ユーティリティを使用します。

<DrawerContent className="w-96">

同じコンポーネントが複数の方向でレンダリングされる場合、data-[swipe-axis=*] バリアントを使用してオーバーライドの範囲を 1 つの軸に設定します。

<DrawerContent className="data-[swipe-axis=y]:max-h-[50vh] data-[swipe-axis=x]:w-96">

ドロワーの領域をスクロール可能にするには、スクロール コンテナーをフレックス アイテムにします。コンテンツサイズのドロワー内では解決されない h-full は避けてください。

<DrawerContent>
  <DrawerHeader>...</DrawerHeader>
  <div className="flex-1 overflow-y-auto p-4">{/* Scrollable content */}</div>
  <DrawerFooter>...</DrawerFooter>
</DrawerContent>

スタイリング

ドロワーは、スタイル レベルのカスタマイズ用の CSS 変数を公開します。 DrawerContent にサイズ変数を設定します。 CSS の [data-slot=drawer-overlay] にオーバーレイ変数を設定します。

変数デフォルト説明
--drawer-inset0pxドロワーをビューポートの端から浮かせます。
--drawer-bleed-backgroundvar(--color-popover)スワイプのオーバーシュート時にドロワーの背後の隙間を埋めます。
--drawer-overlay-min-opacity0最小オーバーレイ不透明度。スナップ ポイントが有効な場合のデフォルトは 0.5 です。

ドロワーは、DrawerContent の data-[swipe-direction=down]: やその子孫の group-data-[swipe-axis=y]/drawer-popup: などのバリアントでターゲットにできるデータ属性も設定します。

属性値設定されるタイミング
data-swipe-directionup、right、down、leftいつも。
data-swipe-axisx、yいつも。
data-snap-pointsありドロワーにスナップ ポイントがあります。
data-expandedありドロワーが完全なスナップ ポイントにあります。
data-swipingありスワイプが進行中です。
data-nested-drawer-openあり入れ子のドロワーが上部に開きます。

位置

swipeDirection プロップを使用してドロワーの側面を設定します。

使用可能なオプションは、up、right、down、および left です。

import { Button } from "@/components/ui/base/button"
import {
  Drawer,

スワイプ ハンドル

Drawer で showSwipeHandle を使用して、スワイプ ハンドルをレンダリングします。

"use client"

import { Button } from "@/components/ui/base/button"

ネスト

別のドロワー内から新しいドロワーを開きます。親ドロワーはマウントされたまま残り、最前面のドロワーの背後に積み重なります。

"use client"

import { useIsMobile } from "@/hooks/use-mobile"

非モーダル

modal={false} を設定すると、ドロワーが開いている間もページの残りの部分を操作できるようになります。disablePointerDismissal と組み合わせると、外側を押してもドロワーが閉じないようにできます。modal="trap-focus" を使用すると、スクロールやポインター操作を制限せずにドロワー内にフォーカスを維持できます。

import { Button } from "@/components/ui/base/button"
import {
  Drawer,

スナップ ポイント

snapPoints を使用して、ドロワーを事前設定された高さにスナップします。 0 と 1 の間の数字はビューポートの小数を表します。 1 より大きい数値はピクセル値として扱われます。文字列値は px および rem 単位をサポートします。スナップ ポイントは垂直ドロワーに適用されます。

制御された snapPoint プロップと onSnapPointChange プロップを使用して、アクティブなスナップ ポイントを追跡します。完全なスナップ ポイントに達すると、ドロワーに data-expanded 属性が設定され、data-expanded: バリアントでスタイルを指定できます。

"use client"

import { Button } from "@/components/ui/base/button"

レスポンシブ

Dialog コンポーネントと Drawer コンポーネントを組み合わせて、応答性の高いダイアログを作成できます。これにより、デスクトップでは Dialog コンポーネントがレンダリングされ、モバイルでは Drawer がレンダリングされます。

"use client"

import * as React from "react"

Vaul からの移行

Base ドロワーは現在 Base UI を使用しています。以前のバージョンをインストールしていた場合は、以下の手順に従って使用箇所を更新してください。

依存関係を更新します。

- npm install vaul
+ npm install @base-ui/react

direction を swipeDirection に置き換えます。

bottom の代わりに down を使用し、top の代わりに up を使用します。left と right は変更ありません。

- <Drawer direction="bottom">
+ <Drawer swipeDirection="down">

asChild を render に置き換えます。

DrawerTrigger の場合は、トリガー要素を render プロップに渡します。

- <DrawerTrigger asChild>
-   <Button variant="outline">Open</Button>
- </DrawerTrigger>
+ <DrawerTrigger render={<Button variant="outline" />}>
+   Open
+ </DrawerTrigger>

DrawerClose の場合は、閉じる要素を render プロップに渡します。

- <DrawerClose asChild>
-   <Button variant="outline">Cancel</Button>
- </DrawerClose>
+ <DrawerClose render={<Button variant="outline" />}>
+   Cancel
+ </DrawerClose>

スナップ ポイントのプロップを更新します。

スナップ ポイントを使用している場合は、制御されたスナップ ポイントのプロップと、連続スナップ ポイントのプロップの名前を変更してください。

  <Drawer
    snapPoints={[0.25, 0.5, 1]}
-   activeSnapPoint={snapPoint}
-   setActiveSnapPoint={setSnapPoint}
-   snapToSequentialPoint
+   snapPoint={snapPoint}
+   onSnapPointChange={setSnapPoint}
+   snapToSequentialPoints
  >

アニメーションとフォーカスのプロップを更新します。

- <Drawer onAnimationEnd={(open) => setDone(open)}>
+ <Drawer onOpenChangeComplete={(open) => setDone(open)}>
- <DrawerContent onOpenAutoFocus={(event) => event.preventDefault()}>
+ <DrawerContent initialFocus={false}>

Vaul 専用のプロップを確認します。

handleOnly、repositionInputs、shouldScaleBackground に相当するものは、Base UI ドロワー API にはありません。必要な動作に応じて、disablePointerDismissal、modal、snapPoints、または制御された open 状態などの Base UI プロップを使用してください。

- <Drawer handleOnly repositionInputs={false} shouldScaleBackground>
+ <Drawer>
- <Drawer dismissible={false}>
+ <Drawer disablePointerDismissal>

カスタム データ属性セレクターを更新します。

Vaul の data-vaul-drawer-direction セレクターを、Base UI の data-swipe-direction セレクターに置き換えます。

- <DrawerContent className="data-[vaul-drawer-direction=bottom]:max-h-[50vh]">
+ <DrawerContent className="data-[swipe-direction=down]:max-h-[50vh]">

Base UI は、スワイプとトランジションの状態に応じて data-swiping、data-starting-style、data-ending-style も公開します。DrawerContent の子孫では、軸ごとのスタイル指定に group-data-[swipe-axis=x]/drawer-popup と group-data-[swipe-axis=y]/drawer-popup を使用できます。

API リファレンス

完全な API リファレンスについては、Base UI ドキュメント を参照してください。