Skip to content

PullRefresh ​

A mobile pull-to-refresh container: the default slot is the scrollable content (a list, etc.) and the container itself is the scroll box (height constrained by the host). Keep pulling down past the top of the list to reveal the indicator, which follows the finger with a resistance curve (asymptotically approaching the distance cap); releasing past the threshold triggers a refresh — oas-refresh is dispatched and the component parks at the threshold height showing the refreshing visual. When the host finishes the async refresh it removes refreshing, and the component plays the success copy before bouncing back. Mouse drag works the same on desktop (unified pointer events); wheel scrolling is unaffected. Colors derive from semantic tokens and adapt to dark mode automatically.

Basic Usage ​

Give the container a fixed height (host-constrained) and put a plain list inside. On touch screens keep pulling down at the top of the list; on desktop hold the left mouse button and drag vertically. On release the host sets refreshing to start the async refresh and removes it when done (the demo simulates a 900 ms data fetch).

Pull to refresh with visible event feedback

Item 01 — keep pulling down at the top
Item 02
Item 03
Item 04
Item 05
Item 06
Item 07
Item 08
Item 09
Item 10
Item 11 (scroll back to the top and pull again)

Pull down from the top inside the list →

Threshold and Resistance ​

threshold (default 60 px) is the pull distance required at release to trigger a refresh; max-pull (default 100 px) caps the distance — while pulling, the distance follows the resistance curve pull = maxPull × (1 − e^(−dy/maxPull)) and asymptotically approaches the cap (diminishing gain per pixel for a physical damping feel). Past the threshold the arrow flips and the copy changes to "Release to refresh"; releasing below it springs back with zero side effects.

threshold=40 / max-pull=160: lighter trigger, longer travel

Item 01 — pull past 40 px and release to trigger
Item 02
Item 03
Item 04
Item 05
Item 06
Item 07
Item 08

Try a shorter pull →

Disabled ​

disabled turns the gesture off entirely (the config-provider global disabled injection behaves the same): setting it mid-drag cancels immediately and springs back without dispatching any event.

disabled: gesture does not respond

Item 01 — pulling does nothing (disabled)
Item 02
Item 03
Item 04
Item 05

Pulling while disabled never dispatches oas-refresh

Scroll Coordination and Accessibility ​

  • The container carries overscroll-behavior-y: contain (no scroll chaining: pulling past the top never hands off to the page or triggers a page-level pull-to-refresh) and touch-action: pan-y; when the pointer starts at the top and moves down, the component takes over the gesture and calls preventDefault to block native scrolling; starting below the top or pulling up hands everything back to native scrolling.
  • Wheel scrolling is unaffected (the gesture is driven by pointer drags only).
  • The indicator is role="status" + aria-live="polite": copy changes (Pull to refresh → Release to refresh → Refreshing… → Refresh successful) are announced to screen readers; the component never grabs keyboard focus and the content semantics are entirely provided by the host.
  • Under prefers-reduced-motion the spring-back/flip transitions are disabled (state changes apply instantly; the spinner remains).

API ​

oas-pull-refresh ​

Attributes ​

AttributeDescriptionTypeDefault
disabledDisables the pull gesture entirely (the config-provider global disabled injection behaves the same); setting it mid-drag cancels immediately and springs back without dispatchingboolean—
max-pullPull distance cap (px, default 100): the resistance curve pull = maxPull × (1 − e^(−dy/maxPull)) approaches the cap with diminishing gain——
refreshingRefreshing (host-controlled): after oas-refresh the host sets it to start the async refresh and removes it when done; the component plays the success copy for about 600ms then bounces back; further pulls are ignored while refreshing; setting it without a gesture (programmatic refresh) parks at the refreshing visual too, without dispatchingboolean—
thresholdPull distance threshold to trigger a refresh (px, default 60): oas-refresh is dispatched on release only when the pulled distance reaches it; invalid/non-positive falls back to the default; the effective value is clamped to max-pull——

Events ​

EventDescription
oas-refreshDispatched once when the pull is released past the threshold; the component parks at the threshold height in the refreshing visual and waits for the host to set refreshing (it stays parked otherwise)

Slots ​

NameDescription
defaultScrollable content (a list, etc.); the container itself is the scroll box (overflow-y: auto), height constrained by the host

CSS Variables ​

CSS VariableDefault
--oas-pull-refresh-indicator-height48px
--oas-pull-refresh-label-colorvar(--oas-color-text-secondary)
--oas-pull-refresh-spinner-colorvar(--oas-color-primary)

Parts ​

PartDescription
rootScroll box container (overflow-y: auto + no scroll chaining)
trackTranslation layer (carries the pull transform, spring-back transition)
indicatorIndicator area (role="status" + aria-live="polite")
arrowPull-down arrow (flips past the threshold; hidden while refreshing/success)
spinnerRotating indicator while refreshing (mutually exclusive with the arrow)
labelState copy (i18n, four states)
contentContent area (default slot projection)

Released under the MIT OR Apache-2.0 License.