Offcanvas panels (drawers / sheets) provide premium, enterprise-grade side panels for filters, details, multi-step workflows, and notification centers.
New: Program and Premium variants are draggable-resizable (no library) and not dismissible by default (no Escape / no backdrop click). You must close them explicitly.
Two triggers. In floating mode, Program + Premium panels resize from the side (width) and from the bottom (height). Snaps + persistence included.
import { Button } from "@/design-system/components/Button";
import {
Offcanvas, OffcanvasTrigger, OffcanvasContent,
OffcanvasHeader, OffcanvasTitle, OffcanvasDescription,
OffcanvasBody, OffcanvasFooter, OffcanvasClose
} from "@/design-system/components/Offcanvas";
export function Example() {
return (
<div style={{ display: "flex", gap: 12, flexWrap: "wrap", alignItems: "center" }}>
{/* Premium (resizable: width + height in floating mode) */}
<Offcanvas>
<OffcanvasTrigger asChild>
<Button variant="primary">Open draggable premium</Button>
</OffcanvasTrigger>
<OffcanvasContent
placement="right"
backdrop="glass"
variant="premium"
mode="floating"
size="lg"
tone="primary"
persistKey="docs:offcanvas:draggable:premium:right"
closeOnEscape={false}
closeOnBackdropClick={false}
// Optional: explicit starting sizes for a clear “expandable” feel
defaultSizePx={360}
defaultBlockSizePx={640}
resizeSnapPoints={[360, 420, 560, 720]}
resizeSnapPointsBlock={[420, 520, 640, 760]}
>
<OffcanvasHeader>
<div>
<OffcanvasTitle>Premium Panel</OffcanvasTitle>
<OffcanvasDescription>
Drag left edge for width + bottom edge for height. Snaps on release.
</OffcanvasDescription>
</div>
<OffcanvasClose asChild>
<Button variant="ghost" iconOnly aria-label="Close" />
</OffcanvasClose>
</OffcanvasHeader>
<OffcanvasBody>
Put content here. Tip: focus the resize edges and use arrow keys (Home/End supported).
</OffcanvasBody>
<OffcanvasFooter>
<Button variant="ghost">Back</Button>
<Button variant="primary">Confirm</Button>
</OffcanvasFooter>
</OffcanvasContent>
</Offcanvas>
{/* Program (resizable: width + height in floating mode) */}
<Offcanvas>
<OffcanvasTrigger asChild>
<Button variant="outline">Open draggable program</Button>
</OffcanvasTrigger>
<OffcanvasContent
placement="left"
backdrop="dim"
variant="program"
mode="floating"
size="md"
persistKey="docs:offcanvas:draggable:program:left"
closeOnEscape={false}
closeOnBackdropClick={false}
defaultSizePx={380}
defaultBlockSizePx={620}
resizeSnapPoints={[360, 420, 560, 720]}
resizeSnapPointsBlock={[420, 520, 620, 740]}
>
<OffcanvasHeader>
<div>
<OffcanvasTitle>Program Panel</OffcanvasTitle>
<OffcanvasDescription>
Enterprise “tool window” UX: resize from side + bottom, keyboard accessible.
</OffcanvasDescription>
</div>
<OffcanvasClose asChild>
<Button variant="ghost" iconOnly aria-label="Close" />
</OffcanvasClose>
</OffcanvasHeader>
<OffcanvasBody>
Great for logs, diagnostics, inspectors, power-user tooling, and admin consoles.
</OffcanvasBody>
<OffcanvasFooter>
<Button variant="ghost">Clear</Button>
<Button variant="primary">Run</Button>
</OffcanvasFooter>
</OffcanvasContent>
</Offcanvas>
</div>
);
}
Right placement + blur backdrop + sticky header/footer. Escape and backdrop click close by default.
import { Button } from "@/design-system/components/Button";
import {
Offcanvas, OffcanvasTrigger, OffcanvasContent,
OffcanvasHeader, OffcanvasTitle, OffcanvasDescription,
OffcanvasBody, OffcanvasFooter, OffcanvasClose
} from "@/design-system/components/Offcanvas";
export function Example() {
return (
<Offcanvas>
<OffcanvasTrigger asChild>
<Button variant="primary">Open</Button>
</OffcanvasTrigger>
<OffcanvasContent placement="right" backdrop="blur" variant="surface">
<OffcanvasHeader>
<div>
<OffcanvasTitle>Filters</OffcanvasTitle>
<OffcanvasDescription>Refine results for the current view.</OffcanvasDescription>
</div>
<OffcanvasClose asChild>
<Button variant="ghost" iconOnly aria-label="Close">
{/* X icon */}
</Button>
</OffcanvasClose>
</OffcanvasHeader>
<OffcanvasBody>
<div className="offcanvas-copy">Put form fields, checkboxes, etc here.</div>
</OffcanvasBody>
<OffcanvasFooter>
<Button variant="ghost">Reset</Button>
<Button variant="primary">Apply</Button>
</OffcanvasFooter>
</OffcanvasContent>
</Offcanvas>
);
}
Premium enterprise panel with accent hairline + inner frame. Drag edge to resize (or keyboard resize). Not dismissible by default.
import { Button } from "@/design-system/components/Button";
import {
Offcanvas, OffcanvasTrigger, OffcanvasContent,
OffcanvasHeader, OffcanvasTitle, OffcanvasDescription,
OffcanvasBody, OffcanvasFooter, OffcanvasClose
} from "@/design-system/components/Offcanvas";
export function Example() {
return (
<Offcanvas>
<OffcanvasTrigger asChild>
<Button variant="primary">Open premium panel</Button>
</OffcanvasTrigger>
<OffcanvasContent
placement="right"
backdrop="glass"
variant="premium"
mode="floating"
size="lg"
tone="primary"
persistKey="docs:offcanvas:premium:right"
>
<OffcanvasHeader>
<div>
<OffcanvasTitle>Review & Confirm</OffcanvasTitle>
<OffcanvasDescription>
Premium panels are resizable and require explicit close by default.
Floating premium panels can resize width + height (bottom drag).
</OffcanvasDescription>
</div>
<OffcanvasClose asChild>
<Button variant="ghost" iconOnly aria-label="Close">
{/* X icon */}
</Button>
</OffcanvasClose>
</OffcanvasHeader>
<OffcanvasBody>
<div className="offcanvas-muted">
Drag the panel edge to resize (or focus the edge handle and use arrow keys).
</div>
</OffcanvasBody>
<OffcanvasFooter>
<Button variant="ghost">Back</Button>
<Button variant="primary">Confirm</Button>
</OffcanvasFooter>
</OffcanvasContent>
</Offcanvas>
);
}
A “pro tool window” look: branded gradient, precise borders, subtle grid. Perfect for admin tools, logs, diagnostics, and power-user workflows. Not dismissible by default.
import { Button } from "@/design-system/components/Button";
import {
Offcanvas, OffcanvasTrigger, OffcanvasContent,
OffcanvasHeader, OffcanvasTitle, OffcanvasDescription,
OffcanvasBody, OffcanvasFooter, OffcanvasClose
} from "@/design-system/components/Offcanvas";
export function Example() {
return (
<Offcanvas>
<OffcanvasTrigger asChild>
<Button variant="outline">
Open program panel
</Button>
</OffcanvasTrigger>
<OffcanvasContent
placement="right"
backdrop="dim"
variant="program"
mode="floating"
size="md"
persistKey="docs:offcanvas:program:right"
>
<OffcanvasHeader>
<div>
<OffcanvasTitle>Diagnostics Console</OffcanvasTitle>
<OffcanvasDescription>
Program panels are resizable and require explicit close by default.
Floating program panels can resize width + height (bottom drag).
</OffcanvasDescription>
</div>
<OffcanvasClose asChild>
<Button variant="ghost" iconOnly aria-label="Close">
{/* X icon */}
</Button>
</OffcanvasClose>
</OffcanvasHeader>
<OffcanvasBody>
<div className="offcanvas-copy">
Ideal for audit logs, sync status, integration traces, or “inspector-like”
debugging panels in enterprise admin UIs.
</div>
</OffcanvasBody>
<OffcanvasFooter>
<Button variant="ghost">Clear</Button>
<Button variant="primary">Run</Button>
</OffcanvasFooter>
</OffcanvasContent>
</Offcanvas>
);
}
Left, right, bottom sheet, and top drawer — same component, consistent behavior.
// See source: placements examples in this docs page.Backdrop can be none, dim, blur, or glass. Note: program/premium panels are not dismissible via backdrop by default.
// Backdrop is configured via: backdrop="none" | "dim" | "blur" | "glass"Glass / neumorphic variants support premium visuals. Floating mode adds margins + card radius.
// variant="surface" | "glass" | "neumorphic" | "program" | "premium"
// mode="attached" | "floating"
// program + premium: resizable + explicit close by defaultA powerful admin UX pattern: the panel is fixed and usable while the page remains interactive (no backdrop, no focus trap).
import { Button } from "@/design-system/components/Button";
import {
Offcanvas, OffcanvasTrigger, OffcanvasContent,
OffcanvasHeader, OffcanvasTitle, OffcanvasDescription,
OffcanvasBody, OffcanvasClose
} from "@/design-system/components/Offcanvas";
export function Example() {
return (
<Offcanvas>
<OffcanvasTrigger asChild>
<Button variant="outline">Open inspector</Button>
</OffcanvasTrigger>
<OffcanvasContent
modal={false}
placement="right"
mode="floating"
size="sm"
variant="surface"
>
<OffcanvasHeader>
<div>
<OffcanvasTitle>Inspector</OffcanvasTitle>
<OffcanvasDescription>Live details for the selected item.</OffcanvasDescription>
</div>
<OffcanvasClose asChild>
<Button variant="ghost" iconOnly aria-label="Close">
{/* X icon */}
</Button>
</OffcanvasClose>
</OffcanvasHeader>
<OffcanvasBody>
<div className="offcanvas-muted">
Non-modal panels keep the page interactive—great for “details/inspector” UX.
</div>
</OffcanvasBody>
</OffcanvasContent>
</Offcanvas>
);
}