PullToRefresh
Touch pull-to-refresh gesture for a scrollable area: pulling from the top shows a konsta preloader, and releasing past the threshold emits refresh.
vue
<script setup lang="ts">
import RyderPullToRefresh from "@opeolluwa/ryder/components/notes/PullToRefresh.vue"
</script>
<template>
<div class="h-64 overflow-y-auto">
<RyderPullToRefresh :threshold="64" @refresh="load">
<!-- scrollable content -->
</RyderPullToRefresh>
</div>
</template>Examples
Touch-only — this demo does nothing with a mouse:
vue
<script setup lang="ts">
import { ref } from "vue";
import PullToRefresh from "../../../src/components/notes/PullToRefresh.vue";
const refreshed = ref(0);
function onRefresh() {
refreshed.value += 1;
}
</script>
<template>
<div class="space-y-2">
<p class="text-xs text-gray-500 dark:text-white/50">
Touch-only — pull down from the top of the box. Refreshed
{{ refreshed }} time(s).
</p>
<div
class="h-48 overflow-y-auto rounded-xl border border-gray-200 dark:border-white/10"
>
<PullToRefresh @refresh="onRefresh">
<div class="divide-y divide-gray-100 dark:divide-white/5">
<p
v-for="row in 12"
:key="row"
class="px-4 py-3 text-sm text-gray-600 dark:text-white/60"
>
Row {{ row }} — pull down from the top to refresh.
</p>
</div>
</PullToRefresh>
</div>
</div>
</template>Props
| Prop | Type | Default | Description |
|---|---|---|---|
threshold | number | 64 | Pull distance, in pixels, that triggers a refresh. Read once at setup — changing it later has no effect. |
Emits
| Event | Payload | Description |
|---|---|---|
refresh | [] | The gesture completed; run your reload here. |
Slots
| Slot | Props | Content |
|---|---|---|
default | — | The scrollable content, placed inside the pull container. |
Notes
- Touch-only:
touchstart/touchmove/touchendlisteners (all passive) are attached to the container; mouse and trackpad drags do nothing. - The gesture only starts when the container itself is at
scrollTop === 0, and the live distance isdelta × 0.5, capped atthreshold × 1.5. - Put it in a fixed-height
overflow-y-autobox (as in the example) so there is a scroll area to pull against. - The indicator is konsta's
kPreloader:w-5 h-5while pulling,w-6 h-6once it is refreshing and the distance has reached 64px — that size check is hardcoded to 64, not tothreshold. - The composable (
usePullToRefresh) resets the distance in afinally, so a failed refresh cannot leave the bar stuck. refreshis emitted from an internal handler that only awaits the emit itself, so the preloader hides as soon as it returns — your handler does not hold the spinner open.