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

fluidkit

v0.5.0

Published

Liquid UI animations for React — one metaball engine, swappable glass/flat materials, built on Motion.

Readme

fluidkit

CI

A React library of liquid UI animations built on one idea: one liquid engine, swappable materials. Shapes are real metaball geometry (computed bezier bridges applied as a live clip-path), motion is spring-driven with surface tension (drops connect on touch, stretch, and snap), and the same shape renders as clear glass or a flat fill via a material prop. Built on top of Motion.

The core principle

Animate the surface, never the text. Every morph separates a surface layer (the liquid shape, free to scale, stretch, or merge) from a content layer (text / controls, which only cross-fades, never scales). Text always stays crisp.

Install

npm install fluidkit react react-dom motion

react, react-dom, and motion are peer dependencies (bring your own shared copy).

Optional GPU tier

LiquidMetal is a real WebGL primitive. It lives behind its own subpath export (fluidkit/liquid-metal), not the core fluidkit entry, so the core bundle stays GPU-free whether or not you use it. Its GPU library is an optional peer dependency: installing fluidkit without it never warns, and importing the core entry never resolves it.

npm i @paper-design/[email protected]   # for fluidkit/liquid-metal (pinned exact)
import { LiquidMetal } from "fluidkit/liquid-metal";

See docs/primitives/liquid-metal.md for props, fallback behavior, and caveats.

Quick start

import { useState } from "react";
import { MorphSurface } from "fluidkit";

function App() {
  const [open, setOpen] = useState(false);
  return (
    <div onClick={() => setOpen((v) => !v)}>
      <MorphSurface
        open={open}
        closedContent={<span>Ask fluidkit</span>}
        openContent={<div>Ready when you are.</div>}
      />
    </div>
  );
}

Primitives

| Primitive | What it does | Degrades to | |---|---|---| | MorphSurface | One liquid body: pill morphs into panel, satellite droplets absorbed through real bridges | Instant snap + opacity-only face fade | | Droplets | Drop cluster with surface tension; grab / drag / tear / re-merge with the pointer (interactive) | Separate static dots | | Thinking | Working indicator: droplets merge and split (role="status") | Three static dots | | FlowStagger | Staggered rise + un-blur entrance for list items, FLIP on reorder | Simple simultaneous fade | | LiquidTabs | Flagship tab strip: the indicator flows between tabs (slide or stretch), flat or glass material, labels tint by liquid coverage | Plain pill, snaps instantly | | Ripple | Pointer-origin water ripple on tap/click | No ripple, children render normally | | LiquidButton | Liquid pill button; jelly variant squashes on press via geometry (label never scales), still variant holds rigid | Normal button with an opacity press dip | | MeshGradient | Ambient CSS backdrop: large blurred radial-gradient blobs drift slowly behind your content | Static blobs at their home position | | Silk | Ambient CSS backdrop: full-height diagonal gradient sheets flowing like slow fabric | Static sheets at their home position | | GlassPanes | Glass-native backdrop: edge-to-edge frosted panes sliding on a shared diagonal, each at its own blur depth | Layered frosted fills | | Caustics | Poolside light background, or a caustic wall material for engine surfaces | Static plaster wall when WebGL or motion is unavailable | | LiquidCard | Content surface that sizes to its children; the liquid layer stays behind crisp content | Static card; glass falls back to frosted flat fill | | MeniscusDivider | Thin full-width liquid bead for section breaks, exposed as a separator | Static separator; glass falls back to frosted flat fill | | LiquidPanel | Drawer or sheet surface that pours in from one edge; content arrives above it | Surface snaps; content cross-fades | | LiquidTooltip | Tooltip droplet that condenses beside its trigger, with focus and Escape behavior | Full-size droplet fade | | LiquidText | Glass or flat glyphs with a sheen sweep while the real text stays selectable | Solid readable text; sheen parks under reduced motion | | LiquidDialog | Modal surface that rises from its trigger with focus restore, scroll lock, Escape and backdrop close | No travel; surface and content cross-fade | | VoiceBall | Voice-assistant orb driven by level and mode (idle, listening, speaking) | Static circle reflecting the current level | | LiquidSwitch | Toggle: the thumb droplet tears off one well through a real bridge and merges into the other; real hidden checkbox underneath | Thumb snaps; the on-tint still flips | | LiquidCheckbox | The check is liquid: a droplet lands and fills the well; indeterminate is a half-filled meniscus | Fill level snaps | | LiquidSlider | Droplet thumb riding the meniscus edge of a part-filled channel; real hidden range input underneath | Thumb tracks the value, no spring lag | | LiquidField | Text field on a glass surface: the input stays real and crisp, focus swells the surface + shows the focus meniscus | Swell dropped; focus ring stays | | LiquidProgress | Determinate progress as a vessel filling; the meniscus wobbles only while the value moves | Fill width tracks the value | | LiquidToast | toast() notifications that condense at the screen corner and evaporate on dismiss | Opacity-only in/out | | LiquidMenu | Dropdown that pours from its trigger; full ARIA menu keyboard pattern | Opacity fade over poured geometry | | LiquidMetal | Optional GPU tier: a real WebGL liquid-metal shader (fluidkit/liquid-metal) | Static metallic-gradient fallback |

Materials

Every surface component shares one styling pack, applied wherever it's physically meaningful: material ("glass"/"flat", with material="caustics" available on engine surfaces), tint/color (the glass tint, caustic light, or flat fill), opacity (how see-through the fill is, 0 clear to 1 solid; replaces the tint's own alpha, degrades to the default transparency where CSS relative color syntax is unsupported), intensity (how loudly the material reads, 0-1 or "whisper"/"present"), light (scene light position; null disables speculars), reflection (specular highlights on/off), refraction (opt-in Chromium-only edge lensing), and shadow (drop shadow on/off). Components omit only what can't physically apply: LiquidText's lighting is its sheen sweep, not the scene light, so it takes none of light/reflection/refraction/shadow.

  • glass — white tint + backdrop blur/saturation, specular highlights from one configurable scene light (light prop), toggleable via reflection. Opt-in refraction adds Chromium-only edge lensing (SVG displacement inside backdrop-filter; degrades silently). A drop of water is liquid glass.
  • flat — plain color; also the automatic fallback when backdrop-filter is unsupported.
  • caustics — poolside light over a plaster wall on supported engine surfaces. The wall is the no-WebGL fallback; caustic surfaces paint no glass speculars because the light pattern is the highlight.

Theming

FluidThemeProvider turns a brand into coherent surfaces: semantic tokens in, per-component styling out.

import { FluidThemeProvider } from "fluidkit";

<FluidThemeProvider theme={{ accent: "#0A7CFF", surface: "#FFF", text: "#14151A", radius: 14, mode: "light" }}>
  <App /> {/* every fluidkit surface inside derives its tint/fill/radius */}
</FluidThemeProvider>
  • Tokens: accent, surface, text, radius (px), mode ("light"/"dark"), plus the character knobs material ("glass"/"flat") and intensity. mutedText, background, and fontFamily are accepted but reserved (no component consumes them yet).
  • Derivation, not broadcast. Each component reads the theme through its own rule (src/theme/derive.ts): containers tint from accent at a per-component share and fill flat from surface; ink surfaces (the tabs indicator, buttons, ripples) fill from accent; LiquidText glyphs fill from text; radius applies where a component has a radius prop. Dark mode raises tint alphas so glass reads over dark hosts.
  • Only set tokens derive. An absent token never overrides a component default, so a colors-only theme keeps each component's character (tabs stay flat, buttons stay present). No provider = exactly the unthemed rendering.
  • Precedence: explicit props → theme derivation → component defaults. Nested providers merge token-by-token, inner wins.
  • material="caustics" is deliberately not themeable — it's ambient art, not a brand surface.

Cross-cutting guarantees

  • Reduced motion: prefers-reduced-motion collapses every effect to a clean static state; animation loops never run.
  • SSR-safe: nothing touches window at import time or during render.
  • Tree-shakeable: named exports from a single entry point (sideEffects: false).
  • Theming: colors, tint, light position, and physics via props. No brand shipped.
  • Graceful degradation: feature detection picks the best available path; never hard-fails.
  • Performance: animation loops pause off-screen (IntersectionObserver) and under reduced motion.

Motion accessibility & degradation

Every exported component ships with a tested degradation contract (tests/degradation/, one contract file per component). What you're guaranteed:

  • Reduced motion. With prefers-reduced-motion on, a component still renders its content and stays interactive — buttons click, tabs switch, tooltips show on focus, dialogs open and close. No animation loop runs and no frame rewrites geometry; each primitive parks in its documented static state (the "Degrades to" column above). Opacity-only cross-fades are the one kind of motion that remains. When the preference is unknown (e.g. SSR), components default to the static-safe rendering.
  • Missing capability. Where a component leans on a browser capability, the fallback is a real rendering, never a blank box: without backdrop-filter, glass degrades to a frosted flat fill (GlassPanes/Silk to layered tinted sheets); without WebGL, Caustics renders just its plaster wall and LiquidMetal a static metallic gradient; refraction is opt-in and silently skipped where SVG-filter backdrops aren't supported.

Consumers don't need to keep their own static fallbacks on top: if fluidkit renders it moving, it also renders it still.

Release status

  • 0.5.0: current package. Ships semantic theming, tested degradation contracts, React 19 CI coverage, controls, menus, toasts, and the optional LiquidMetal subpath.
  • 0.4.0: added the surface family (LiquidCard, LiquidPanel, LiquidDialog, LiquidTooltip, LiquidText, VoiceBall, MeniscusDivider), ambient backgrounds, Caustics, and the docs showcase.
  • 0.3.0: moved LiquidTabs onto the engine, added pointer grab / tear / re-merge interactions, opt-in refraction, per-frame DOM writes, and the docs site.
  • 0.2.0: introduced the liquid engine and rebuilt Droplets, Thinking, and MorphSurface on it.

See CHANGELOG.md for full release notes.

Docs site

The playground doubles as the public docs site: hero, live demos, controls, and copy-paste snippets for every primitive.

  • Develop: npm run dev
  • Build: npm run build:site → static bundle in dist-site/, deployable to any static host (GitHub Pages, Netlify, Vercel — no server needed).

More

Development

  • npm test: run tests
  • npm run typecheck: type check the library
  • npm run size: check bundle size (36.7 kB brotli budget on the core entry via size-limit)
  • npm run check:gpu-leak: guard against GPU dependencies
  • npm run check:pack: verify npm pack contents

All guards run in CI (Node 20 and 24).

License

MIT