Components
UI components for Swoff — UpdatePrompt, SWProgressBar, InstallButton.
Vue Components
These components use Vue composables to provide ready-to-use UI elements. See Component Specs for behavioral details.
UpdatePrompt
<script setup>
import { useSWUpdate } from "../composables/useSWUpdate";
const {
updateStatus,
currentVersion,
availableVersion,
progress,
forceUpdate,
acceptUpdate,
dismissUpdate,
} = useSWUpdate();
</script>
<template>
<div
v-if="updateStatus !== 'idle'"
:class="['update-prompt', forceUpdate ? 'fullscreen' : 'bottom-sheet']"
>
<p>Update available: v{{ currentVersion }} → v{{ availableVersion }}</p>
<div
v-if="updateStatus === 'downloading'"
class="progress-bar"
:style="{ width: `${progress}%` }"
/>
<template v-else>
<button @click="acceptUpdate">Update</button>
<button v-if="!forceUpdate" @click="dismissUpdate">Later</button>
</template>
</div>
</template>SWProgressBar
<script setup>
import { useSWProgress } from "../composables/useSWProgress";
const { progress, status } = useSWProgress();
</script>
<template>
<div
v-if="status === 'installing'"
class="fixed top-0 left-0 w-full h-1 bg-gray-200"
>
<div
class="h-full bg-blue-500 transition-all"
:style="{ width: `${progress}%` }"
/>
</div>
</template>InstallButton
<script setup>
import { ref, onMounted } from "vue";
const deferredPrompt = ref(null);
onMounted(() => {
window.addEventListener("beforeinstallprompt", (e) => {
e.preventDefault();
deferredPrompt.value = e;
});
});
const handleInstall = async () => {
if (!deferredPrompt.value) return;
deferredPrompt.value.prompt();
const { outcome } = await deferredPrompt.value.userChoice;
if (outcome === "accepted") deferredPrompt.value = null;
};
</script>
<template>
<button v-if="deferredPrompt" @click="handleInstall">Install App</button>
</template>Next Steps
- Vue Composables — underlying composables
- Component Specs — behavioral requirements
Swoff