Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions web/build/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,35 @@
<meta charset="utf-8" />
<link rel="icon" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="/_app/immutable/entry/start.DloRK_ld.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DhdZQ6Fn.js" rel="modulepreload">
<link href="/_app/immutable/entry/start.ZBdqMrTD.js" rel="modulepreload">
<link href="/_app/immutable/chunks/CiRPKAwS.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DtfuHTUv.js" rel="modulepreload">
<link href="/_app/immutable/entry/app.DcaH8u5r.js" rel="modulepreload">
<link href="/_app/immutable/entry/app.zQYyvZcz.js" rel="modulepreload">
<link href="/_app/immutable/chunks/kNaey6uv.js" rel="modulepreload">
<link href="/_app/immutable/chunks/xihTtKlq.js" rel="modulepreload">
<link href="/_app/immutable/nodes/0.Cl2pHMx4.js" rel="modulepreload">
<link href="/_app/immutable/nodes/0.DKJm-K02.js" rel="modulepreload">
<link href="/_app/immutable/chunks/DKyKpwK7.js" rel="modulepreload">
<link href="/_app/immutable/chunks/5Qa-t89S.js" rel="modulepreload">
<link href="/_app/immutable/chunks/hKaPXkrQ.js" rel="modulepreload">
<link href="/_app/immutable/chunks/BscTVQ9J.js" rel="modulepreload">
<link href="/_app/immutable/chunks/B0RXJPsG.js" rel="modulepreload">
<link href="/_app/immutable/chunks/fe7zj1-L.js" rel="modulepreload">

<link href="/_app/immutable/assets/0.CqeqEt7D.css" rel="stylesheet">
<link href="/_app/immutable/assets/0.DtaeUL2f.css" rel="stylesheet">
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">
<script>
{
__sveltekit_vs9042 = {
__sveltekit_9284yn = {
base: ""
};

const element = document.currentScript.parentElement;

Promise.all([
import("/_app/immutable/entry/start.DloRK_ld.js"),
import("/_app/immutable/entry/app.DcaH8u5r.js")
import("/_app/immutable/entry/start.ZBdqMrTD.js"),
import("/_app/immutable/entry/app.zQYyvZcz.js")
]).then(([kit, app]) => {
kit.start(app, element);
});
Expand Down
13 changes: 13 additions & 0 deletions web/src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,19 @@ export function statusTextClass(status: string): string {
return map[status] ?? 'text-muted-foreground';
}

// ── Interaction helpers ──────────────────────────────────────────────

/**
* Keyboard activation for clickable table rows: rows are not natively
* focusable, so pair tabindex="0" with Enter/Space handling.
*/
export function rowKeyActivate(e: KeyboardEvent, activate: () => void) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
activate();
}
}

// ── Time formatting ───────────────────────────────────────────────────

/**
Expand Down
10 changes: 8 additions & 2 deletions web/src/routes/(dashboard)/+layout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,18 @@
</svelte:head>

<div class="min-h-screen bg-background">
<a
href="#main-content"
class="sr-only focus:not-sr-only focus:fixed focus:top-2 focus:left-2 focus:z-50 focus:rounded-md focus:bg-primary focus:px-3 focus:py-2 focus:text-sm focus:text-primary-foreground"
>
Skip to content
</a>
<!-- Top Nav -->
<header class="sticky top-0 z-40 border-b bg-background">
<div class="flex h-14 items-center gap-3 px-4 lg:px-6">
<Sheet.Root bind:open={mobileMenuOpen}>
<Sheet.Trigger
class="md:hidden inline-flex items-center justify-center h-9 w-9 rounded-md border border-input bg-background hover:bg-muted transition-colors"
class="md:hidden inline-flex items-center justify-center h-11 w-11 rounded-md border border-input bg-background hover:bg-muted transition-colors"
aria-label="Open menu"
>
<svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
Expand Down Expand Up @@ -103,7 +109,7 @@
</header>

<!-- Content -->
<main>
<main id="main-content">
{@render children()}
</main>
</div>
15 changes: 12 additions & 3 deletions web/src/routes/(dashboard)/issues/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
let error = $state('');
let liveIndicator = $state(false);

import { levelTextClass, statusTextClass, timeAgo } from '$lib/utils';
import { levelTextClass, statusTextClass, timeAgo, rowKeyActivate } from '$lib/utils';

let wsUnsub: (() => void) | null = $state(null);

Expand Down Expand Up @@ -109,6 +109,10 @@
navigate();
}

function openIssue(issue: Issue) {
goto(`/issues/${issue.id}?project=${selectedProject}`);
}

function goToPage(p: number) {
if (p < 1 || p > totalPages) return;
currentPage = p;
Expand Down Expand Up @@ -262,6 +266,9 @@
</div>

<!-- Content -->
{#if !loading && !error}
<p class="sr-only" role="status">{totalIssues} issues loaded</p>
{/if}
{#if loading}
<div class="space-y-3">
{#each Array(5) as _}
Expand Down Expand Up @@ -298,8 +305,10 @@
<TableBody>
{#each issues as issue}
<TableRow
class="cursor-pointer hover:bg-muted/50"
onclick={() => goto(`/issues/${issue.id}?project=${selectedProject}`)}
class="cursor-pointer hover:bg-muted/50 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring"
tabindex={0}
onclick={() => openIssue(issue)}
onkeydown={(e) => rowKeyActivate(e, () => openIssue(issue))}
>
<TableCell>
<Badge variant="outline" class={levelTextClass(issue.level)}>
Expand Down
6 changes: 4 additions & 2 deletions web/src/routes/(dashboard)/issues/[issueId]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
TableRow
} from '$lib/components/ui/table/index.js';

import { levelTextClass, statusTextClass, timeAgo, formatTime } from '$lib/utils';
import { levelTextClass, statusTextClass, timeAgo, formatTime, rowKeyActivate } from '$lib/utils';

let issue: Issue | null = $state(null);
let events: StoredEvent[] = $state([]);
Expand Down Expand Up @@ -288,8 +288,10 @@
<TableBody>
{#each events as event (event.id)}
<TableRow
class="cursor-pointer hover:bg-muted/50"
class="cursor-pointer hover:bg-muted/50 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring"
tabindex={0}
onclick={() => goToEvent(event)}
onkeydown={(e) => rowKeyActivate(e, () => goToEvent(event))}
>
<TableCell class="font-medium whitespace-normal">
{eventSummary(event)}
Expand Down
6 changes: 5 additions & 1 deletion web/src/routes/(dashboard)/release-health/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,11 @@
</Table>
</div>

<!-- Pagination -->
{#if !loading && !error}
<p class="sr-only" role="status">{totalSessions} sessions loaded</p>
{/if}

<!-- Pagination -->
<Pagination page={currentPage} {totalPages} total={totalSessions} {perPage} onPageChange={goToPage} />
{/if}
</div>
18 changes: 14 additions & 4 deletions web/src/routes/(dashboard)/transactions/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
TableHeader,
TableRow
} from '$lib/components/ui/table/index.js';
import { timeAgo, formatDuration, transactionStatusTextClass } from '$lib/utils';
import { timeAgo, formatDuration, transactionStatusTextClass, rowKeyActivate } from '$lib/utils';

let projects: Project[] = $state([]);
let selectedProject: string = $state('');
Expand Down Expand Up @@ -55,6 +55,10 @@
}
}

function openTransaction(txn: TransactionResponse) {
goto(`/transactions/${txn.id}?project=${selectedProject}`);
}

function buildUrl(): string {
const params = new URLSearchParams();
if (selectedProject) params.set('project', selectedProject);
Expand Down Expand Up @@ -188,8 +192,10 @@
<TableBody>
{#each transactions as txn}
<TableRow
class="cursor-pointer hover:bg-muted/50"
onclick={() => goto(`/transactions/${txn.id}?project=${selectedProject}`)}
class="cursor-pointer hover:bg-muted/50 focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ring"
tabindex={0}
onclick={() => openTransaction(txn)}
onkeydown={(e) => rowKeyActivate(e, () => openTransaction(txn))}
>
<TableCell class="whitespace-normal font-medium">{txn.name}</TableCell>
<TableCell class="font-mono text-muted-foreground whitespace-nowrap">
Expand Down Expand Up @@ -223,7 +229,11 @@
</Table>
</div>

<!-- Pagination -->
{#if !loading && !error}
<p class="sr-only" role="status">{totalTransactions} transactions loaded</p>
{/if}

<!-- Pagination -->
<Pagination page={currentPage} {totalPages} total={totalTransactions} {perPage} onPageChange={goToPage} />
{/if}
</div>
Loading