How to build an accessible PullToRefresh in React
The gesture is a touch-only enhancement: it arms only at scrollTop 0 and uses touch-action/overscroll containment so normal scrolling and keyboard use are unaffected. A polite aria-live status region announces the pull, release, and refreshing states (strings from the i18n catalog), and the Spinner exposes role="status" while loading. Because pull-to-refresh cannot be performed without a pointer, apps should also offer an explicit refresh control for keyboard users.
When to use a PullToRefresh
- A scrollable list or feed on touch devices that the user refreshes by pulling down from the top
- Mobile screens where a dedicated refresh button would be redundant or out of reach
- Content that updates on demand and benefits from a familiar pull gesture
When not to use it
- Desktop, pointer-first surfaces — provide an explicit Refresh button
- Content that auto-refreshes or paginates on scroll — use infinite scroll instead
- Regions that are not the primary scroll container of the screen
Accessibility
Role status, verified at WCAG 2.2-AA.
Common mistakes
Avoid: Wrapping a non-scrolling element and relying on pull as the only refresh path
Prefer: Wrap the scroll container and also expose a Refresh control for non-touch users
Pull-to-refresh is touch-only; keyboard and pointer users need an explicit control
Example
<PullToRefresh onRefresh={() => refetch()}>
<FeedList items={items} />
</PullToRefresh>