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 from the top.
Resistance, armed threshold and an honest callback.
Quick 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.
npm install @pinky-ui/systemspnpm add @pinky-ui/systemsyarn add @pinky-ui/systemsnpx pinky-ui add pull-to-refreshPrefer to run the whole repository locally instead?
git clone https://github.com/florash/Pinky-UI.git
cd Pinky-UI
npm install
npm run devAccessibility
- 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.