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>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
148b99c4a6
commit
c05352d6fd
@@ -607,3 +607,84 @@ input:focus-visible {
|
||||
width: 100%;
|
||||
height: 40vh
|
||||
}
|
||||
|
||||
// v-lazy images (vue3-lazyload sets lazy="loading" | "loaded" | "error").
|
||||
// Hidden until the real file has loaded, then faded in, so a card never shows
|
||||
// a placeholder that is then swapped out, or a photo painting in top-down.
|
||||
img[lazy='loading'] {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
img[lazy='loaded'],
|
||||
img[lazy='error'] {
|
||||
opacity: 1;
|
||||
transition: opacity 0.35s ease;
|
||||
}
|
||||
|
||||
// Shimmering placeholder block for content that is still loading.
|
||||
.skeleton {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
background: @hairlineSoft;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
transform: translateX(100%);
|
||||
background: linear-gradient(90deg, transparent, fade(#fff, 65%), transparent);
|
||||
animation: skeleton-sweep 1.3s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
|
||||
// RTL page, so the sweep runs right to left.
|
||||
@keyframes skeleton-sweep {
|
||||
to {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.skeleton::after {
|
||||
animation: none;
|
||||
}
|
||||
}
|
||||
|
||||
// First-paint entrance (driven by composables/useReveal.ts): put `reveal` on
|
||||
// each section and `is-revealed` on their container once the data is in. Each
|
||||
// section rises a little, scales up from just under full size and fades in,
|
||||
// one beat (--reveal-delay) after the one above it.
|
||||
//
|
||||
// The curve is a long decelerate with no overshoot — it starts fast, settles
|
||||
// slowly and never bounces back. The travel is deliberately small (14px, 2% of
|
||||
// scale): the content should look like it was always there and simply came
|
||||
// into focus, not like it flew in.
|
||||
//
|
||||
// The settled state is `transform: none`, not an identity transform: any
|
||||
// transform left on a section would make it the containing block for fixed
|
||||
// elements inside it and give it a permanent stacking context.
|
||||
.reveal {
|
||||
opacity: 0;
|
||||
transform: translate3d(0, 14px, 0) scale(0.98);
|
||||
will-change: transform, opacity;
|
||||
}
|
||||
|
||||
.is-revealed .reveal {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
will-change: auto;
|
||||
transition:
|
||||
opacity 0.62s cubic-bezier(0.32, 0.72, 0, 1) var(--reveal-delay, 0ms),
|
||||
transform 0.62s cubic-bezier(0.32, 0.72, 0, 1) var(--reveal-delay, 0ms);
|
||||
}
|
||||
|
||||
// Respect a reduced-motion preference: show the content, skip the choreography.
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.reveal {
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
.is-revealed .reveal {
|
||||
transition: none;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user