Implement the approved UX review across Fleet, Betas, Library, deployments, and Settings. Add reviewed promotion and reconciliation plans, atomic queued-removal cancellation, recoverable beta drafts and launch inputs, accessible controls, and mobile improvements. Validated with 473 tests, a clean typecheck, production build, and isolated desktop/mobile browser walkthroughs. Include the review and implementation coverage notes.
25 lines
1.7 KiB
Svelte
25 lines
1.7 KiB
Svelte
<script lang="ts">
|
|
import Dialog from './primitives/Dialog.svelte';
|
|
import Button from './primitives/Button.svelte';
|
|
import { notificationHistory, markNotificationsRead, clearNotifications } from '$ui/toast.js';
|
|
let { open = $bindable(false) }: { open?: boolean } = $props();
|
|
$effect(() => { if (open) markNotificationsRead(); });
|
|
</script>
|
|
|
|
<Dialog bind:open title="Recent notifications" description="Recent action results and completed lobby watches in this browser tab. Watches run while the app is open.">
|
|
{#if $notificationHistory.length}
|
|
<ol>{#each $notificationHistory as item (item.id)}<li class:attention={item.variant === 'danger' || item.variant === 'warning'}><p>{item.message}</p><time datetime={item.createdAt}>{new Date(item.createdAt).toLocaleString()}</time>{#if item.href}<a href={item.href} onclick={() => open = false}>View details →</a>{/if}</li>{/each}</ol>
|
|
{:else}<p class="empty">No recent notifications. Completed lobby watches and action results will appear here.</p>{/if}
|
|
{#snippet actions()}<Button disabled={!$notificationHistory.length} onclick={clearNotifications}>Clear history</Button><Button onclick={() => open = false}>Close</Button>{/snippet}
|
|
</Dialog>
|
|
|
|
<style>
|
|
ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 12px; }
|
|
li { border: 1px solid var(--border-strong); padding: 12px; border-radius: var(--radius-md); }
|
|
li.attention { border-color: var(--state-warning); }
|
|
p { margin: 0 0 8px; font-size: var(--text-sm); }
|
|
time { display: block; color: var(--text-secondary); font-size: var(--text-xs); }
|
|
a { display: inline-block; margin-top: 8px; font-size: var(--text-sm); }
|
|
.empty { color: var(--text-secondary); }
|
|
</style>
|