@slithy/modal-spring
v0.4.2
Published
React Spring animation adapter for @slithy/modal-kit.
Readme
@slithy/modal-spring
Animated modal adapter for @slithy/modal-kit, built on react-spring and @use-gesture/react.
Provides animated enter/leave transitions, an animated backdrop, and drag-to-close gesture support.
Installation
pnpm add @slithy/modal-core @slithy/modal-kit @slithy/modal-spring
pnpm add "@react-spring/web@>=9 <10" @use-gesture/react@react-spring/web (v9.x) and @use-gesture/react are peer dependencies. react-spring v10 is not yet supported.
Setup
import { LayerProvider, LayerStackPriority } from "@slithy/layers";
import { Portal } from "@slithy/portal";
import { ModalRenderer } from "@slithy/modal-spring";
export function App() {
return (
<LayerProvider id="app" zIndex={LayerStackPriority.App}>
<main>{/* your app */}</main>
<ModalRenderer
renderLayer={(children) => (
<LayerProvider id="modal" zIndex={LayerStackPriority.Modal}>
{children}
</LayerProvider>
)}
renderPortal={(children) => <Portal>{children}</Portal>}
/>
</LayerProvider>
);
}renderLayer and renderPortal are optional — omit them if you don't use @slithy/layers or @slithy/portal.
ModalRenderer props
| Prop | Type | Description |
| --------------- | ------------------------- | --------------------------------------------------- |
| renderLayer | (children) => ReactNode | Wrap all modals in a layer context |
| renderPortal | (children) => ReactNode | Wrap each modal in a portal |
| skipAnimation | boolean | Skip all animations. Intended for test environments |
Usage
import { useModalStore } from "@slithy/modal-core";
import { Modal } from "@slithy/modal-spring";
function MyButton() {
const open = (event: React.MouseEvent) => {
useModalStore.getState().openModal(
<Modal aria-label="My Modal">
<p>Content</p>
</Modal>,
{ triggerEvent: event },
);
};
return <button onClick={open}>Open</button>;
}Modal Props
| Prop | Type | Default | Description |
| -------------------------- | ------------------------------- | ---------- | ------------------------------------------------ |
| aria-label | string | — | Accessible name for the dialog |
| alignX | 'center' \| 'left' \| 'right' | 'center' | Horizontal position |
| alignY | 'middle' \| 'top' \| 'bottom' | 'middle' | Vertical position |
| dismissible | boolean | true | Allow Escape and backdrop-click to close |
| contentClassName | string | — | Class on the <dialog> element |
| contentStyle | CSSProperties | — | Static styles on the <dialog> element |
| contentTransitions | { from, enter, leave } | — | Spring transition values |
| disableOpacityTransition | boolean | — | Skip the default opacity fade |
| dragDirection | DragDirection | — | Enable drag-to-close |
| layerIsActive | boolean | true | Pass from useLayerState for layer coordination |
| springConfig | SpringConfig | — | Override the default spring config |
| afterOpen | () => void | — | Fires after enter animation completes |
| afterClose | () => void | — | Fires after modal is removed |
useModalState
Reads per-modal context from inside a modal component. Re-exported from @slithy/modal-kit for convenience.
import { useModalState } from "@slithy/modal-spring";
const modalId = useModalState((s) => s.modalId);See @slithy/modal-kit docs for the full API.
Exports
| Export | Description |
| ------------------ | ----------------------------------------------------- |
| Modal | Animated modal component |
| ModalProps | — |
| ModalRenderer | Renders all open modals with animated backdrop |
| ModalBackdrop | Animated backdrop (used by ModalRenderer) |
| DragHandle | Drag-to-close gesture wrapper |
| useModalDrag | Low-level drag hook |
| useModalDragging | Internal drag spring hook |
| useModalState | Per-modal context hook — re-exported from modal-kit |
| defaultSpring | Default spring config |
| iosSheetSpring | iOS-feel spring config |
| DragDirection | 'up' \| 'down' \| 'left' \| 'right' |
| DragStyles | Spring transform values from drag |
