Merge pull request 'fix(ui): hold info toast ~1s before it rises and fades' (#181) from feature/toast-hold-before-fade into development
CI / changes (push) Successful in 2s
CI / unit (push) Has been skipped
CI / integration (push) Has been skipped
CI / ui (push) Successful in 1m7s
CI / conformance (push) Successful in 9s
CI / gate (push) Successful in 0s
CI / deploy (push) Successful in 1m44s
CI / changes (push) Successful in 2s
CI / unit (push) Has been skipped
CI / integration (push) Has been skipped
CI / ui (push) Successful in 1m7s
CI / conformance (push) Successful in 9s
CI / gate (push) Successful in 0s
CI / deploy (push) Successful in 1m44s
This commit was merged in pull request #181.
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
import { app, dismissToast } from '../lib/app.svelte';
|
||||
|
||||
const dur = $derived(app.reduceMotion ? 0 : 260);
|
||||
// An info bubble owns its whole 2s life through a CSS rise-and-fade animation, so it takes
|
||||
// no Svelte enter/leave transition; an error keeps the fly-in / fade-out dwell behaviour.
|
||||
// An info bubble owns its whole 3s life through a CSS animation — appear, a ~1s hold at rest,
|
||||
// then rise-and-fade — so it takes no Svelte enter/leave transition; an error keeps the fly-in /
|
||||
// fade-out dwell behaviour.
|
||||
const isInfo = $derived(app.toast?.kind !== 'error');
|
||||
</script>
|
||||
|
||||
@@ -50,17 +51,19 @@
|
||||
border-color: var(--danger);
|
||||
color: var(--danger);
|
||||
}
|
||||
/* An info bubble fades in, then drifts up by roughly the tab-bar height while fading out,
|
||||
all within 2s; the X centring is preserved across the rise. */
|
||||
/* An info bubble fades in, holds for ~1s at rest, then drifts up by roughly the tab-bar height
|
||||
while fading out, all within 3s; the X centring is preserved across the rise. The 8%/41%
|
||||
stops are the appear (~240ms) and the end of the ~1s hold. */
|
||||
.toast.rise {
|
||||
animation: toast-rise 2s ease-out forwards;
|
||||
animation: toast-rise 3s ease-out forwards;
|
||||
}
|
||||
@keyframes toast-rise {
|
||||
0% {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(8px);
|
||||
}
|
||||
12% {
|
||||
8%,
|
||||
41% {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
@@ -69,16 +72,16 @@
|
||||
transform: translateX(-50%) translateY(-56px);
|
||||
}
|
||||
}
|
||||
/* Reduced motion: the same 2s life, fade only — no upward travel. */
|
||||
/* Reduced motion: the same 3s life (appear, ~1s hold, fade), fade only — no upward travel. */
|
||||
.toast.rise-reduced {
|
||||
animation: toast-rise-reduced 2s ease-out forwards;
|
||||
animation: toast-rise-reduced 3s ease-out forwards;
|
||||
}
|
||||
@keyframes toast-rise-reduced {
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
12%,
|
||||
70% {
|
||||
8%,
|
||||
41% {
|
||||
opacity: 1;
|
||||
}
|
||||
100% {
|
||||
|
||||
@@ -214,9 +214,9 @@ function goForeground(): void {
|
||||
export function showToast(text: string, kind: Toast['kind'] = 'info'): void {
|
||||
app.toast = { kind, text, seq: ++toastSeq };
|
||||
if (toastTimer) clearTimeout(toastTimer);
|
||||
// An info bubble lives exactly as long as its rise-and-fade animation (2s); an error
|
||||
// dwells longer (4s) so it is not missed.
|
||||
toastTimer = setTimeout(() => (app.toast = null), kind === 'error' ? 4000 : 2000);
|
||||
// An info bubble lives exactly as long as its appear + ~1s hold + rise-and-fade animation (3s);
|
||||
// an error dwells longer (4s) so it is not missed.
|
||||
toastTimer = setTimeout(() => (app.toast = null), kind === 'error' ? 4000 : 3000);
|
||||
}
|
||||
|
||||
/** dismissToast hides the current toast at once — a tap on the bubble dismisses it. */
|
||||
|
||||
Reference in New Issue
Block a user