HextaUI

Drawer

Um painel que desliza a partir de qualquer borda e acompanha o seu dedo, com pontos de ancoragem, uma alça funcional e drawers aninhados que se empilham.

"use client"

import * as React from "react"
import { IconMinus, IconPlus } from "@tabler/icons-react"

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

export function DrawerDemo() {
  const [goal, setGoal] = React.useState(350)

  return (
    <Drawer>
      <DrawerTrigger render={<Button variant="outline" />}>
        Set daily goal
      </DrawerTrigger>
      <DrawerContent>
        <div className="mx-auto flex w-full max-w-sm flex-col">
          <DrawerHeader>
            <DrawerTitle>Move goal</DrawerTitle>
            <DrawerDescription>Set your daily activity goal.</DrawerDescription>
          </DrawerHeader>
          <div className="flex items-center justify-center gap-6 p-6">
            <Button
              variant="outline"
              size="icon"
              aria-label="Decrease goal"
              disabled={goal <= 200}
              onClick={() => setGoal(goal - 10)}
            >
              <IconMinus />
            </Button>
            <div className="flex min-w-32 flex-col items-center">
              <NumberFlow
                value={goal}
                className="text-6xl font-semibold tracking-tight"
              />
              <span className="text-xs text-muted-foreground uppercase">
                Calories / day
              </span>
            </div>
            <Button
              variant="outline"
              size="icon"
              aria-label="Increase goal"
              disabled={goal >= 600}
              onClick={() => setGoal(goal + 10)}
            >
              <IconPlus />
            </Button>
          </div>
          <DrawerFooter>
            <DrawerClose render={<Button />}>Save goal</DrawerClose>
            <DrawerClose render={<Button variant="outline" />}>
              Cancel
            </DrawerClose>
          </DrawerFooter>
        </div>
      </DrawerContent>
    </Drawer>
  )
}
pnpm dlx shadcn@latest add https://hextaui.com/r/drawer.json

Adiciona o componente, os tokens de tema do HextaUI e quaisquer componentes do HextaUI dos quais ele depende.

import {
  Drawer,
  DrawerBody,
  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>
    <DrawerBody>{/* content */}</DrawerBody>
    <DrawerFooter>
      <Button>Submit</Button>
      <DrawerClose render={<Button variant="outline" />}>Cancel</DrawerClose>
    </DrawerFooter>
  </DrawerContent>
</Drawer>
Drawer
├── DrawerTrigger
└── DrawerContent
    ├── DrawerHeader
    │   ├── DrawerTitle
    │   └── DrawerDescription
    ├── DrawerBody
    └── DrawerFooter
        └── DrawerClose

Direções

Defina swipeDirection em <Drawer /> para escolher a borda. O drawer abre a partir dessa borda e desliza de volta em direção a ela. Drawers superior e inferior exibem uma alça por padrão.

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

const directions = [
  { value: "up", label: "Top" },
  { value: "right", label: "Right" },
  { value: "down", label: "Bottom" },
  { value: "left", label: "Left" },
] as const

export function DrawerDirections() {
  return (
    <div className="flex flex-wrap justify-center gap-2">
      {directions.map(({ value, label }) => (
        <Drawer key={value} swipeDirection={value}>
          <DrawerTrigger render={<Button variant="outline" />}>
            {label}
          </DrawerTrigger>
          <DrawerContent>
            <DrawerHeader>
              <DrawerTitle>Swipe {value} to close</DrawerTitle>
              <DrawerDescription>
                The drawer follows your finger and keeps the momentum when you
                let go.
              </DrawerDescription>
            </DrawerHeader>
            <DrawerFooter>
              <DrawerClose render={<Button variant="outline" />}>
                Close
              </DrawerClose>
            </DrawerFooter>
          </DrawerContent>
        </Drawer>
      ))}
    </div>
  )
}

Snap points

Passe snapPoints para fazer um drawer inferior parar em alturas predefinidas. Números de 0 a 1 são frações do viewport, números maiores são pixels e strings aceitam px ou rem. A parte visível sempre se ajusta ao conteúdo, então nada fica escondido abaixo da tela.

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

const snapPoints = ["20rem", 1]

const places = [
  "Blue Bottle Coffee",
  "Tartine Bakery",
  "Mission Dolores Park",
  "Ferry Building",
  "Golden Gate Park",
  "Lands End Trail",
  "Twin Peaks",
  "Coit Tower",
  "Alamo Square",
  "Baker Beach",
  "Crissy Field",
  "Japanese Tea Garden",
]

export function DrawerSnapPoints() {
  return (
    <Drawer snapPoints={snapPoints}>
      <DrawerTrigger render={<Button variant="outline" />}>
        Nearby places
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Nearby places</DrawerTitle>
          <DrawerDescription>
            Drag up to see the full list, or down to close.
          </DrawerDescription>
        </DrawerHeader>
        <DrawerBody>
          <ul className="flex flex-col divide-y">
            {places.map((place) => (
              <li key={place} className="py-3 text-sm">
                {place}
              </li>
            ))}
          </ul>
        </DrawerBody>
      </DrawerContent>
    </Drawer>
  )
}

Conteúdo rolável

<DrawerBody /> rola por conta própria, então o header e o footer permanecem no lugar. O deslize só começa quando o body volta ao topo.

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

const sections = Array.from({ length: 12 }, (_, index) => index + 1)

export function DrawerScrollable() {
  return (
    <Drawer>
      <DrawerTrigger render={<Button variant="outline" />}>
        Terms of service
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Terms of service</DrawerTitle>
          <DrawerDescription>Last updated October 2026.</DrawerDescription>
        </DrawerHeader>
        <DrawerBody>
          <div className="flex flex-col gap-4 text-sm text-muted-foreground">
            {sections.map((section) => (
              <p key={section}>
                {section}. By using the service you agree to these terms. We may
                update them from time to time, and we will let you know when
                something important changes. Keep your account details safe and
                tell us if you think someone else has access.
              </p>
            ))}
          </div>
        </DrawerBody>
        <DrawerFooter>
          <DrawerClose render={<Button />}>Accept</DrawerClose>
          <DrawerClose render={<Button variant="outline" />}>
            Decline
          </DrawerClose>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  )
}

Formulários e o teclado

Envolva <DrawerContent /> em <DrawerVirtualKeyboardProvider /> quando um drawer inferior contiver campos de texto. Em celulares, o campo em foco rola para a vista acima do teclado virtual em vez de ficar escondido atrás dele. Mantenha os campos em <DrawerBody /> para que o header e o footer fiquem no lugar.

import { Button } from "@/components/ui/button"
import {
  Drawer,
  DrawerBody,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
  DrawerVirtualKeyboardProvider,
} from "@/components/ui/drawer"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
import { Input } from "@/components/ui/input"

export function DrawerKeyboard() {
  return (
    <Drawer>
      <DrawerTrigger render={<Button variant="outline" />}>
        Delivery details
      </DrawerTrigger>
      <DrawerVirtualKeyboardProvider>
        <DrawerContent>
          <DrawerHeader>
            <DrawerTitle>Delivery details</DrawerTitle>
            <DrawerDescription>
              Tap a field on your phone. It stays above the keyboard.
            </DrawerDescription>
          </DrawerHeader>
          <DrawerBody>
            <FieldGroup>
              <Field>
                <FieldLabel>Name</FieldLabel>
                <Input name="name" autoComplete="name" />
              </Field>
              <Field>
                <FieldLabel>Phone</FieldLabel>
                <Input name="phone" type="tel" autoComplete="tel" />
              </Field>
              <Field>
                <FieldLabel>Street address</FieldLabel>
                <Input name="street" autoComplete="street-address" />
              </Field>
              <Field>
                <FieldLabel>Apartment</FieldLabel>
                <Input name="apartment" />
              </Field>
              <Field>
                <FieldLabel>City</FieldLabel>
                <Input name="city" autoComplete="address-level2" />
              </Field>
              <Field>
                <FieldLabel>Postal code</FieldLabel>
                <Input name="postal" autoComplete="postal-code" />
              </Field>
            </FieldGroup>
          </DrawerBody>
          <DrawerFooter>
            <DrawerClose render={<Button />}>Save address</DrawerClose>
          </DrawerFooter>
        </DrawerContent>
      </DrawerVirtualKeyboardProvider>
    </Drawer>
  )
}

Aninhado

Um drawer aberto a partir de um drawer na mesma borda fica empilhado por cima. Os de trás encolhem, aparecem acima dele e acompanham seu dedo quando você desliza o de cima para fora.

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

export function DrawerNested() {
  return (
    <Drawer>
      <DrawerTrigger render={<Button variant="outline" />}>
        Choose a plan
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Choose a plan</DrawerTitle>
          <DrawerDescription>
            Compare plans, then open the details of the one you like.
          </DrawerDescription>
        </DrawerHeader>
        <DrawerFooter>
          <Drawer>
            <DrawerTrigger render={<Button />}>Pro plan details</DrawerTrigger>
            <DrawerContent>
              <DrawerHeader>
                <DrawerTitle>Pro plan</DrawerTitle>
                <DrawerDescription>
                  The first drawer steps back behind this one.
                </DrawerDescription>
              </DrawerHeader>
              <DrawerFooter>
                <Drawer>
                  <DrawerTrigger render={<Button />}>Checkout</DrawerTrigger>
                  <DrawerContent>
                    <DrawerHeader>
                      <DrawerTitle>Checkout</DrawerTitle>
                      <DrawerDescription>
                        Swipe down to go back one step.
                      </DrawerDescription>
                    </DrawerHeader>
                    <DrawerFooter>
                      <DrawerClose render={<Button variant="outline" />}>
                        Back
                      </DrawerClose>
                    </DrawerFooter>
                  </DrawerContent>
                </Drawer>
                <DrawerClose render={<Button variant="outline" />}>
                  Back
                </DrawerClose>
              </DrawerFooter>
            </DrawerContent>
          </Drawer>
          <DrawerClose render={<Button variant="outline" />}>Close</DrawerClose>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  )
}

Confirmar a partir de um drawer

Diálogos, alert dialogs, sheets e drawers em outra borda ficam em camadas por cima em vez de empilhados. O drawer recua e um backdrop mais claro o cobre.

import {
  AlertDialog,
  AlertDialogAction,
  AlertDialogCancel,
  AlertDialogContent,
  AlertDialogDescription,
  AlertDialogFooter,
  AlertDialogHeader,
  AlertDialogTitle,
  AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
import { Button } from "@/components/ui/button"
import {
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer"

export function DrawerConfirm() {
  return (
    <Drawer>
      <DrawerTrigger render={<Button variant="outline" />}>
        Photo options
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>IMG_2048.heic</DrawerTitle>
          <DrawerDescription>Taken on October 3, 2026.</DrawerDescription>
        </DrawerHeader>
        <DrawerFooter>
          <DrawerClose render={<Button variant="outline" />}>Share</DrawerClose>
          <AlertDialog>
            <AlertDialogTrigger render={<Button variant="destructive" />}>
              Delete photo
            </AlertDialogTrigger>
            <AlertDialogContent>
              <AlertDialogHeader>
                <AlertDialogTitle>Delete “IMG_2048.heic”?</AlertDialogTitle>
                <AlertDialogDescription>
                  It will be removed from all your devices.
                </AlertDialogDescription>
              </AlertDialogHeader>
              <AlertDialogFooter>
                <AlertDialogCancel>Cancel</AlertDialogCancel>
                <AlertDialogAction variant="destructive">
                  Delete
                </AlertDialogAction>
              </AlertDialogFooter>
            </AlertDialogContent>
          </AlertDialog>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  )
}

Responsivo

Altere swipeDirection com uma media query para mostrar um painel lateral no desktop e um bottom sheet em celulares.

"use client"

import * as React from "react"

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

const query = "(min-width: 768px)"

function subscribe(onChange: () => void) {
  const media = window.matchMedia(query)
  media.addEventListener("change", onChange)
  return () => media.removeEventListener("change", onChange)
}

function useIsDesktop() {
  return React.useSyncExternalStore(
    subscribe,
    () => window.matchMedia(query).matches,
    () => false
  )
}

export function DrawerResponsive() {
  const isDesktop = useIsDesktop()

  return (
    <Drawer swipeDirection={isDesktop ? "right" : "down"}>
      <DrawerTrigger render={<Button variant="outline" />}>
        Notifications
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Notifications</DrawerTitle>
          <DrawerDescription>
            A side panel on desktop and a bottom sheet on phones.
          </DrawerDescription>
        </DrawerHeader>
        <DrawerFooter>
          <DrawerClose render={<Button variant="outline" />}>Close</DrawerClose>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  )
}

Não modal

Com modal={false} não há backdrop, a página continua rolando e o foco pode sair do drawer.

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

export function DrawerNonModal() {
  return (
    <Drawer modal={false} swipeDirection="right">
      <DrawerTrigger render={<Button variant="outline" />}>
        Open inspector
      </DrawerTrigger>
      <DrawerContent>
        <DrawerHeader>
          <DrawerTitle>Inspector</DrawerTitle>
          <DrawerDescription>
            The page stays scrollable and clickable while this is open.
          </DrawerDescription>
        </DrawerHeader>
        <DrawerFooter>
          <DrawerClose render={<Button variant="outline" />}>Close</DrawerClose>
        </DrawerFooter>
      </DrawerContent>
    </Drawer>
  )
}

Controlado

Passe open e onOpenChange para abri-lo de qualquer lugar, sem gatilho.

"use client"

import * as React from "react"

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

export function DrawerControlled() {
  const [open, setOpen] = React.useState(false)

  return (
    <>
      <Button variant="outline" onClick={() => setOpen(true)}>
        Open from anywhere
      </Button>
      <Drawer open={open} onOpenChange={setOpen}>
        <DrawerContent>
          <DrawerHeader>
            <DrawerTitle>Controlled drawer</DrawerTitle>
            <DrawerDescription>
              Opened from a plain button, without a trigger.
            </DrawerDescription>
          </DrawerHeader>
          <DrawerFooter>
            <Button variant="outline" onClick={() => setOpen(false)}>
              Close
            </Button>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
    </>
  )
}

Gatilhos desanexados

Compartilhe um drawer entre vários gatilhos com createDrawerHandle. Cada gatilho passa um payload que o drawer renderiza por meio de uma função como filho.

"use client"

import { Button } from "@/components/ui/button"
import {
  createDrawerHandle,
  Drawer,
  DrawerBody,
  DrawerContent,
  DrawerDescription,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from "@/components/ui/drawer"

const contacts = createDrawerHandle<{ name: string; email: string }>()

export function DrawerDetached() {
  return (
    <div className="flex flex-wrap justify-center gap-2">
      <DrawerTrigger
        handle={contacts}
        payload={{ name: "Olivia Martin", email: "[email protected]" }}
        render={<Button variant="outline" size="sm" />}
      >
        Olivia
      </DrawerTrigger>
      <DrawerTrigger
        handle={contacts}
        payload={{ name: "Jackson Lee", email: "[email protected]" }}
        render={<Button variant="outline" size="sm" />}
      >
        Jackson
      </DrawerTrigger>
      <Drawer handle={contacts}>
        {({ payload }) => (
          <DrawerContent>
            <DrawerHeader>
              <DrawerTitle>{payload?.name}</DrawerTitle>
              <DrawerDescription>{payload?.email}</DrawerDescription>
            </DrawerHeader>
            <DrawerBody>
              <p className="text-sm text-muted-foreground">
                One drawer, opened by either trigger.
              </p>
            </DrawerBody>
          </DrawerContent>
        )}
      </Drawer>
    </div>
  )
}

Da direita para a esquerda

Passe dir="rtl" a <DrawerContent /> para espelhar seu conteúdo. swipeDirection nomeia uma borda física, então "left" permanece à esquerda e a alça permanece na borda interna.

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

export function DrawerRtl() {
  return (
    <div dir="rtl" className="flex flex-wrap justify-center gap-2">
      <Drawer>
        <DrawerTrigger render={<Button variant="outline" />}>
          من الأسفل
        </DrawerTrigger>
        <DrawerContent dir="rtl">
          <DrawerHeader>
            <DrawerTitle>تعديل الملف الشخصي</DrawerTitle>
            <DrawerDescription>
              يتم حفظ التغييرات عند النقر على حفظ.
            </DrawerDescription>
          </DrawerHeader>
          <DrawerFooter>
            <DrawerClose render={<Button />}>حفظ</DrawerClose>
            <DrawerClose render={<Button variant="outline" />}>
              إلغاء
            </DrawerClose>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
      <Drawer swipeDirection="left" showSwipeHandle>
        <DrawerTrigger render={<Button variant="outline" />}>
          من اليسار
        </DrawerTrigger>
        <DrawerContent dir="rtl">
          <DrawerHeader>
            <DrawerTitle>القائمة</DrawerTitle>
            <DrawerDescription>اسحب إلى اليسار للإغلاق.</DrawerDescription>
          </DrawerHeader>
          <DrawerFooter>
            <DrawerClose render={<Button variant="outline" />}>
              إغلاق
            </DrawerClose>
          </DrawerFooter>
        </DrawerContent>
      </Drawer>
    </div>
  )
}
TeclaAção
EnterSpaceNo gatilho, abre o drawer e move o foco para dentro dele.
TabShift + TabAlterna entre elementos focáveis. O foco permanece dentro de um drawer modal.
EscFecha o drawer mais ao topo e devolve o foco ao seu gatilho.
  • O drawer é um diálogo. <DrawerTitle /> o rotula e <DrawerDescription /> o descreve, então inclua sempre um título.
  • Deslizar nunca é a única saída: Escape, o backdrop e um botão <DrawerClose /> também o fecham.
  • A alça é decorativa e fica oculta para tecnologias assistivas. Com o mouse, o texto dentro do drawer pode ser selecionado sem arrastá-lo.
  • Com movimento reduzido ativado, o drawer aparece e some com fade em vez de deslizar. O arraste ainda acompanha o ponteiro.

Construído sobre o drawer do Base UI. Cada parte aceita as props da primitiva que envolve.

PropTipoPadrão
swipeDirectionA borda de onde ele abre e a direção que o dispensa.
"up" | "down" | "left" | "right""down"
showSwipeHandleMostra a alça. O padrão é true para up e down, e false para left e right.
boolean–
snapPointsAlturas em que um drawer vertical pode parar. 0–1 é uma fração do viewport, >1 são pixels, strings aceitam px ou rem.
(number | string)[]–
snapPoint
number | string | null–
defaultSnapPoint
number | string | null–
onSnapPointChange
(snapPoint, details) => void–
defaultOpen
booleanfalse
open
boolean–
onOpenChange
(open: boolean, details) => void–
onOpenChangeCompleteChamado após o fim da animação de abertura ou fechamento.
(open: boolean) => void–
modalO backdrop só é renderizado quando true.
boolean | "trap-focus"true
disablePointerDismissalMantém aberto quando o backdrop é clicado.
booleanfalse
handle
DrawerHandle<Payload>–
children
ReactNode | ({ payload }) => ReactNode–
PropTipoPadrão
handle
DrawerHandle<Payload>–
payload
Payload–
render
ReactElement | (props, state) => ReactElement<button>
AtributoDescrição
data-slot="drawer-trigger"Selecione o gatilho no CSS.
data-popup-openPresente enquanto o seu drawer está aberto.

Renderiza o portal, o backdrop, o viewport e o popup, além da alça. Drawers verticais se ajustam ao conteúdo até a altura do viewport menos 4rem. Drawers laterais têm 75% de largura, até 24rem a partir do breakpoint sm. Substitua com h-* ou w-*, ou limite a um eixo com data-[swipe-axis=y]:.

PropTipoPadrão
initialFocus
boolean | RefObject | (type) => HTMLElement | boolean–
finalFocus
boolean | RefObject | (type) => HTMLElement | boolean–
className
string | (state) => string–
render
ReactElement | (props, state) => ReactElement<div>
AtributoDescrição
data-slot="drawer-popup"O painel do drawer.
data-slot="drawer-content"O wrapper interno em volta dos seus children. Ele rola quando nada mais rola.
data-swipe-directionup, right, down ou left.
data-swipe-axisx ou y.
data-openPresente enquanto o drawer está aberto.
data-starting-stylePresente enquanto a animação de entrada ocorre.
data-ending-stylePresente enquanto a animação de saída ocorre.
data-swipingPresente enquanto está sendo arrastado.
data-snap-pointsPresente quando o drawer tem snap points.
data-expandedPresente no snap point de altura total.
data-nested-drawer-openPresente enquanto outro drawer está aberto por cima.
data-stackPresente enquanto um drawer na mesma borda está empilhado por cima.
--drawer-insetFaz o drawer flutuar afastado das bordas do viewport. O padrão é 0px.
--drawer-bleed-backgroundPreenche a área revelada ao arrastar além da borda. O padrão é a cor do popover.
--drawer-swipe-movement-xDistância de arraste horizontal. Também existe uma variável -y.
--drawer-snap-point-offsetA que distância abaixo do topo está o snap point atual.
--nested-drawersQuantos drawers estão abertos por cima.

Renderizado por <DrawerContent /> quando modal é true. Ele esmaece conforme você desliza e permanece pelo menos metade visível quando há snap points. Um drawer em camada sobre um sheet ou um drawer em outra borda recebe um backdrop mais claro.

AtributoDescrição
data-slot="drawer-overlay"O pano de fundo.
data-nestedPresente em backdrops mais claros de drawers em camadas.
--drawer-overlay-min-opacityA menor opacidade a que ele esmaece ao deslizar. 0, ou 0.5 com snap points.

Renderizado por <DrawerContent /> na borda interna quando showSwipeHandle está ativado. O drawer inteiro pode ser arrastado, então a alça é só uma pista visual.

AtributoDescrição
data-slot="drawer-swipe-handle"A alça.

Elementos <div> simples que organizam o drawer. O header centraliza seu texto em drawers verticais em telas pequenas, o body rola e ocupa o espaço restante, e o footer empilha suas ações.

AtributoDescrição
data-slot="drawer-header"Título e descrição.
data-slot="drawer-body"Conteúdo rolável.
data-slot="drawer-footer"Ações.
PropTipoPadrão
render
ReactElement | (props, state) => ReactElement<h2>
AtributoDescrição
data-slot="drawer-title"Rotula o drawer.
PropTipoPadrão
render
ReactElement | (props, state) => ReactElement<p>
AtributoDescrição
data-slot="drawer-description"Descreve o drawer.

Não renderiza nenhum elemento. Coloque-o dentro de <Drawer />, em volta de <DrawerContent />. Enquanto o teclado virtual está aberto, ele adiciona espaço abaixo do contêiner de rolagem do drawer, rola o campo em foco para a vista e faz toques em campos abrirem o teclado no iOS. Drawers sem ele não são afetados.

PropTipoPadrão
children
ReactNode–
AtributoDescrição
--drawer-keyboard-insetDefinido no viewport enquanto o teclado está aberto: quanto dele se sobrepõe à página. Use com um fallback de 0px.
PropTipoPadrão
render
ReactElement | (props, state) => ReactElement<button>
AtributoDescrição
data-slot="drawer-close"Fecha o drawer quando pressionado.

createDrawerHandle<Payload>() retorna um handle que conecta um <Drawer /> a gatilhos renderizados em outro lugar. Crie-o uma vez, fora do seu componente.

Usado em blocos

Blocos que se baseiam em Drawer.