Uranus® Design System

Sheet

Painel lateral que desliza a partir da borda da viewport para acomodar fluxos secundários

Sheet é um painel modal que desliza a partir de uma borda da tela. Use-o quando o fluxo principal precisa continuar visível por contexto, mas a tarefa atual é longa demais para um Popover — edição de perfil, filtros de uma lista, navegação lateral em telas estreitas. Para um painel que sobe a partir do rodapé em mobile prefira Drawer.

'use client';

import {
  Button,
  Input,
  Label,
  Sheet,
  SheetClose,
  SheetContent,
  SheetDescription,
  SheetFooter,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@uranus-workspace/design-system';

export default function SheetDefault() {
  return (
    <Sheet>
      <SheetTrigger asChild>
        <Button variant="outline">Editar perfil</Button>
      </SheetTrigger>
      <SheetContent>
        <SheetHeader>
          <SheetTitle>Editar perfil</SheetTitle>
          <SheetDescription>
            Atualize suas informações pessoais. As mudanças são aplicadas ao confirmar.
          </SheetDescription>
        </SheetHeader>
        <div className="grid gap-4 py-6">
          <div className="grid gap-2">
            <Label htmlFor="sheet-name">Nome</Label>
            <Input id="sheet-name" defaultValue="Gustavo Bertoi" />
          </div>
          <div className="grid gap-2">
            <Label htmlFor="sheet-email">E-mail</Label>
            <Input id="sheet-email" type="email" defaultValue="gustavo@uranus.com.br" />
          </div>
        </div>
        <SheetFooter>
          <SheetClose asChild>
            <Button variant="outline">Cancelar</Button>
          </SheetClose>
          <Button>Salvar alterações</Button>
        </SheetFooter>
      </SheetContent>
    </Sheet>
  );
}

Anatomia

  • SheetTrigger — elemento que abre o painel.
  • SheetContent — o painel em si. Aceita a prop side ("top" | "right" | "bottom" | "left", padrão "right").
  • SheetHeaderSheetTitle + SheetDescription — título e contexto.
  • SheetFooter — área para ações principais.
  • SheetClose — botão para fechar explicitamente. Um X no canto superior direito já é incluído por padrão.

Ancorado à esquerda

Use side="left" para navegação mobile ou árvores de conteúdo que normalmente ficam fixas à esquerda em telas maiores.

'use client';

import {
  Button,
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@uranus-workspace/design-system';
import { Menu } from 'lucide-react';

export default function SheetLeft() {
  return (
    <Sheet>
      <SheetTrigger asChild>
        <Button variant="outline" size="icon" aria-label="Abrir menu">
          <Menu />
        </Button>
      </SheetTrigger>
      <SheetContent side="left">
        <SheetHeader>
          <SheetTitle>Navegação</SheetTitle>
          <SheetDescription>Acesse rapidamente as principais áreas do produto.</SheetDescription>
        </SheetHeader>
        <nav className="mt-6 flex flex-col gap-1 text-sm">
          <a className="rounded-md px-2 py-2 hover:bg-accent" href="#inicio">
            Início
          </a>
          <a className="rounded-md px-2 py-2 hover:bg-accent" href="#projetos">
            Projetos
          </a>
          <a className="rounded-md px-2 py-2 hover:bg-accent" href="#equipe">
            Equipe
          </a>
          <a className="rounded-md px-2 py-2 hover:bg-accent" href="#configuracoes">
            Configurações
          </a>
        </nav>
      </SheetContent>
    </Sheet>
  );
}

Uso

import {
  Button,
  Sheet,
  SheetContent,
  SheetDescription,
  SheetHeader,
  SheetTitle,
  SheetTrigger,
} from '@uranus-workspace/design-system';

<Sheet>
  <SheetTrigger asChild>
    <Button variant="outline">Abrir painel</Button>
  </SheetTrigger>
  <SheetContent side="right">
    <SheetHeader>
      <SheetTitle>Editar perfil</SheetTitle>
      <SheetDescription>Atualize suas informações pessoais.</SheetDescription>
    </SheetHeader>
  </SheetContent>
</Sheet>

Faça

  • Use side="right" para ações secundárias em desktop e side="left" para navegação.
  • Mantenha sempre um SheetTitle, mesmo que visualmente escondido com className="sr-only" — leitores de tela precisam dele.
  • Posicione ações principais no SheetFooter para que não desçam junto ao conteúdo.

Não faça

  • Não use Sheet para confirmações curtas — use AlertDialog.
  • Não aninhe sheets dentro de sheets.
  • Não esconda o botão de fechar — ele é parte do contrato de acessibilidade.

Acessibilidade

  • Construído sobre Radix Dialog — foco fica preso, Esc fecha e o fundo recebe inert enquanto o sheet está aberto.
  • SheetTitle e SheetDescription são associados via aria-labelledby e aria-describedby automaticamente.
  • O botão de fechar padrão inclui um span com sr-only garantindo nome acessível.
  • Respeita prefers-reduced-motion — o slide é substituído por um fade simples.