Skip to content
Pinky UI

mobile

Pull to Refresh

A resistance-driven refresh chamber with threshold, armed, refreshing and complete states; release settles on Jelly's elastic spring curve.

  • mobile
  • refresh
  • pull
  • tension

Live preview

Pull to reveal refreshresistance / threshold / release

Pull from the top.

Resistance, armed threshold and an honest callback.

Quick usage

usage
import { PullToRefresh } from "@pinky-ui/systems";

<PullToRefresh onRefresh={reload}>{content}</PullToRefresh>

Install

Add @pinky-ui/systems as a dependency, or use the CLI to copy this component's source directly into your project — no dependency to manage, fully editable.

shell
npm install @pinky-ui/systems

Prefer to run the whole repository locally instead?

repository
git clone https://github.com/florash/Pinky-UI.git
cd Pinky-UI
npm install
npm run dev

Accessibility

  • Pointer and keyboard paths expose the same state change.
  • Status and focus remain meaningful when motion is disabled.

Performance

  • Uses local state and transforms; no per-frame React pointer loop.

Reduced motion

Resolves state changes without layout animation while preserving semantics.

When to use

  • Product workflows with a clear reversible or inspectable state.

When not to use

  • Decorative motion without a user task.

Skill

Purpose

Use for a tactile refresh chamber that invokes a host-owned refresh callback. It reveals from behind the content surface instead of pretending that a spinner is the content.

Use when

A scrollable mobile collection has an obvious reload action and a top boundary.

Avoid

Fake network states, hijacking browser refresh, or making pull the only refresh route.

Interaction states

The resistance curve makes pulling distinct from ready; the threshold has an armed cue, release enters refreshing, and a short complete state confirms the callback without inventing network data.

Accessibility

Expose pulling, ready, refreshing, and complete as readable status text. Keep a visible Refresh button so keyboard and switch users do not need a gesture.

Keyboard and touch

The button invokes the same callback as the gesture. The gesture only begins at scrollTop === 0, uses pointer capture, and cancels cleanly below threshold.

Reduced motion and performance

Use requestAnimationFrame for the visual offset and clean it on unmount. Release settles on Jelly's elastic spring (springs.elastic) — the same curve used for Jelly and JellyCard press/settle — so the chamber snaps back with a visible, springy overshoot rather than a linear ease-out; the drag itself stays a direct 1:1 resisted follow, only the release borrows the curve. Reduced motion keeps the threshold/armed state and direct content relationship, but removes the elastic settle and ambient spinner motion.

Composition and anti-patterns

The callback owns data and errors; this primitive does not invent network behavior.

Open this skill on its own page