npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tailmotion

v0.10.1

Published

A motion language for product interfaces: scoped motion personalities, state-driven presence, native HTML motion, product recipes and scroll-driven reveals. Zero runtime, pure CSS, framework-agnostic.

Readme

Add motion without adding a runtime

npm install tailmotion
@import "tailmotion/css";
<button class="tm-press rounded-lg bg-blue-600 px-4 py-2 text-white">
  Save changes
</button>

TailMotion gives product interfaces a tested motion language with good decisions already made. Tailwind owns layout, color, spacing, radius, shadows and typography; TailMotion owns how an element enters, exits, responds, repeats and reacts to state.

A keyframe collection answers "how do I fade this in?" TailMotion answers "how should this whole product move, and what happens when the state changes?"

📖 Full documentation → · 🎛️ Live capability demo →

What it does that a keyframe collection cannot

One class changes the motion personality of a whole interface

<main class="tm-motion-calm">
  <button class="tm-press">Save</button>
  <div class="tm-slide-block-start">Saved</div>
</main>

tm-motion-calm, tm-motion-productive and tm-motion-expressive retune every TailMotion descendant. Duration is a factor, not a value, so each animation keeps its own relative character — tm-pop stays livelier than tm-fade-in in all three. Element-level utilities like tm-duration-300 still win.

Motion personalities

Your existing data-state animates, with no runtime

<div class="tm-presence-slide-block" data-state="open">Product menu</div>

Reads data-state, aria-expanded, aria-pressed, aria-checked or .tm-open / .tm-closed. Built from transitions, so reversing mid-flight retargets from the current position instead of restarting. Radix UI, Base UI, Ark and Melt work with no adapter — the class is the integration.

State-driven presence

Native dialog, popover and disclosure get real exits

<dialog class="tm-native-dialog">…</dialog>
<div popover class="tm-native-popover">…</div>
<details class="tm-native-disclosure">…</details>

The browser keeps focus management, the top layer, light dismiss, Escape and every native semantic. TailMotion adds the movement, picks no color or size, and adds no JavaScript.

Native elements

Product patterns as motion only

<div role="status" data-state="open" class="tm-toast">Changes saved</div>

<button data-state="loading" class="tm-feedback-button">
  <span class="tm-feedback-idle">Save</span>
  <span class="tm-feedback-loading">Saving</span>
  <span class="tm-feedback-success">Saved</span>
</button>

Menu, dialog, toast, tooltip, accordion, tabs, loading-to-success and hold-to-confirm. State selectors, timing, easing and transform origin — no colors, no dimensions, no components.

Product recipes

Scroll reveals with no observer, that fail safely

<section class="tm-scroll-reveal">Content</section>

CSS view timelines, driven by the browser on the compositor. Entirely inside @supports (animation-timeline: view()), so a browser without support renders ordinary, fully visible content — a fallback an IntersectionObserver cannot offer.

Scroll-driven motion

Stagger that can also leave

<ul data-state="open" class="tm-stagger tm-stagger-75 tm-stagger-from-end">
  <li>Profile</li><li>Settings</li><li>Sign out</li>
</ul>

Enter in document order, exit last-item-first, replay from a state change — with nothing reordered in the DOM, so reading order, tab order and the accessibility tree are untouched.

Choreography

What is guaranteed

Every one of these is verified by npm run check, which fails the build if it stops being true.

  • Zero runtime in the CSS core. No JavaScript, no observer, no frame loop.
  • Nothing modern can hide content. A hidden base state is only ever declared inside the @supports block that also says how it comes back.
  • Reduced motion preserves the state. Animations collapse to 1ms rather than being removed, with two deliberate, documented exceptions.
  • Direction is logical. Inline-axis motion mirrors in RTL; block-axis motion does not.
  • Transform-safe. 32 keyframes — every entrance, exit, presence and scroll class — animate translate / scale / rotate, so a Tailwind rotate-3 on the same element survives.
  • Tailwind v3, Tailwind v4, or no Tailwind at all.
  • Usage-generated CSS for the simple catalogue (experimental). Tailwind v3 (via the plugin) and Tailwind v4 (via tailmotion/tailwind.css) can emit only the fade/pop/bounce-style utilities and interactions your markup actually uses, instead of the whole catalogue. See Installation.

Documentation

| | | |---|---| | Quickstart | Install and ship the first four behaviours | | Installation | Tailwind v3, v4, the CDN, the optional plugin | | The motion model | Four token groups and one override order | | Class reference | Every class, trigger, state, duration and contract | | CSS variables | Every --tm-* property and its default | | Browser support | Every guarded feature and its exact fallback | | Accessibility | Reduced motion, RTL, focus, and what motion must never be alone | | Framework integration | React, Vue, Svelte, HTML, headless UI | | Migration | Upgrading to 0.8 | | Support and non-goals | What is supported, and what will never be built |

The docs/ folder in this repository is the source for all of the above.

Quick reference

| Profile | Use for | Duration | Travel | Overshoot | |---|---|---|---|---| | tm-motion-calm | Settings, finance, long-form reading | ×1.1 | 8px | none | | tm-motion-productive | The recommended default for product UI | ×0.85 | 10px | ×0.6 | | tm-motion-expressive | Onboarding, marketing, celebration | ×1.2 | 22px | ×1.3 |

Plus tm-speed-*, tm-emphasis-* and tm-no-overshoot for one axis at a time.

tm-presence-fade · tm-presence-scale · tm-presence-pop · tm-presence-slide-block · tm-presence-slide-inline

tm-menu · tm-dialog · tm-dialog-backdrop · tm-toast · tm-tooltip · tm-accordion-panel · tm-tab-panel · tm-tab-indicator · tm-feedback-button · tm-hold-confirm

tm-native-popover · tm-native-dialog · tm-native-disclosure

Entrances tm-fade-in · tm-scale-in · tm-slide-block-start · tm-slide-block-end · tm-slide-inline-start · tm-slide-inline-end · tm-blur-in · tm-pop · tm-drop · tm-zoom-in · tm-zoom-out · tm-rotate-in · tm-elastic · tm-reveal · tm-unfold · tm-glide · tm-scale-fade · tm-rise · tm-flip-x · tm-flip-y · tm-swing-in

Exits tm-fade-out · tm-scale-out · tm-slide-block-out · tm-slide-inline-out · tm-blur-out

Interactions tm-press · tm-hover-lift · tm-hover-scale · tm-rotate-hover · tm-rotate-press · tm-icon-swap

Continuous tm-spin · tm-pulse · tm-bounce · tm-float · tm-drift · tm-sway · tm-glow · tm-morph · tm-ripple · tm-shimmer · tm-sparkle

Timing tm-duration-* · tm-delay-* · tm-ease-* · tm-repeat-* · tm-distance-* · tm-stagger-*

Full details, including every duration and easing role, in the class reference.

@import "tailmotion/css";            /* everything — 31.6 KB gzipped */

@import "tailmotion/profiles.css";   /* 3.7 KB */
@import "tailmotion/presence.css";   /* 4.7 KB */
@import "tailmotion/native.css";     /* 5.0 KB */
@import "tailmotion/recipes.css";    /* 6.4 KB */
@import "tailmotion/scroll.css";     /* 4.1 KB */
@import "tailmotion/choreography.css"; /* 4.8 KB */

@import "tailmotion/animations/base.css";  /* or one family at a time */
@import "tailmotion/animations/fade.css";

The full bundle is not tree-shaken, and each module repeats the shared token layer — so if you need more than one, import tailmotion/css instead.

Imports and bundle size

React Native

Not supported. TailMotion is CSS and DOM selectors. React Native Web can use it for its browser target only, where the output is real DOM and real CSS.

Community

License

MIT © Moumen Soliman