Drop-in web components with spring-physics animations. Works in any framework - or no framework at all.
Architected with animation as a core concern from day one - not bolted on as an afterthought. Every component leverages spring physics, interruptible animations, and composable primitives to deliver interactions that feel natural and responsive.
▸ Reveal elements on scroll ▸ Hover/press/tilt responses ▸ Character-by-character text effects ▸ Parallax & scroll scenes ▸ Sliders, dialogs, image comparisons & more
Built with Motion and Lit. Full TypeScript types included.
1. Install
npm install motion-components2. Import & use
// Import all components
import 'motion-components'
// Import separate components (tree shakable)
import 'motion-components/motion-reveal'
import 'motion-components/motion-hover'
import 'motion-components/motion-stagger'
// Prevent content flash before animations run
import 'motion-components/preload.css'<motion-reveal>
<h1>Animates in when scrolled into view</h1>
</motion-reveal>
<motion-hover scale="1.05">
<button>Hover me</button>
</motion-hover>
<motion-stagger interval="0.06">
<p>First child</p>
<p>Second child</p>
<p>Third child</p>
</motion-stagger><script type="module" src="https://cdn.jsdelivr.net/npm/motion-components/dist/index.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/motion-components/dist/preload.css" />
<motion-reveal>
<h1>Animates in when scrolled into view</h1>
</motion-reveal>| Framework | Config needed? |
|---|---|
| Astro, Svelte, Solid, Preact | None |
| React | Use React 19+ (native web component support). React 18 has limited support - upgrade if possible. |
| Vue 3 | Tell the compiler to treat motion-* as custom elements |
| Angular | Add CUSTOM_ELEMENTS_SCHEMA |
| Plain HTML | Use the CDN script tag above |
Vue 3 config
// vite.config.js
vue({
template: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('motion-'),
},
},
})Angular config
import { CUSTOM_ELEMENTS_SCHEMA, Component } from '@angular/core'
@Component({
schemas: [CUSTOM_ELEMENTS_SCHEMA],
})
export class MyComponent {}Entrance & transition effects
motion-reveal motion-stagger motion-blur motion-blur-in
Input-driven interactivity
motion-hover motion-press motion-magnetic motion-tilt
Typography & character effects
motion-split motion-typewriter motion-counter motion-scramble
motion-ticker motion-words motion-curve motion-circle
motion-arc motion-headline motion-glitch motion-gravity
motion-liquid motion-perspective motion-stretch motion-text-mask
motion-font
Scroll-driven animation
motion-parallax motion-scene
Ready-made interactive components
motion-slider motion-gallery motion-dialog motion-countdown
motion-spotlight motion-progress motion-image-compare motion-flip-card
Syntax-highlighted code display
motion-code motion-code-inline
Import note:
motion-codelives atmotion-components/code-windowandmotion-code-inlineatmotion-components/code-inline. The subpath names differ from the tag names.
Web components upgrade asynchronously, so content can flash before animations are ready. Choose your prevention method:
import 'motion-components/preload.css'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/motion-components/dist/preload.css" />import { preload } from 'motion-components'
preload(['motion-reveal', 'motion-split', 'motion-dialog'])Call preload() with no arguments to cover all preload-registered components.
import { preloadCSS } from 'motion-components'
// inject preloadCSS into your framework's <head> mechanismWhich components need preloading? Only those that hide content on initialization - reveal, text, stagger, dialog, and a few widgets. The build validates preload entries automatically via npm run check:preload.
- Motion-first. Built around animation from the start, not retrofitted.
- Spring physics by default. No linear easing, no jank.
- Interruptible. Interactions never queue or stutter - even mid-animation.
- Per-component imports. Each component is a standalone subpath export - no dead weight, no bundler magic required.
- Composable. Shared primitives instead of reimplemented animations.
- Accessible. Honors
prefers-reduced-motion. Keyboard-navigable.
npm install # install dependencies
npm run build # build library to ./dist
npm run dev # rebuild on file change
npm run typecheck # tsc --noEmit
npm run lint # ESLint
npm run format # Prettier
npm run check:preload # validate FOUC preload rules
npm run size # bundle size budget checksrc/
├── reveal/ entrance & transition effects
├── respond/ input-driven interactivity
├── text/ typography effects
├── scroll/ scroll-driven components
├── components/ ready-made widgets
└── code/ code-display components
See CONTRIBUTING.md for component authoring conventions.
MIT © Tanja Gomilar