Files
gems/opal-web/src/lib/components/Toast.svelte
T
joakim b53e77a8ec feat: add foundational Tier 1 components and store methods
Add generic BottomSheet, Toast, and ConfirmDialog components.
Add startTask/stopTask optimistic methods to tasks store.
Add --color-active-bg/text theme tokens for all three themes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 15:44:30 +01:00

106 lines
2.1 KiB
Svelte

<script>
import { onMount, onDestroy } from 'svelte';
import { fly } from 'svelte/transition';
/** @type {string} */
export let message;
/** @type {{ label: string, handler: () => void }|undefined} */
export let action = undefined;
/** @type {number} */
export let duration = 5000;
/** @type {() => void} */
export let onDismiss;
/** @type {ReturnType<typeof setTimeout>|null} */
let timer = null;
function startTimer() {
if (duration > 0) {
timer = setTimeout(() => {
onDismiss();
}, duration);
}
}
function clearTimer() {
if (timer) {
clearTimeout(timer);
timer = null;
}
}
function handleAction() {
clearTimer();
if (action) action.handler();
onDismiss();
}
onMount(() => {
startTimer();
});
onDestroy(() => {
clearTimer();
});
</script>
<div class="toast" transition:fly={{ y: 20, duration: 200 }}>
<span class="toast-message">{message}</span>
{#if action}
<button class="toast-action" on:click={handleAction} type="button">
{action.label}
</button>
{/if}
</div>
<style>
.toast {
position: fixed;
bottom: calc(3.5rem + var(--spacing-md));
left: var(--spacing-md);
right: var(--spacing-md);
max-width: var(--content-max-width);
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-md);
padding: var(--spacing-sm) var(--spacing-md);
background-color: var(--bg-tertiary);
border: 1px solid var(--border-color);
border-radius: var(--border-radius);
box-shadow: var(--shadow-md);
z-index: 40;
}
.toast-message {
font-size: var(--font-size-sm);
color: var(--text-primary);
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.toast-action {
font-size: var(--font-size-sm);
font-weight: 600;
color: var(--color-primary);
background: none;
border: none;
cursor: pointer;
padding: var(--spacing-xs) var(--spacing-sm);
border-radius: 0.25rem;
white-space: nowrap;
min-width: unset;
min-height: 36px;
}
.toast-action:hover {
background-color: var(--bg-secondary);
}
</style>