Animate
One typed attribute and wrapper API for identity-token motion, with a tiny SSR-safe runtime.
- Who is it for?
- Developers adding appear, scroll, press, longpress, hover or focus motion to any kit element.
- When should I use it?
- When a card, section or control should move on appear, scroll progress, press, longpress, hover or focus.
- When should I pick something else?
- For pinned scene crossfades use `ScrollScenes`. For section snap/smooth-scroll use `SectionScroll`. For first-paint class utilities see `Animate entrances and hover feedback with CSS utilities`.
Install or copy
This ships on npm only; there is no copy-source brick for it.
- You get
- Every component from one import, with the theme tokens included. Updates arrive with your package manager.
- You need
- React 19 and Tailwind CSS 4, for example a Next.js app created with the Tailwind option.
Install
Terminal pnpm add @zedtech/zedkit-uiLoad the styles
Tailwind does not scan node_modules, so the @source line points it at the kit's class names. The path is relative to this file.
src/app/globals.cssReplace the contents@import "tailwindcss"; @import "@zedtech/zedkit-ui/styles.css"; @source "../../node_modules/@zedtech/zedkit-ui/src/**/*.{ts,tsx}";Import and render
src/app/page.tsxReplace the contentsimport { AnimateObserver, Card } from "@zedtech/zedkit-ui"; export default function Page() { return ( <main className="p-8"> <AnimateObserver /> <Card data-animate="fade-up" data-animate-delay="100" data-animate-press="scale-down"> Invoice </Card> </main> ); }
Package version 1.6.2.
Usage and states
import { AnimateObserver, Card } from "@zedtech/zedkit-ui";
<AnimateObserver />
<Card data-animate="fade-up" data-animate-delay="100" data-animate-press="scale-down">
Invoice
</Card>Wrapper with several triggers
Hold to pulse. Scroll to shift.
import { Animate } from "@zedtech/zedkit-ui";
<Animate on={{ appear: "fade-up", press: "scale-down", longpress: "pulse", scroll: "parallax" }}>
Band
</Animate>Stagger children
Write the launch email
Review the product photos
Publish the sale banner
import { Animate, Stack, Text } from "@zedtech/zedkit-ui";
<Animate on={{ appear: "fade-up" }} stagger>
<Stack>
<Text>One</Text>
<Text>Two</Text>
</Stack>
</Animate>Wraps: (none)
Props
Prop
Type
Show inherited HTML attributes
Standard attributes from the underlying element. See MDN.
Prop
Type
Accessibility
prefers-reduced-motion: reduce leaves content visible and in place. Hover is gated to hover-capable pointers. Focus uses :focus-visible. Press ignores disabled. Longpress is decorative, never the only action. Appear does not set aria-hidden.
Troubleshooting
Nothing appears to move — mount `<AnimateObserver />` once near the app root (or call `observeAnimate()`), then check reduced motion and `data-motion` on `<html>`. Content stays visible without JS by design. Scroll parallax needs `animation-timeline: view()` or the runtime fallback. In-app reduce flashes on load — render `<MotionScript />` in `<head>` (same pattern as `IdentityScript`) so `data-motion="reduce"` is set before paint; `useMotionPreference()` is `"reduce"` on the server.
Triggers and tokens
One element can carry several triggers. Identities retune the same tokens
(--zk-reveal-duration, --zk-reveal-distance, --zk-reveal-ease,
--zk-stagger-step, --zk-lift-*, --zk-press-scale, --zk-longpress-ms).
| Trigger | Attribute | When |
|---|---|---|
| appear | data-animate / data-animate-appear | Enters the viewport once |
| scroll | data-animate-scroll | Progress through the viewport (view() timeline, rAF fallback) |
| press | data-animate-press | :active (not disabled) |
| longpress | data-animate-longpress | Pointer held --zk-longpress-ms |
| hover | data-animate-hover | :hover on hover-capable pointers |
| focus | data-animate-focus | :focus-visible |
Mount <AnimateObserver /> once near the app root so appear, the scroll
fallback, and longpress run. Press, hover and focus are CSS-only.
Reduced motion leaves everything visible and still. The attribute grammar
and trigger semantics live in packages/ui/docs/animate-spec.md.