A single store manages every sheet in your app. Fully typed, stack-based, composable. Powered by Zustand, Motion, and a bit of Radix. All wired up.
Install
pnpm add @howells/stacksheet
Position
Spring
Create
import { createStacksheet } from "@howells/stacksheet" // Optional: type your sheets for autocomplete. type Sheets = { settings: { heading: string } profile: { userId: string } } const { StacksheetProvider, useSheet, } = createStacksheet<Sheets>()
Define
import { Sheet } from "@howells/stacksheet" // Props are spread directly from the action call. function SettingsSheet({ heading }) { return ( <> <Sheet.Header> <Sheet.Title>{heading}</Sheet.Title> <Sheet.Close /> </Sheet.Header> <Sheet.Body> {/* Your content */} </Sheet.Body> </> ) }
Provide
import { StacksheetProvider } from "./stacksheet" import { SettingsSheet } from "./sheets/settings" // sheets is optional — you can also push // components directly without registering them. export default function Layout({ children }) { return ( <StacksheetProvider sheets={{ settings: SettingsSheet }} > {children} </StacksheetProvider> ) } // Ad-hoc: no registration needed. actions.push(ProfileSheet, { userId: "abc" })
Use
const { actions } = useSheet() // "settings" matches the key in your sheets map. // { heading } is spread as props onto SettingsSheet. actions.push("settings", { heading: "position" })