Whole-content state transitions
StateCut fades or slides between empty, error, success and other content states, while easing the container height. Use it with your own React markup.
Your inbox is clear
New messages will appear here.
An empty inbox becomes a list, a form becomes a confirmation, or an error is replaced by content. StateCut connects the old and new view with a fade or a short slide, and eases between their heights.
Install
npx shadcn add @keyframery/state-cutRegister @keyframery with the Quick start first. The helper installs the layer as a dependency; keep one <Cuts /> mounted in your root layout to enable motion.
Use
Change state when the view should transition. Keep the wrapper mounted and render your current content inside it:
import { StateCut } from "@/components/keyframery/state-cut"
<StateCut state={status} cut="fade">
{status === "success" ? <Confirmation /> : <OrderForm />}
</StateCut>The first render does not animate. Updating content without changing state does not start a new transition. Use a stable string or number that represents the view, rather than a random value on each render. A new state remounts the content boundary, so keep drafts or other data you need to retain in a parent component.
You should see
The new content fades or slides into place while the container eases to its height. Try Show messages, Show error, and Try again in the preview. Only the current view is interactive.
Options
Prop
Type
Choose the right helper
| What changes | Use |
|---|---|
| the whole content of a region: empty, error, success or another view | StateCut |
| a skeleton becomes loaded content, with a delay and minimum display time | LoadCut |
| a number, badge or short status label | ValueCut |
| items are added, removed or reordered in a list | ListCut |
StateCut does not fetch data or decide when to show a skeleton. Those decisions stay in your app.
Good to know
- It follows your theme's pace, entrance easing and exit easing, including scoped CSS variables.
cut="none", an ancestor withdata-cut="none", or a disabled layer swaps content without Keyframery motion.- An outgoing snapshot is hidden from assistive technology, inert and ignored by the pointer. Only the current React content remains interactive. Interrupted transitions cancel their old animations and snapshots.
- Reduced motion uses a short fade, without slide or height motion.
- StateCut does not move focus or announce the new view. Keep state controls outside the changing region, and add your app's own accessible status announcement or focus handling when the workflow needs it.
Questions
When should I use StateCut instead of LoadCut?
Use StateCut when a whole view changes state, such as a form becoming a confirmation. Use LoadCut when loading needs a skeleton with a delay and minimum display time.
Does StateCut respect reduced motion?
Yes. With reduced motion, StateCut uses opacity only, without sliding or animating the container height.
Loading states
Animate loading states in React with LoadCut: the skeleton dissolves into the content in the same space, and never flashes when the data is fast.
Icon moves
When a button, menu item or sidebar item is pressed, its lucide icon plays its own move: a gear turns, a bell rings, a lid lifts. No icon swap, no new imports.