From f92d98d067cf3e60b7a47fece7737cd25cf88802 Mon Sep 17 00:00:00 2001 From: curo1305 Date: Mon, 15 Jun 2026 20:11:12 +0200 Subject: [PATCH] feat(10-04): implement toast store, ToastContainer, mount in App.vue - toast.js: reactive toasts array, show/dismiss with auto-dismiss via setTimeout - ToastContainer.vue: Options API, Teleport to body, TransitionGroup, data-test attr - type-to-class maps: accentClass/iconName/iconColorClass for success/error/warning/info - App.vue: import and mount after layout div - all 10 tests pass; SettingsAccountTab and TotpEnrollment regressions green --- frontend/src/App.vue | 2 + frontend/src/components/ui/ToastContainer.vue | 73 +++++++++++++++++++ frontend/src/stores/toast.js | 24 +++--- 3 files changed, 86 insertions(+), 13 deletions(-) create mode 100644 frontend/src/components/ui/ToastContainer.vue diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 389a2e6..6309859 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -6,6 +6,7 @@ + + + diff --git a/frontend/src/stores/toast.js b/frontend/src/stores/toast.js index 0206d89..f0a1055 100644 --- a/frontend/src/stores/toast.js +++ b/frontend/src/stores/toast.js @@ -1,20 +1,18 @@ -/** - * Phase 7.1 STUB — Phase 10 (UX-10) fills in the full implementation. - * - * The signature `show(message, type, duration)` is locked and Phase 10 must - * honor it without modifying Phase 8 call sites. - * - * Default values match UI-SPEC.md: - * type = 'success' (NOT 'info') - * duration = 4000 - */ +import { ref } from 'vue' import { defineStore } from 'pinia' export const useToastStore = defineStore('toast', () => { - // eslint-disable-next-line no-unused-vars + const toasts = ref([]) + function show(message, type = 'success', duration = 4000) { - // No-op stub — Phase 10 implements rendering. + const id = Date.now() + Math.random() + toasts.value.push({ id, message, type, duration }) + if (duration > 0) setTimeout(() => dismiss(id), duration) } - return { show } + function dismiss(id) { + toasts.value = toasts.value.filter(t => t.id !== id) + } + + return { toasts, show, dismiss } })