Getting Started
Typed, animated sheet stacking for React. Powered by Zustand and Motion.
Stacksheet is a sheet stack manager for React. It gives you a hook to open, push, and navigate animated sheet panels from any component — with focus trapping, scroll lock, and keyboard navigation built in.
Quick start
1. Create an instance
createStacksheet() returns a provider and a hook. You'll typically do this once in a shared file and import them where needed.
import { createStacksheet } from "@howells/stacksheet";
export const { StacksheetProvider, useSheet } = createStacksheet();2. Add the provider
Wrap the part of your app that needs sheets. The provider renders the backdrop and panels — your app content goes inside as children.
import "@howells/stacksheet/styles.css";
import { StacksheetProvider } from "./sheets";
function App() {
return (
<StacksheetProvider>
<YourApp />
</StacksheetProvider>
);
}3. Open sheets from anywhere
Call open() with any React component and its props. The component renders inside a sheet panel that slides in from the right on desktop, or from the bottom on mobile.
import { useSheet } from "./sheets";
function UserProfile({ userId }: { userId: string }) {
return <div>User {userId}</div>;
}
function ViewProfileButton() {
const { open } = useSheet();
return (
<button onClick={() => open(UserProfile, { userId: "u_abc" })}>
View Profile
</button>
);
}The sheet panel includes a close button in the header by default. If your sheet component needs to close itself programmatically, use the close action from the hook:
function UserProfile({ userId }: { userId: string }) {
const { close } = useSheet();
return (
<div>
<h2>User {userId}</h2>
<button onClick={close}>Done</button>
</div>
);
}Complete example
Here's everything in a single file:
import { createStacksheet } from "@howells/stacksheet";
import "@howells/stacksheet/styles.css";
const { StacksheetProvider, useSheet } = createStacksheet();
function UserProfile({ userId }: { userId: string }) {
const { close } = useSheet();
return (
<div>
<h2>User {userId}</h2>
<button onClick={close}>Done</button>
</div>
);
}
function ViewProfileButton() {
const { open } = useSheet();
return (
<button onClick={() => open(UserProfile, { userId: "u_abc" })}>
View Profile
</button>
);
}
export default function App() {
return (
<StacksheetProvider>
<ViewProfileButton />
</StacksheetProvider>
);
}Next steps
- Installation — package managers and peer deps
- createStacksheet() — factory function and config options
- Hooks — all
useSheet()actions:open,push,navigate,pop,close, and more - Composable Parts — custom layouts with
Sheet.*components - Drag to Dismiss — swipe gestures and configuration
- Styling — CSS classes, custom properties, and custom headers