6.5 KiB
Sheet
(no submodules)
- sheet.variants — `sheetOverlayVariants`, `sheetCont…-
sheet.variants —
sheetOverlayVariants,sheetContentVariants,sheetHeaderVariants,sheetFooterVariants,sheetTitleVariants, `sh… -
sheet.variants —
sheetOverlayVariants, `sheetCont… -
sheet.variants —
sheetOverlayVariants,sheetContentVariants,sheetHeaderVariants,sheetFooterVariants,sheetTitleVariants, `sh… -
sheet.variants —
sheetOverlayVariants, `sheetCont… -
sheet.variants —
sheetOverlayVariants,sheetContentVariants,sheetHeaderVariants,sheetFooterVariants,sheetTitleVariants, `sh… -
sheet.variants —
sheetOverlayVariants, `sheetCont… -
sheet.variants —
sheetOverlayVariants,sheetContentVariants,sheetHeaderVariants,sheetFooterVariants,sheetTitleVariants, `sh… -
sheet.variants —
sheetOverlayVariants,sheetContentVariants,sheetHeaderVariants,sheetFooterVariants,sheetTitleVariants, `sh…
Purpose
<Sheet> and its sub-components (<SheetTrigger>, <SheetPortal>, <SheetOverlay>, <SheetContent>, <SheetHeader>, <SheetFooter>, <SheetTitle>, <SheetDescription>, <SheetClose>) are the chassis side-anchored panel primitives built on @radix-ui/react-dialog. Sheet is structurally a Dialog with side-anchored positioning, so Radix supplies the same WAI-ARIA dialog semantics (focus-trap, restore-focus, Escape closes, click-outside closes) and the chassis adds a side axis on <SheetContent> (top / right / bottom / left).
Per the WAI-ARIA dialog pattern, every sheet MUST contain a <SheetTitle> so the accessible name is announced. Use className="sr-only" if the visible UI does not need a heading. Logical-property edges (start-0 / end-0) ensure left and right automatically swap under dir="rtl".
Features
- Four side anchors (
top,right,bottom,left) with matching slide-in/slide-out animations. - Focus-trap on open; restore-focus on close (Radix-managed).
- Escape closes; click on the overlay backdrop closes the sheet.
- Translated close-button
aria-labelviareact-ui.sheet.close(Close / 关闭 / إغلاق / Cau / Закрыть). - Theme-driven cva overrides for every slot via
useThemedVariants("Sheet<Slot>"). - All sub-components forward refs to their underlying Radix elements.
motion-reduce:animate-nonecollapses the slide animation underprefers-reduced-motion: reduce.- Logical-property anchoring (
start-0/end-0) soleftandrightflip in RTL automatically.
Usage: Basic Example
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@suaveplan/react-ui";
export function FiltersSheet() {
return (
<Sheet>
<SheetTrigger>Filters</SheetTrigger>
<SheetContent side="right">
<SheetHeader>
<SheetTitle>Filters</SheetTitle>
<SheetDescription>Refine the results.</SheetDescription>
</SheetHeader>
<SheetFooter>
<SheetClose>Apply</SheetClose>
</SheetFooter>
</SheetContent>
</Sheet>
);
}
Usage: Advanced Example
import {
Button,
Sheet,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@suaveplan/react-ui";
import { useState } from "react";
interface NavItem {
readonly id: string;
readonly label: string;
}
export function MobileNavSheet({ items }: { items: readonly NavItem[] }) {
const [open, setOpen] = useState(false);
return (
<Sheet open={open} onOpenChange={setOpen}>
<SheetTrigger asChild>
<Button variant="outline">Open menu</Button>
</SheetTrigger>
<SheetContent side="left">
<SheetHeader>
<SheetTitle>Navigation</SheetTitle>
<SheetDescription>Browse the app.</SheetDescription>
</SheetHeader>
<nav className="mt-4 flex flex-col gap-1">
{items.map((item) => (
<a
key={item.id}
href={`#${item.id}`}
className="rounded px-3 py-2 hover:bg-accent"
onClick={() => setOpen(false)}
>
{item.label}
</a>
))}
</nav>
</SheetContent>
</Sheet>
);
}
API Reference
<Sheet>
Renders the Radix Dialog Root. Same lifecycle props as <Dialog>.
<SheetContent>
| Prop | Type | Default | Description |
|---|---|---|---|
side |
"top" | "right" | "bottom" | "left" |
"right" |
Anchor edge (RTL flips left/right). |
closeAriaLabelKey |
TranslationKey |
react-ui.sheet.close |
Override the close-button accessible name. |
<SheetTitle>
REQUIRED — Radix surfaces a dev warning when omitted. Render className="sr-only" if no visible heading is needed.
<SheetTrigger>, <SheetPortal>, <SheetOverlay>, <SheetHeader>, <SheetFooter>, <SheetDescription>, <SheetClose>
Same as Dialog's analogous sub-components — direct re-exports of the Radix sub-components with the chassis cva applied.
Implementation Notes
- The Radix Content props type is a discriminated union once cva-extra variant props (
side) are layered on; TS cannot narrow the spread back through the chassis surface, so<SheetContent>casts the Radix Content to a relaxed shape viaunknown. The runtime accepts both shapes equivalently. This mirrors the Wave 3b ToggleGroup reconciliation finding and is documented in the implementation comment. - The chassis NEVER assigns a numeric
z-indexto the overlay or content — Radix portals handle stacking. start-0/end-0are logical properties —left/rightautomatically swap in RTL without a chevron-flip step.motion-reduce:animate-none motion-reduce:transition-nonecollapses both the slide and the duration transitions underprefers-reduced-motion: reduce.<SheetContent>self-portals via<SheetPortal>so consumers do not need to remember to portal manually — matches the shadcn upstream convention exactly.