Uranus® Design System

Drawer

Painel que sobe a partir do rodapé da tela, otimizado para interações mobile

Drawer é um painel que desliza a partir da base da viewport. É construído sobre vaul e oferece gestos nativos de arrastar: o usuário pode puxar a borda superior para fechar, como em apps nativos. Use-o em vez de Sheet quando o conteúdo é principalmente consumido em dispositivos móveis.

'use client';

import {
  Button,
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from '@uranus-workspace/design-system';

export default function DrawerDefault() {
  return (
    <Drawer>
      <DrawerTrigger asChild>
        <Button variant="outline">Ver detalhes do pedido</Button>
      </DrawerTrigger>
      <DrawerContent>
        <div className="mx-auto w-full max-w-md">
          <DrawerHeader>
            <DrawerTitle>Pedido #4829</DrawerTitle>
            <DrawerDescription>
              Criado em 14 de abril, com entrega prevista para sexta-feira.
            </DrawerDescription>
          </DrawerHeader>
          <div className="px-4 pb-4 text-sm">
            <ul className="divide-y">
              <li className="flex justify-between py-2">
                <span>Plano Profissional</span>
                <span className="font-medium">R$ 149,00</span>
              </li>
              <li className="flex justify-between py-2">
                <span>Assentos adicionais (3)</span>
                <span className="font-medium">R$ 87,00</span>
              </li>
              <li className="flex justify-between py-2 font-semibold">
                <span>Total</span>
                <span>R$ 236,00</span>
              </li>
            </ul>
          </div>
          <DrawerFooter>
            <Button>Confirmar pedido</Button>
            <DrawerClose asChild>
              <Button variant="outline">Fechar</Button>
            </DrawerClose>
          </DrawerFooter>
        </div>
      </DrawerContent>
    </Drawer>
  );
}

Anatomia

  • Drawer — raiz que controla o estado. A prop shouldScaleBackground (ativada por padrão) reduz levemente o fundo enquanto o drawer está aberto.
  • DrawerTrigger — elemento que abre o drawer.
  • DrawerContent — o painel. Já inclui a "handle" cinza no topo.
  • DrawerHeaderDrawerTitle + DrawerDescription — título e contexto.
  • DrawerFooter — área para ações primárias, sempre empilhadas verticalmente.
  • DrawerClose — botão de fechar explícito.

Uso

import {
  Button,
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerDescription,
  DrawerFooter,
  DrawerHeader,
  DrawerTitle,
  DrawerTrigger,
} from '@uranus-workspace/design-system';

<Drawer>
  <DrawerTrigger asChild>
    <Button variant="outline">Abrir</Button>
  </DrawerTrigger>
  <DrawerContent>
    <DrawerHeader>
      <DrawerTitle>Detalhes do pedido</DrawerTitle>
      <DrawerDescription>Criado em 14 de abril.</DrawerDescription>
    </DrawerHeader>
    <DrawerFooter>
      <Button>Confirmar</Button>
      <DrawerClose asChild>
        <Button variant="outline">Fechar</Button>
      </DrawerClose>
    </DrawerFooter>
  </DrawerContent>
</Drawer>

Faça

  • Use em fluxos mobile onde o gesto de arrastar é esperado.
  • Empilhe ações no DrawerFooter — a ação primária fica em cima, a de cancelar embaixo, alinhadas à largura total.
  • Limite a altura do conteúdo para que a "handle" fique sempre visível e alcançável com o polegar.

Não faça

  • Não use Drawer como navegação principal em desktop — ele bloqueia toda a largura da tela. Use Sheet nesses casos.
  • Não encha o drawer de formulário longo sem scroll — lembre-se de que o usuário pode arrastar para fechar por acidente.
  • Não remova a "handle" visual: ela é a afordance que comunica o gesto.

Acessibilidade

  • vaul expõe role="dialog" e gerencia trap de foco, Esc e retorno de foco ao trigger.
  • DrawerTitle e DrawerDescription são associados ao container via aria-labelledby/aria-describedby automaticamente.
  • Em dispositivos com teclado, o gesto de arrastar é substituído pelo botão DrawerClose — por isso ele é obrigatório em qualquer drawer não trivial.
  • Respeita prefers-reduced-motion.