feat(ui): Phase B — sidebar drawer + SystemStatusDot + 키보드 nav
- +layout.svelte: 햄버거 → IconButton, 우측 nav → Button ghost, sidebar overlay → Drawer (uiState 단일 slot), Esc 글로벌 핸들러 ui.handleEscape() 위임 (5대 원칙 #2) - lib/stores/system.ts (신규): dashboardSummary writable + 60s 폴링, 단일 fetch를 SystemStatusDot(B)와 dashboard(C)가 공유 - SystemStatusDot.svelte (신규): 8px 도트 + tooltip, failed > 0 → error / pending > 10 → warning / 그 외 → success - Sidebar.svelte: 트리에 ArrowUp/Down 키보드 nav, 활성 도메인 row에 aria-current="page"
This commit is contained in:
@@ -66,6 +66,24 @@
|
||||
});
|
||||
|
||||
let totalCount = $derived(tree.reduce((sum, n) => sum + n.count, 0));
|
||||
|
||||
// ArrowUp/Down 키보드 nav — 현재 펼쳐진 tree-row만 traverse
|
||||
function handleTreeKeydown(e) {
|
||||
if (e.key !== 'ArrowDown' && e.key !== 'ArrowUp') return;
|
||||
const root = e.currentTarget;
|
||||
const rows = Array.from(root.querySelectorAll('[data-tree-row]'));
|
||||
if (rows.length === 0) return;
|
||||
const active = document.activeElement;
|
||||
const idx = active ? rows.indexOf(active) : -1;
|
||||
let next;
|
||||
if (e.key === 'ArrowDown') {
|
||||
next = idx < 0 ? 0 : Math.min(idx + 1, rows.length - 1);
|
||||
} else {
|
||||
next = idx <= 0 ? 0 : idx - 1;
|
||||
}
|
||||
e.preventDefault();
|
||||
rows[next].focus();
|
||||
}
|
||||
</script>
|
||||
|
||||
<aside class="h-full flex flex-col bg-sidebar border-r border-default overflow-y-auto">
|
||||
@@ -91,7 +109,7 @@
|
||||
</div>
|
||||
|
||||
<!-- 트리 -->
|
||||
<nav class="flex-1 px-2 py-2">
|
||||
<nav class="flex-1 px-2 py-2" onkeydown={handleTreeKeydown}>
|
||||
{#if loading}
|
||||
{#each Array(5) as _}
|
||||
<div class="h-8 bg-surface rounded-md animate-pulse mx-1 mb-1"></div>
|
||||
@@ -123,6 +141,8 @@
|
||||
|
||||
<button
|
||||
onclick={() => navigate(n.path)}
|
||||
data-tree-row
|
||||
aria-current={isActive ? 'page' : undefined}
|
||||
class="flex-1 flex items-center justify-between px-2 py-1.5 rounded-md text-sm transition-colors
|
||||
{isActive ? 'bg-accent/15 text-accent' : isParent ? 'text-text' : 'text-dim hover:bg-surface hover:text-text'}"
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user