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

react-native-liquid-fill

v0.1.0

Published

Liquid progress for React Native: water that fills any shape, with travelling waves, rising bubbles and a surface that sloshes when the phone tilts. Plus a ProgressRing with a second lap past 100%. Reanimated + react-native-svg, UI thread.

Readme

react-native-liquid-fill

npm license types platforms

Liquid progress for React Native. Water fills any shape, with travelling waves and rising bubbles, and the surface sloshes when the phone tilts. Also includes a ProgressRing that goes round a second time past 100%.

  • The water stays level while the phone turns. Tilt it and the surface swings past level and rocks back, the way water does in a glass. Shake it and the waves whip up. Turn it upside down and the water collects at the top of the screen.
  • It stays calm when it should. Gravity is separated from the hand moving the phone, a phone lying flat on a table doesn't drag the water to one side, and a dropped frame or a slow sensor never kicks the surface.
  • It works in any shape. Use circle, rounded or rect, or pass any SVG path (a drop, a bottle, a battery), with an optional outline.
  • The level springs to a new value instead of jumping. ProgressRing uses the same spring, so a ring and the water inside it rise together.
  • Everything runs on the UI thread. Waves, bubbles and the slosh physics all run in Reanimated worklets. paused stops them for a screen nobody is looking at.
  • Screen readers get a progress bar. Both components are progress bars that read out their percentage.

Install

npm install react-native-liquid-fill

Peer dependencies:

npx expo install react-native-reanimated react-native-svg

For tilt, also install expo-sensors. It's optional, and without it the water just rolls:

npx expo install expo-sensors

On Android 12+ the accelerometer only runs at 5 Hz unless your app declares HIGH_SAMPLING_RATE_SENSORS. Add it to app.json for smooth sloshing:

{ "expo": { "android": { "permissions": ["android.permission.HIGH_SAMPLING_RATE_SENSORS"] } } }

Quick start

import { LiquidFill } from 'react-native-liquid-fill';
import { useAccelerometerTilt } from 'react-native-liquid-fill/expo';

function Water({ progress }: { progress: number }) {
  const tilt = useAccelerometerTilt();
  return <LiquidFill size={160} progress={progress} tilt={tilt} accessibilityLabel="Water today" />;
}

Leave out tilt and the water stays level and just rolls. That way you don't need expo-sensors at all.

Water in a ring

import { innerSize, LiquidFill, ProgressRing } from 'react-native-liquid-fill';

<ProgressRing
  size={220}
  strokeWidth={14}
  progress={progress}
  fill={<LiquidFill size={innerSize(220, 14)} progress={progress} tilt={tilt} />}
>
  <Text>{Math.round(progress * 100)}%</Text>
</ProgressRing>

progress can go past 1. The ring draws the overflow as a second, lighter lap, while the water just stays full.

Shapes

<LiquidFill size={96} progress={p} />                                        // circle
<LiquidFill width={150} height={96} shape="rounded" cornerRadius={24} progress={p} />
<LiquidFill width={64} height={120} shape="rounded" outlineColor="#1C2533" outlineWidth={4} progress={p} />

// Any SVG path, drawn in its own box and scaled to width × height:
<LiquidFill
  width={100}
  height={125}
  path="M50 0 C50 0 95 52 95 80 A45 45 0 0 1 5 80 C5 52 50 0 50 0 Z"
  pathSize={{ width: 100, height: 125 }}
  progress={p}
/>

In a circle, the tilted water is exact. In other shapes the surface still stays level and swings, but the water isn't re-measured for the new angle, so treat it as a convincing look rather than a simulation. progress is the height of the water, not its volume.

Pausing

Stop the waves and the sensor when the screen isn't visible:

const focused = useIsFocused(); // react-navigation / expo-router
const tilt = useAccelerometerTilt({ enabled: focused });

<LiquidFill progress={p} tilt={tilt} paused={!focused} />

Another sensor library

useTilt(source) takes any accelerometer. source starts delivering readings (in g, the way expo-sensors reports them) and returns a function that stops:

import { useTilt, type TiltSource } from 'react-native-liquid-fill';

const source: TiltSource = (onReading) => {
  const sub = mySensor.subscribe(({ x, y, z, timestamp }) => onReading({ x, y, z, timestamp }));
  return () => sub.unsubscribe();
};

const tilt = useTilt(source, { invert: false });

Keep source stable (define it outside the component). If your library's axes point the other way, pass invert: true.

API

<LiquidFill>

| Prop | Default | | |---|---|---| | progress | required | 0–1, the height of the water. | | size | 120 | Width and height of a square container. | | width, height | size | For a container that isn't square. | | shape | 'circle' | 'circle', 'rounded' or 'rect'. A circle becomes an ellipse when width ≠ height. | | cornerRadius | a fifth of the shorter side | For 'rounded'. | | path, pathSize | | Any SVG path and the box it's drawn in. Overrides shape. | | color | #76A1F4 | The water, deep down. | | surfaceColor | #A8C4F8 | The water at the surface, and the back wave. | | emptyColor | transparent | The empty part of the container. | | outlineColor, outlineWidth | none, 0 | A line round the container. | | bubbles | 7 | 0–7. | | bubbleColor | #FFFFFF | | | waveHeight | 1 | 0 for a flat surface. | | waveSpeed | 1 | | | tilt | | From useAccelerometerTilt or useTilt. | | paused | false | Stops waves and bubbles. | | fillSpring | { damping: 15, stiffness: 80 } | The spring the level moves on. | | accessibilityLabel, style, testID | | |

<ProgressRing>

| Prop | Default | | |---|---|---| | size, progress | required | progress 0–2: past 1 is a second lap. | | strokeWidth | size / 10 | | | color, trackColor, overflowColor | #3266AE, #DCE7F8, #76A1F4 | | | lineCap | 'round' | 'round' or 'butt'. | | fill | | Drawn inside, e.g. a LiquidFill. | | children | | Centred on top: the percentage. | | spring | same as LiquidFill | | | accessibilityLabel, style, testID | | |

innerSize(size, strokeWidth, gap = 6) returns the diameter a fill can have inside the ring.

Tilt

  • useAccelerometerTilt({ enabled, invert }) from react-native-liquid-fill/expo, which uses expo-sensors.
  • useTilt(source, { enabled, invert }) from react-native-liquid-fill, which works with any sensor.

Both return a LiquidTilt: three shared values (angle, jolt, stir) that LiquidFill reads on the UI thread. Share one tilt between several LiquidFills on a screen.

License

MIT