Hooks
useSheet() and useStacksheetState() API reference.
useSheet()
Returns the full set of sheet actions. Must be used within <StacksheetProvider>.
const { open, push, replace, swap, navigate, setData, remove, pop, close } =
useSheet();open(Component, data)
Replace the stack with a single sheet. Any existing sheets are removed.
open(UserProfile, { userId: "u_abc" });
// With explicit id (for later setData/remove)
open(UserProfile, "user-1", { userId: "u_abc" });push(Component, data)
Push a new sheet onto the stack. The current top sheet scales down with a depth effect. At maxDepth, replaces the top instead.
push(SettingsSheet, { tab: "billing" });replace(Component, data)
Swap the top sheet without changing stack depth. If the stack is empty, opens a new sheet.
replace(UserProfile, { userId: "u_xyz" });swap(Component, data)
Swap the top panel's content in place — no animation. The panel frame stays in place: same id, same position, same stacking. Only the inner component and props change. React reconciles without an AnimatePresence transition.
swap(SettingsSheet, { tab: "general" });This is useful for tab-like navigation within a single sheet where you want instant content changes without slide animations.
If the stack is empty, swap is a no-op.
navigate(Component, data)
Smart routing that decides based on current stack state:
| Stack state | Same component on top? | Result |
|---|---|---|
| Empty | — | open() |
| Non-empty | Yes | replace() |
| Non-empty | No | push() |
navigate(SettingsSheet, { tab: "general" });setData(Component, id, data)
Update data on an already-open sheet by id. No animation — only the content re-renders.
setData(UserProfile, "user-1", { userId: "u_new" });remove(id)
Remove a specific sheet from anywhere in the stack by id. Closes the stack if it was the last one.
remove("notification-1");pop()
Remove the top sheet. The sheet below expands back with a spring animation.
pop();close()
Clear the entire stack and close.
close();useStacksheetState()
Returns reactive sheet state. Re-renders when the stack or open state changes. Must be used within <StacksheetProvider>.
const { stack, isOpen } = useStacksheetState();| Property | Type | Description |
|---|---|---|
stack | SheetItem[] | Current sheet stack, ordered bottom to top |
isOpen | boolean | Whether any sheets are currently visible |
Each item in stack is a SheetItem:
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for this sheet instance |
type | string | Internal type key (component name or registry key) |
data | Record<string, unknown> | Data payload |
function SheetIndicator() {
const { stack, isOpen } = useStacksheetState();
return (
<span>
{isOpen ? `${stack.length} sheets open` : "closed"}
</span>
);
}useSheetPanel()
Returns the current panel's context. Must be called inside a component rendered by the sheet stack (works in both classic and composable mode).
import { useSheetPanel } from "@howells/stacksheet";
const { close, back, isNested, isTop, panelId, side } = useSheetPanel();| Property | Type | Description |
|---|---|---|
close | () => void | Close the entire sheet stack |
back | () => void | Pop the top sheet (go back one level) |
isNested | boolean | Whether the stack has more than one sheet |
isTop | boolean | Whether this is the top (active) sheet |
panelId | string | Unique ID prefix for ARIA linking |
side | Side | Current resolved side ("left" | "right" | "bottom") |
This is the hook that powers the Sheet.* composable parts. Use it when you need panel-level context for custom controls. See Composable Parts for the full guide.