Stacksheetv1.1.4

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.

sheets.ts
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.

app.tsx
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

On this page