Files
tehran_tala/apps/user-app/src/components/ui/ToastHost.vue
T
s.esmaeiliandClaude Sonnet 5 c05352d6fd refactor(ui): replace modal dialogs with toast/sheet components
Remove DialogVant/NotifyVant and add Toast and Sheet components with
useToast, useReveal, and usePageTransition composables. Rework
Navigation, RegisterView, and styles across both apps; rebuild dist assets.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-04 13:57:25 +03:30

90 lines
2.1 KiB
Vue

<!--
Renders the shared toast queue (see composables/useToast.ts). Mounted once
in App.vue. Toasts drop in from the top with a spring, the stack slides to
make room, and a closing toast shrinks up and fades out.
-->
<template>
<Teleport to="body">
<div class="toast-host">
<TransitionGroup name="toast">
<ToastCard v-for="item in toasts" :key="item.id" :item="item" @close="dismiss(item.id)" />
</TransitionGroup>
</div>
</Teleport>
</template>
<script setup lang="ts">
import ToastCard from './ToastCard.vue'
import { useToast } from '../../composables/useToast'
const { toasts, dismiss } = useToast()
</script>
<style lang="less">
.toast-host {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 3000;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: calc(12px + env(safe-area-inset-top, 0px)) 14px 0;
direction: rtl;
pointer-events: none;
> * {
max-width: 420px;
}
}
// Enter: drop from above, slightly small and blurred, then overshoot into place.
.toast-host .toast.toast-enter-active {
transition:
transform 0.6s cubic-bezier(0.2, 1.35, 0.4, 1),
opacity 0.35s ease,
filter 0.4s ease;
}
.toast-host .toast.toast-enter-from {
transform: translateY(-120%) scale(0.88);
opacity: 0;
filter: blur(6px);
}
// Leave: taken out of flow so the stack can glide up behind it.
.toast-host .toast.toast-leave-active {
position: absolute;
left: 14px;
right: 14px;
margin: 0 auto;
transition:
transform 0.32s cubic-bezier(0.5, 0, 0.75, 0),
opacity 0.28s ease,
filter 0.3s ease;
}
.toast-host .toast.toast-leave-to {
transform: translateY(-40%) scale(0.9);
opacity: 0;
filter: blur(4px);
}
.toast-host .toast.toast-move {
transition: transform 0.45s cubic-bezier(0.2, 1.2, 0.4, 1);
}
@media (prefers-reduced-motion: reduce) {
.toast-host .toast.toast-enter-active,
.toast-host .toast.toast-leave-active,
.toast-host .toast.toast-move {
transition: opacity 0.2s ease;
}
.toast-host .toast.toast-enter-from,
.toast-host .toast.toast-leave-to {
transform: none;
filter: none;
}
}
</style>