Sheet
Painel ancorado à lateral para fluxos mais longos, construído sobre o Radix Dialog com slide-in direcional a partir de qualquer borda.
Visão geral
Sheet é um Radix Dialog estilizado como painel lateral. Use-o para conteúdo que não merece foco total como um Dialog, mas é rico demais para um Popover: bandejas de filtro, painéis de detalhe, configurações multi-seção, menus de navegação no mobile. A direção do slide é configurável por lado (top, right, bottom, left).
Para a ergonomia de desktop, prefira right (painéis de filtro e detalhe). left é convencional para navegação. Em breakpoints mobile, o Drawer costuma encaixar melhor porque adiciona gestos nativos de drag-to-dismiss.
Preview
'use client';import { Button } from '@gremorie/rx-forms';import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from '@gremorie/rx-overlays';export function SheetPreview() { return ( <Sheet> <SheetTrigger asChild> <Button variant="outline">Open sheet</Button> </SheetTrigger> <SheetContent> <SheetHeader> <SheetTitle>Filters</SheetTitle> <SheetDescription> Narrow down the registry by category and edition. </SheetDescription> </SheetHeader> </SheetContent> </Sheet> );}Anatomia
Sheet raiz Radix que mantém o estado de abertura
├─ SheetTrigger elemento que abre o sheet
└─ SheetContent painel deslizante em portal (side, showCloseButton)
├─ SheetHeader envolve título + descrição
│ ├─ SheetTitle headline
│ └─ SheetDescription texto do corpo
├─ SheetClose fecha o sheet
└─ SheetFooter linha de ações inferiorInstalação
bash npx gremorie@latest add rx-sheet bash pnpm dlx gremorie@latest add rx-sheet bash yarn dlx gremorie@latest add rx-sheet bash bunx --bun gremorie@latest add rx-sheet Uso
import { Button } from "@gremorie/rx-forms";
import {
Sheet,
SheetContent,
SheetDescription,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@gremorie/rx-overlays";
export function Example() {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="outline">Open filters</Button>
</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Filters</SheetTitle>
<SheetDescription>
Narrow down the registry by category and edition.
</SheetDescription>
</SheetHeader>
{/* filter controls */}
</SheetContent>
</Sheet>
);
}A edição Angular deste componente hoje é distribuída a partir do source (veja o workbench para o lado a lado); a entrada no registry vem a seguir.
API
<Sheet>
Estende o Radix Dialog.Root. Mesma API controlada do Dialog (open, defaultOpen, onOpenChange, modal).
<SheetContent>
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "right" | "bottom" | "left" | "right" | Borda contra a qual o sheet encaixa e a partir da qual desliza. |
showCloseButton | boolean | true | Renderiza o botão X de fechar no canto superior direito. |
Envolve o Radix Dialog.Content em um Portal com o overlay. A largura e a altura se adaptam à side:
right/left: altura total,w-3/4limitado asm:max-w-sm.top/bottom: largura total,h-auto.
<SheetHeader>, <SheetFooter>
Containers de layout com padding p-4. O header empilha título e descrição; o footer empurra para a parte inferior (mt-auto) com gap-2.
<SheetTitle>, <SheetDescription>
Mapeiam para o Radix Dialog.Title e Dialog.Description. Ambos são exigidos pelo Radix; renderize com className="sr-only" se visualmente ocultos.
<SheetTrigger>, <SheetClose>, <SheetOverlay>, <SheetPortal>
Pass-throughs sobre os primitivos do Radix com atributos data-slot.
Composição
<Sheet>detém o estado de aberto/fechado.<SheetTrigger asChild>envolve o elemento focável que o abre.<SheetContent side="right">monta via Portal, desenha o overlay, desliza a partir da borda escolhida.- Header carrega título e descrição; o corpo guarda o conteúdo principal; o footer fixa as ações primárias na parte inferior.
- Dispensa: clique no overlay, pressione
Esc, clique no X (showCloseButton) ou chameSheetClose.
Variações
Lados
SheetContent desliza a partir de qualquer borda via a prop side (top, right, bottom, left). Cada trigger abaixo abre o sheet a partir de uma borda diferente.
'use client';import { Button } from '@gremorie/rx-forms';import { Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle, SheetTrigger,} from '@gremorie/rx-overlays';const sides = ['top', 'right', 'bottom', 'left'] as const;export function SheetSidesPreview() { return ( <div className="flex flex-wrap gap-2"> {sides.map((side) => ( <Sheet key={side}> <SheetTrigger asChild> <Button variant="outline" className="capitalize"> {side} </Button> </SheetTrigger> <SheetContent side={side}> <SheetHeader> <SheetTitle className="capitalize">{side} sheet</SheetTitle> <SheetDescription> This sheet docks against the {side} edge and slides in from there. </SheetDescription> </SheetHeader> </SheetContent> </Sheet> ))} </div> );}Painel de filtros à direita
O padrão canônico de desktop. Formulário de filtro fixo, corpo com scroll, apply/reset no footer.
<Sheet>
<SheetTrigger asChild>
<Button variant="outline">Filters</Button>
</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Filters</SheetTitle>
</SheetHeader>
<div className="flex-1 overflow-auto px-4">{/* filter form */}</div>
<SheetFooter>
<Button variant="outline">Reset</Button>
<Button>Apply</Button>
</SheetFooter>
</SheetContent>
</Sheet>Drawer de navegação à esquerda
Emparelhe com um trigger de hambúrguer no mobile para a navegação primária.
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" aria-label="Open menu">
<MenuIcon />
</Button>
</SheetTrigger>
<SheetContent side="left">
<SheetHeader>
<SheetTitle>Navigation</SheetTitle>
</SheetHeader>
<nav className="px-4">{/* nav links */}</nav>
</SheetContent>
</Sheet>Painel de notificações inferior
Use side="bottom" para painéis transitórios que não merecem um modal centralizado (status do sistema, atividade recente).
<SheetContent side="bottom">
<SheetHeader>
<SheetTitle>Recent activity</SheetTitle>
</SheetHeader>
{/* activity feed */}
</SheetContent>Acessibilidade
- Role:
role="dialog"comaria-modal="true"(propmodalpadrão). - Teclado:
Escfecha;Tabcircula o foco dentro do content; o foco fica preso enquanto aberto. - Gestão de foco: o foco vai para o primeiro elemento focável na abertura e retorna ao trigger ao fechar.
- Title:
SheetTitleé obrigatório; sem ele o Radix loga um aviso. Usesr-onlyse precisar ocultá-lo visualmente. - Description: liga ao content via
aria-describedbyautomaticamente. - Reduced motion: as animações de slide respeitam
prefers-reduced-motionvia as utilidades animate do Tailwind subjacentes.
Relacionados
- Drawer - bottom sheet baseado em vaul com drag-to-dismiss para mobile.
- Dialog - modal centralizado para decisões focadas.
- Popover - overlay inline ancorado para pequenas UI contextuais.
- Navigation Menu - navegação de nível superior que não faz overlay.