Kinetic Presets
122 ready-to-use animation presets, 5 customizable factories, and composition utilities for @vitus-labs/kinetic.
@vitus-labs/kinetic-presets provides a comprehensive library of 122 animation presets organized into 25 categories, plus 5 factory functions for creating custom presets and 5 composition utilities.
Installation
npm install @vitus-labs/kinetic-presetsPeer dependencies: react >= 18, @vitus-labs/kinetic
Try It Live
Pick a preset and toggle visibility — the box will animate in and out using the selected preset's enter/leave config:
function PresetGallery() { const presets = { fadeUp: { enter: { opacity: 0, transform: 'translateY(20px)' }, enterTo: { opacity: 1, transform: 'translateY(0)' }, leave: { opacity: 1, transform: 'translateY(0)' }, leaveTo: { opacity: 0, transform: 'translateY(20px)' }, transition: 'all 350ms cubic-bezier(0.4, 0, 0.2, 1)', }, slideRight: { enter: { opacity: 0, transform: 'translateX(-30px)' }, enterTo: { opacity: 1, transform: 'translateX(0)' }, leave: { opacity: 1, transform: 'translateX(0)' }, leaveTo: { opacity: 0, transform: 'translateX(-30px)' }, transition: 'all 350ms cubic-bezier(0.4, 0, 0.2, 1)', }, scaleIn: { enter: { opacity: 0, transform: 'scale(0.85)' }, enterTo: { opacity: 1, transform: 'scale(1)' }, leave: { opacity: 1, transform: 'scale(1)' }, leaveTo: { opacity: 0, transform: 'scale(0.85)' }, transition: 'all 350ms cubic-bezier(0.34, 1.56, 0.64, 1)', }, rotateIn: { enter: { opacity: 0, transform: 'rotate(-180deg) scale(0.5)' }, enterTo: { opacity: 1, transform: 'rotate(0deg) scale(1)' }, leave: { opacity: 1, transform: 'rotate(0deg) scale(1)' }, leaveTo: { opacity: 0, transform: 'rotate(180deg) scale(0.5)' }, transition: 'all 450ms cubic-bezier(0.4, 0, 0.2, 1)', }, flipX: { enter: { opacity: 0, transform: 'perspective(400px) rotateX(90deg)' }, enterTo: { opacity: 1, transform: 'perspective(400px) rotateX(0deg)' }, leave: { opacity: 1, transform: 'perspective(400px) rotateX(0deg)' }, leaveTo: { opacity: 0, transform: 'perspective(400px) rotateX(-90deg)' }, transition: 'all 400ms ease-out', }, bounceIn: { enter: { opacity: 0, transform: 'scale(0.3)' }, enterTo: { opacity: 1, transform: 'scale(1)' }, leave: { opacity: 1, transform: 'scale(1)' }, leaveTo: { opacity: 0, transform: 'scale(0.3)' }, transition: 'all 500ms cubic-bezier(0.68, -0.55, 0.265, 1.55)', }, } const [name, setName] = React.useState('fadeUp') const [show, setShow] = React.useState(true) const ref = React.useRef(null) const preset = presets[name] React.useEffect(() => { const el = ref.current if (!el) return if (show) { Object.assign(el.style, preset.enter) el.style.transition = '' requestAnimationFrame(() => requestAnimationFrame(() => { el.style.transition = preset.transition Object.assign(el.style, preset.enterTo) })) } else { el.style.transition = preset.transition Object.assign(el.style, preset.leaveTo) } }, [show, name, preset]) return ( <div style={{ fontFamily: 'system-ui' }}> <div style={{ display: 'flex', gap: 8, marginBottom: 16, flexWrap: 'wrap' }}> {Object.keys(presets).map(key => ( <button key={key} type="button" onClick={() => { setShow(false); setTimeout(() => { setName(key); setShow(true) }, 400) }} style={{ padding: '6px 12px', borderRadius: 6, border: 'none', background: name === key ? '#0d6efd' : '#e9ecef', color: name === key ? 'white' : '#212529', cursor: 'pointer', fontSize: 13, fontWeight: 500, }} > {key} </button> ))} </div> <button type="button" onClick={() => setShow(s => !s)} style={{ padding: '6px 14px', borderRadius: 6, border: '1px solid #adb5bd', background: 'transparent', color: '#495057', cursor: 'pointer', fontSize: 13, marginBottom: 16, }} > {show ? 'Hide' : 'Show'} </button> <div style={{ minHeight: 120, display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#f8f9fa', borderRadius: 8, padding: 24 }}> <div ref={ref} style={{ width: 100, height: 100, background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)', borderRadius: 12, display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white', fontWeight: 600, fontSize: 14, }} > {name} </div> </div> </div> ) }
Quick Start
import { kinetic } from '@vitus-labs/kinetic'
import { fadeUp, scaleIn, compose, withDuration } from '@vitus-labs/kinetic-presets'
// Use a preset directly
const FadeCard = kinetic('div').preset(fadeUp)
// Customize duration
const SlowFade = kinetic('div').preset(withDuration(fadeUp, 500))
// Compose multiple effects
const FadeScale = kinetic('div').preset(compose(fadeUp, scaleIn))Or use with the <Transition> component:
import { Transition } from '@vitus-labs/kinetic'
import { slideUp } from '@vitus-labs/kinetic-presets'
<Transition show={visible} {...slideUp}>
<div>Animated content</div>
</Transition>Preset Categories
All 122 presets are organized into 25 categories:
| Category | Count | Examples |
|---|---|---|
| Fades | 14 | fade, fadeUp, fadeDownBig, fadeUpLeft |
| Slides | 8 | slideUp, slideDown, slideLeftBig |
| Scales | 9 | scaleIn, scaleUp, scaleDown, scaleRotateIn |
| Blurs | 6 | blurIn, blurInDown, blurScale |
| Bounces | 5 | bounceIn, bounceInDown, bounceInLeft |
| Rotations | 4 | rotateIn, rotateInReverse, rotateInDown |
| Flips | 6 | flipX, flipY, flipDiagonal |
| Zooms | 10 | zoomIn, zoomOut, zoomInDown, zoomOutLeft |
| Clip Path | 8 | clipCircle, clipDiamond, clipCenter |
| Perspective | 4 | perspectiveUp, perspectiveDown |
| Swings | 4 | swingInTop, swingInBottom, swingInLeft |
| Tilts | 4 | tiltInUp, tiltInDown, tiltInLeft |
| Floats | 4 | floatUp, floatDown, floatLeft |
| Flies | 4 | flyInUp, flyInDown, flyInLeft |
| Light Speed | 2 | lightSpeedInLeft, lightSpeedInRight |
| Back | 4 | backInUp, backInDown, backInLeft |
| Pushes | 2 | pushInLeft, pushInRight |
| Rolls | 2 | rollInLeft, rollInRight |
| Swirls | 2 | swirlIn, swirlInReverse |
| Slits | 2 | slitHorizontal, slitVertical |
| Expand | 2 | expandX, expandY |
| Squish | 2 | squishX, squishY |
| Skews | 4 | skewIn, skewInReverse, skewInY |
| Special | 8 | popIn, puffIn, rubberIn, newspaperIn, springIn, spinIn |
| Drop/Rise | 2 | drop, rise |
Factories
5 factory functions create custom presets with full control over timing, easing, and parameters:
| Factory | Creates | Key Options |
|---|---|---|
createFade | Fade with optional direction | direction, distance, duration |
createSlide | Directional slide | direction, distance, duration |
createScale | Scale transform | from, duration, easing |
createRotate | Rotation | degrees, duration, easing |
createBlur | Blur + optional scale | amount, scale, duration |
Composition Utilities
5 utility functions modify and combine presets:
| Utility | Description | Example |
|---|---|---|
compose | Merge multiple presets into one | compose(fade, slideUp) |
withDuration | Override enter/leave duration | withDuration(fade, 500, 200) |
withEasing | Override enter/leave easing | withEasing(fade, 'ease-in-out') |
withDelay | Add delay to transitions | withDelay(fade, 100) |
reverse | Swap enter and leave animations | reverse(slideUp) |
Common Patterns
Page Section Reveal
Animate sections as users scroll into view:
import { kinetic } from '@vitus-labs/kinetic'
import { fadeUp, withDuration, withEasing } from '@vitus-labs/kinetic-presets'
import { useIntersection } from '@vitus-labs/hooks'
const RevealSection = kinetic('section')
.preset(withEasing(withDuration(fadeUp, 600), 'cubic-bezier(0.16, 1, 0.3, 1)'))
function HeroSection({ children }) {
const [ref, entry] = useIntersection({ threshold: 0.2 })
const visible = entry?.isIntersecting ?? false
return (
<div ref={ref}>
<RevealSection show={visible} appear>
{children}
</RevealSection>
</div>
)
}Tooltip with Directional Presets
Choose the animation based on placement:
import { kinetic } from '@vitus-labs/kinetic'
import { fadeUp, fadeDown, fadeLeft, fadeRight } from '@vitus-labs/kinetic-presets'
const presetMap = {
top: fadeDown, // tooltip above: slides down into view
bottom: fadeUp, // tooltip below: slides up into view
left: fadeRight, // tooltip left: slides right into view
right: fadeLeft, // tooltip right: slides left into view
}
function Tooltip({ show, placement = 'top', children }) {
const Component = kinetic('div').preset(presetMap[placement])
return (
<Component show={show} role="tooltip">
{children}
</Component>
)
}Sequential Feature Cards
import { kinetic } from '@vitus-labs/kinetic'
import { bounceIn, withDelay } from '@vitus-labs/kinetic-presets'
const StaggerCards = kinetic('div')
.preset(bounceIn)
.stagger({ interval: 80, reverseLeave: true })
function Features({ features, visible }) {
return (
<StaggerCards show={visible} appear>
{features.map((f) => (
<div key={f.id} className="feature-card">
<h3>{f.title}</h3>
<p>{f.description}</p>
</div>
))}
</StaggerCards>
)
}Animated Route Transitions
import { kinetic } from '@vitus-labs/kinetic'
import { fade, slideLeft, compose, withDuration } from '@vitus-labs/kinetic-presets'
const PageTransition = kinetic('div').preset(
withDuration(compose(fade, slideLeft), 200, 150)
)
// In your layout
function Layout({ children, routeKey }) {
return (
<PageTransition show={true} appear key={routeKey}>
<main>{children}</main>
</PageTransition>
)
}How Presets Work
A preset is a plain object with enter/leave style and class definitions:
// This is what fadeUp looks like internally:
const fadeUp = {
enterStyle: { opacity: 0, transform: 'translateY(16px)' },
enterToStyle: { opacity: 1, transform: 'translateY(0)' },
enterTransition: 'all 300ms ease-out',
leaveStyle: { opacity: 1, transform: 'translateY(0)' },
leaveToStyle: { opacity: 0, transform: 'translateY(16px)' },
leaveTransition: 'all 200ms ease-in',
}All 122 presets follow this symmetric pattern (leave reverses enter). The library uses a compact internal helper that generates both directions from a single pair of states, keeping the bundle small despite the large number of presets.
Tree-Shaking
All 122 presets are individually exported for tree-shaking. Import only what you use:
// Only bundles fadeUp and scaleIn — everything else is eliminated
import { fadeUp, scaleIn } from '@vitus-labs/kinetic-presets'The presets object re-exports everything as a single object (useful for exploration/debugging), but prefer named imports for production builds.
Exports
import {
// Factories
createFade,
createSlide,
createScale,
createRotate,
createBlur,
// Utilities
compose,
withDuration,
withEasing,
withDelay,
reverse,
// All 122 presets (named exports)
fade,
fadeUp,
fadeDown,
// ... see full list in Presets Reference
// All presets as object
presets,
} from '@vitus-labs/kinetic-presets'
import type {
Preset,
Direction,
FadeOptions,
SlideOptions,
ScaleOptions,
RotateOptions,
BlurOptions,
} from '@vitus-labs/kinetic-presets'