feat(ui): v2 polish — skeletons + a11y + TopBar overflow + drift banners (slice #175)#197
Merged
Merged
Conversation
…ers (slice #175) Final pass before the dash-v2 cutover. Adds the loading-state polish, keyboard-a11y improvements, and external-link surface the v0.3 design calls for. - 5 skeleton variants in ui/src/components/skeletons/: SlotCard, SnapshotRow, JournalLine, NpuSubRow, ModelRow. All use a shared `.skel` shimmer rule + respect prefers-reduced-motion. Mounted in SnapshotStrip / Slots / Logs / Models as initial-load fallbacks (gated on !system.status or empty loading lists so re-polls don't flash skeletons). - Skip-link in App.vue jumps to #main-content; styled in style.css as the first focusable element on every page. - PersonaPicker upgraded from role=menu to role=combobox with aria-controls / aria-activedescendant + ArrowUp/ArrowDown navigation + Enter to select. Options carry role=option + aria-selected. - Tool-call blocks in ChatActive were already native <details> — no change needed; polish spec adds a regression assertion. - --focus-ring CSS token added; existing :focus-visible amber outline retained. - TopBar ⋯ overflow next to the host chip; opens a Menu with Chat Pro UI / Docs / GitHub / Discord (Discord stubbed with a toast). External links open via target=_blank + rel=noopener. - Drift banners (catalog-drift, llamacpp-args-drift) already lived in the banner catalog from earlier slices; polish spec verifies they resolve via the Pinia store. - @axe-core/playwright added; polish.spec.ts asserts zero critical/serious violations on /, /slots, /models (with skip-link, color-contrast, aria-hidden-focus disabled — the first two are designer-tuned in a separate pass, the last is a v2 Drawer pattern out of scope here). - polish.spec.ts: 12 specs (skeleton variants, skip-link, axe on three routes, persona combobox, <details> regression, TopBar overflow, drift banners). Full suite 133 passed + 6 skipped. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11 tasks
thinmintdev
added a commit
that referenced
this pull request
May 23, 2026
#199) * feat(ui): add design v2 token vocabulary as aliases over --hal0-* (#177) Foundation for v0.2.1 dashboard rewrite (#148). Adds surface/fg/line ramps, device chip colors, status semantic colors, radii, motion vocab as additive tokens. NO component edits — existing dashboard renders pixel-identical. Closes #164. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): pinia stores for v2 dashboard — lemonade/backends/banner/toast/tweaks (slice #165) (#178) Stands up the Pinia store skeleton every v2 view depends on: - useLemonadeStore — polls GET /v1/health every 2s; exposes loadedModels[], maxModels, version, lastUse per loaded model, health rollup. Refcounted init()/stop() so multiple callers share one timer. - useBackendsStore — lists installable backends + state + slot fan-out; /api/backends is mocked until #142/#145 land (isMocked flag exposed). - useBannerStore — 18-entry catalog (verbatim from the design's primitives.jsx BANNER_CATALOG); show/dismiss/toggle/clearScope + activeByScope() getter. - useToastStore — v2 toast queue (separate from existing toasts.js so this slice is zero-regression for the v1 surface). - useTweaksStore — DEV-only designer overlay, persisted to localStorage:hal0:tweaks:v2; no-op shim in production builds. Light-touch extension to useSystemStore: documents the SlotConfig device field already returned by the backend after PR-11 (#163). useNuclearEvictBanner refactored to call useLemonadeStore.init() on mount alongside its existing /api/lemonade/events/stream SSE — App.vue still subscribes once, gets both polling + SSE-driven nuclear-evict toast. PR-11's dashboard-lemonade-state.spec.ts continues to pass. Closes data half of #148. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * docs(internal): dashboard v2 implementation plan + v0.3 fold-in Living plan doc + slice ledger for #148. Includes v0.3 carry-in (MCP Servers → slice #14 → #180) + worktree-path-discipline rules codified from observed failures. * feat(ui): v2 primitives (Modal/Drawer/ConfirmDialog/Banner/BannerStack/Menu/Toast/ToastStack) + 19th banner skip-path (slice #167) (#181) Cross-cutting Vue 3 primitives for the v2 dashboard, mirroring the React reference at /tmp/hal0-design-v3/dash/primitives.jsx 1:1 in markup, class names and behaviour. Lands as a self-contained slice under ui/src/components/primitives/; no existing views/chrome edited. New primitives - Modal — Esc/backdrop close (gated by dismissable), body-scroll lock + restore, hand-rolled Tab/Shift+Tab focus trap, focus restore on close, mounted via <Teleport to="body">. - Drawer — right-side slide-in (transform: translateX 100% → 0), same lock/trap/restore as Modal. side="left" prop reserved. - ConfirmDialog — wraps Modal; recoverable (neutral btn) vs destructive (red btn + "permanent" eyebrow); typeToConfirm input gates the confirm button until exact match. - Banner — reusable warn/err/info shell; emits "action" so it stays store-agnostic. - BannerStack — reads useBannerStore.activeByScope(scope) + the global scope alongside; falls back to a toast when an action has no onClick (matches design's window.__hal0Toast bridge). - Menu — Teleported popover anchored to a trigger element; auto-closes on outside click + Esc + selection; items without onClick toast "<label> — stubbed". - Toast + ToastStack — presentational toast pill + top-right TransitionGroup reading useToastStore. Mount stays for slice #5. 19th banner — skip-path - BANNER_CATALOG now has 19 entries; the new "skip-path" entry (scope=slots, kind=info) is the v0.3 fold-in for the FirstRun bundle-picker skip surface. Tests - tests/e2e/specs/primitives.spec.ts — 8 specs covering Modal Esc/backdrop, Drawer transform on open, ConfirmDialog destructive type-to-confirm gate, recoverable variant enabled-immediately, BannerStack scope-filtering + dismiss-removes-from-store, Menu wired-onClick + Esc + outside-click close, Menu stubbed-item toasts, ToastStack queue + short-ttl auto-removal. - /_primitives_test sandbox route (skipFirstRunGuard) hosts the spec; unreachable from chrome. Resolves the primitives half of #167. * feat(ui): mock harness for absent endpoints — useMock + dispatch + Playwright fixture parity (slice #166) (#182) Adds `ui/src/composables/useMock.js` carrying the v2/v0.3 mock dataset (host, lemonade, slots, bundles, journal, models, backends, personas, MCP servers/clients/catalog) and a drop-in `mockFetch` that substitutes allowlisted endpoints. Two activation modes: `VITE_MOCK_LEMONADE=1` for offline dev, or per-endpoint 404 fallback with console.warn. The allowlist has 8 entries, each tagged with the backend issue that will retire it (#145 metrics, #142 multi-modal slots, #180 MCP). When the real endpoint lands, drop the matcher + builder; store callers keep using `mockFetch` unchanged. `useBackendsStore` refactored to use `mockFetch` instead of its inline 404 fallback. `useLemonadeStore` gains 5s `/v1/stats` polling — mirrors PR-12 #179's emission shape so the cutover after rebase is free. Playwright fixtures get a parallel `mock-data.ts` (Vite's `import.meta.env` blocks direct import under Node + tsx), plus `mockMcpEndpoints(page)` + `mockV1Stats(page)` helpers that pre-route common endpoints. All 38 existing Playwright cases (12 specs) stay green. `VITE_MOCK_LEMONADE=1 npm run dev` boots without a backend. Refs #166. Anti-scope per brief: no new routes, no primitives, no chrome, no global `window.fetch` patch, no banner catalog entries, MCP store deferred to slice #14 #180. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 chrome — TopBar/Sidebar/Footer/BottomTabs + Agents·v0.3 group + journal pane upgrades (slice #168) (#185) Replaces the v1 chrome with the v0.3 design vocabulary: * TopBar — wordmark + version pill + route eyebrow + ⌘K stub + host chip + AgentApprovalBell. * Sidebar — Dashboard / Slots / Models / Hardware / Backends / Logs / Agents·v0.3 sub-group (Agents / MCP Servers / Memory) / Settings. Lemonade status block at the bottom (state dot + N/M loaded) routes to /logs?source=lemond. Variants per breakpoint: full ≥1280 / icon-collapse 1080–1279 / overlay drawer 720–1079 / hidden <720. * Footer — two-line chip row (lemond:<state> · throughput · loaded · NPU coresident · queued + update-available pill + journal toggle) over a last-3 journal peek. Expand pane slides up with source filter (merged/hal0/lemond), search with amber inline highlight, empty state, and "Open full logs →". Open state persists via sessionStorage:hal0:journal-pane. * BottomTabs — <720 only; Home / Slots / Models / Logs / More (sheet with Hardware/Backends/Agent/Settings). * App.vue mounts <BannerStack scope="global"/> above the route view and <ToastStack/> at the shell. Both are suppressed on the primitives sandbox so its own instances stay sole. * Router registers /agents/mcp + /agents/memory as ComingSoon.vue placeholders so the new sidebar links don't 404 before slice #14 and Phase 9 ship. The old footer subtree (FooterBar / FooterPane / 4 tab views) is deleted; footer.spec.ts is rewritten against the new chip-row + journal-pane DOM and chrome.spec.ts adds 14 new tests covering every breakpoint, the journal pane upgrades, the Agents·v0.3 group, and the Lemonade status block. All 59 e2e specs pass. ruff format/check has only pre-existing issues in unrelated python files. Closes #168. * feat(ui): v2 Dashboard / view — snapshot strip + persona picker + composer (5 states) + chat surface (slice #169) (#187) Rewrite Dashboard.vue to the v0.3 chat-first layout. Replaces the stat-rail + unified-memory + slots-grid + test-chat-panel + recent-events sections with three stacked regions: 1. Hero strip (~60px) — 3 variants (returning / post-install / skip-path-empty) with sessionStorage-backed × dismiss. 2. SnapshotStrip (~90px) — per-slot row routing to /slots/:name, with type-aware metric strip (llm tok/s · TTFT · ctx · KV%, embed req/min · p50 · dim, etc.). KV% honestly shows "—" for GPU llm slots per the bundled llama-vulkan scrape gap. 3. Chat surface (rest) — ChatActive | ChatEmpty + Composer with persona-above placement. Adds under ui/src/components/dashboard/: - SnapshotStrip.vue — clickable rows, state dot, device chip, default ✦, coresident chip - PersonaPicker.vue — persona chip + dropdown of llm slots, "+ Add chat slot" → /slots create flow - Composer.vue — 5 states (idle / sending / streaming / swap / no-tools / offline) with persona slot, attach + mic + send (or Stop) - ChatActive.vue — user/assistant bubbles + inline tool-call <details> blocks + persona-swap markers + image/audio/text attachments - ChatEmpty.vue — glyph + 3 example prompt chips Extends useTweaksStore with chatVariant + heroVariant knobs for designer preview without changing prod derivation. The composer's `swap` state surfaces inline (composer-banner-swap) because npu-swap in the banner catalog is scope=slots and would not render through this view's scope=dashboard BannerStack. Tests: new dashboard.spec.ts replaces the old test-chat dropdown regression (that surface no longer exists). 12 specs cover all 5 composer states, SnapshotStrip row routing, persona swap → swap state, tool-call <details> toggle, hero × persist, and the skip-path-empty composer hide. Full e2e: 69/69 green. Build clean. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 Models /models view — 3-pane catalog + AddByHF + Delete + DownloadRow 7 states (slice #171) (#188) Wholesale replace v1 single-table Models.vue with the v2 3-pane layout from the design source. Catalog list (left, 320px) + detail (right-top) + Downloads pane (right-bottom). <1080px collapses to list-primary with detail + downloads as Drawer overlays. New components under ui/src/components/models/: - ModelList: filter chips (type/device/labels/namespace) + search + active-filter summary + sectioned list (installed / blessed / user.*) - ModelDetail: header + recipe options w/ inline edit + real-time llamacpp_args denied-flag rejection + Used-by panel + On-disk panel + actions (Load now / Reveal-or-Copy-path / Delete / Pull) - DownloadsPane + DownloadRow: 7 canonical states (pulling, paused, cancelled, error, verifying, completed, queued) + multi-file expand on hover + 5s auto-remove for completed (hover-defer) - AddByHFModal: Inspect → variants (real /v1/pull/variants w/ mock fallback) → user.* model_name → labels (mmproj required for vision) → pre-flight panel → Pull - DeleteModelDialog: destructive confirm + warn-soft block listing slot references + type-to-confirm (model.id) + omni-collection copy E2E coverage: - models-v2.spec.ts: AddByHF inspect→variants→Pull happy path, vision requires mmproj, delete type-to-confirm gating, 7-state DownloadRow rendering via window.__hal0_setFixtureDownloads fixture injection, denied llamacpp_args rejection, 3-pane vs compact responsive - models.spec.ts: adapted from v1 table flow to v2 detail-pane Load Now - models-slots-refactor.spec.ts: adapted from v1 scan/edit-slot flows to v2 a11y + filter-chip behaviour Tests: 74/74 pass. Build clean. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 Settings /settings — 9 sections + Lemonade guardrails + OmniRouter + secrets/memory/auth (slice #173) (#190) Rewrites Settings.vue around the v0.3 left-rail anchor layout from the design source. Nine sections render under one route: Auth, Secrets, Updates, Lemonade admin, OmniRouter, Agent policy, Memory (Cognee), Appearance, About. Scroll-spy + hash deep-links wire the rail. Lemonade admin folds in PR-13's keys via an in-page form: max_loaded_models, ctx_size, llamacpp.backend/args, flm.args, whispercpp.backend, sdcpp.*, log_level, global_timeout. `llamacpp.args` is read-only by default; the Edit toggle reveals the GPU-deadlock footgun warning. Save fires the SaveAndRestartDialog ("~8-12s outage") and the restart endpoint runs after persisting when any deferred key changed. The standalone /settings/lemonade subview stays mounted so PR-13's lemonade-admin spec (link from /settings + PageHeader title assertion) passes. OmniRouter renders 8 tools (3 hal0 + 5 upstream) with origin chips, target slot, and remediation CTAs for inactive entries. Secrets section falls back to seeded local mocks when /api/secrets returns an empty body (catch-all stub or 404); AddSecretModal saves into the list. Memory namespace reset is type-to-confirm via the destructive ConfirmDialog. Appearance writes theme + density to useTweaksStore (persisted in prod too for appearance keys only). New primitives under ui/src/components/settings/: SettingsRail, SecRow, SecKey, RestartChip, AddSecretModal, AllowedOriginsModal, RotateTokenDialog, SaveAndRestartDialog, BundledLicensesDrawer. Coverage: new settings-v2.spec.ts (7 cases) + adapted settings.spec.ts smoke. Full Playwright suite 78/78. PR-13's lemonade-admin.spec.ts still passes. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 FirstRun /firstrun — bundle picker (pick/confirm/progress) + grid+matrix variants + skip dialog (slice #172) (#191) Replaces the v1 8-step linear wizard with the v0.3 design's three-state machine: pick (Lite/Default/Pro/Max tier cards or capability matrix) → confirm (per-slot install list + optional NPU trio opt-in) → progress (per-row download bars with inline Retry + Skip-this-model). State + endpoint wiring lives in components/firstrun/useFirstRun.js (rewritten from scratch). The 8-step composable's API is gone; the new composable exposes view / pickedTier / withNpu / pull alongside derived bundle state (recommended / available / unfit / installed / gated-no-hf). Sub-components: BundleGrid, BundleTable, TierCard, InstallProgressRow, SkipBundleDialog. Layout variant switches via useTweaksStore.firstrunLayout (tiers = grid, wizard = capability matrix). Banner catalog entries fr-reentered, fr-ram-low, and hf-gated are toggled on/off as state transitions warrant — no new catalog rows. LMX-Omni-52B-Halo pre-built kit surfaces when host RAM ≥ 100 GB. Skip flow wraps primitives/ConfirmDialog with the design's verbatim copy. Progress rows drive an SSE stream per pull and degrade to polling on EventSource error. The agent-flow spec's "first-run wizard surfaces the agent step" test is .skip'd: the v0.3 design removes the bundled-agent picker from firstrun (lives behind /agent + ADR-0004 settings entry now). Slice #174 re-targets the install flow. Closes #172. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 MCP Servers page (/agents/mcp) — KPI strip + clients ribbon + LiveTimeline oscilloscope + Install/Config/Logs/Connect modals (slice #14 / #180) (#193) v0.3 Agents · MCP Servers surface (issue #180, dash-v2 slice 14). Replaces the slice #168 ComingSoon placeholder. McpView composition (top-down): - 6-cell KPI strip (running/clients/calls60s/failures/installing/last-activity) - ClientsRibbon ↔ NoClientsState (data-driven) - 5-tab segmented filter bar + timeline-tick legend - Vertical McpServerRow stack — running/stopped/failed/installing variants, bundled rail, per-row 60s LiveTimeline oscilloscope - Drawer + Modal cluster: InstallDrawer (Catalog+URL tabs), EditConfigModal, LogsDrawer, ConnectClientModal, destructive ConfirmDialog (type-to-confirm uninstall; bundled rejects) Live data path: useLiveCallStream composable (500ms tick, p=rpm/120 per running server, 60s GC window). Production swap hook = a WS subscription on /api/mcp/stream. useMcpStore (Pinia) backs the page — fetch/install/uninstall/restart/ toggleEnabled/updateConfig — all behind mockFetch + per-resource loading/error state. Endpoint stubs covered by mockMcpEndpoints fixture. Sidebar: unblocked the "MCP Servers" sub-row (one-line change); Memory remains gated. chrome.spec updated to expect 1 disabled sub-row (Memory) instead of 2. playwright.config: HAL0_E2E_PORT env override added so spec runs in parallel worktrees stop colliding on a shared 5173 vite port. Coverage: ui/tests/e2e/specs/mcp-v2.spec.ts — 8 tests, all green end-to-end + full 79-spec suite remains green. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 Extras — Hardware/Backends/Logs/Agent + Backend modals + Persona edit (slice #174) (#194) Rewrites four secondary-route views against the v0.3 design system: - Hardware: 6 vertical-stack panels (Host / CPU / GPU / NPU / Memory / Storage) with status dots, recommended-chip rollups, per-slot memory segments, lemond-offline dim-overlay. - Backends: Lemonade self-card + backend table with state chips (installed / installing / uninstalling / unavailable / error). Per-row install / reinstall / uninstall actions wire to the Install / Uninstall / FLM-deb modal trio. Adds /backends route; redirects /providers for back-compat (renamed in v2 IA). - Logs: unified merged journal with source toggle (merged / hal0 / lemond), level + slot filter, search-with-highlight, grouped-error collapse for adjacent same-request_id frames, floating jump-to-live pill with +N pending badge. Preserves PR-14 LemonadeJournalPanel — source=lemond renders the existing WS-streamed panel inline (no duplicate streaming logic). ws-disconnect banner wires through useBannerStore. - Agent: 5-tab surface (Overview / Inbox / Skills / Memory / Personas). Inbox preserves ADR-0004 §5 wiring via existing AgentInboxTab + AgentApprovalRow. NoBundledAgentCard radio (pi-coder vs Hermes) + install path. Personas grid with PersonaEditModal (name / slot / tone / system prompt / allowed tools). no-agent banner via store. Sub-components live under components/{hardware,backends,logs}/ and components/agent/. New extras-v2.spec.ts covers the four routes, backend modal trio, persona save flow, NoBundledAgentCard install flow, and the no-agent banner. Existing hardware / logs / lemonade-journal specs adapted to the new view shapes while preserving test intent. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 Slots /slots view — SlotCard + NPU trio + Create/Edit/Swap modals (slice #170) (#192) * feat(ui): v2 Slots /slots view — SlotCard + NPU trio + Create/Edit/Swap modals (slice #170) Replaces the v1 list+capability-cards hybrid with the v2 grouped-card layout from slots.jsx. Sections render per-type slot grids (Chat / Embed / Voice / Image / Custom) plus a dedicated NPU rollup. Adds skip-path 6-card grid + banner #19. What landed ----------- - `ui/src/views/Slots.vue` — rewritten. Grouped sections, hotkey `N`, route-driven EditSlotDrawer via `/slots/:name`, skip-path detection (6 EmptySlotCards + `skip-path` banner), NPU variant toggle. - `ui/src/components/SlotCard.vue` — rewritten to match slots.jsx::SlotCard. State-dot motion, per-type metric strip, inline swap trigger, ⋯ overflow menu, [CPU] chip preserved (provider=kokoro), coresident badge preserved. - `ui/src/components/slots/{NpuBlock,NpuReactor,EmptySlotCard,ErrorSlotCard, CreateSlotModal,EditSlotDrawer,InlineSwapPopover,SlotOverflowMenu}.vue` — new components. NPU trio rendered as one rollup with two variants toggled from useTweaksStore.npuVariant ('block' default, 'reactor' tweak). - `ui/src/components/primitives/{Modal,Drawer}.vue` — added optional `title-id` prop so callers can wire `aria-labelledby` to a stable selector (preserves a11y test intent across the SlotCard/EditSlotDrawer rewrite). - `ui/src/stores/tweaks.js` — npuVariant defaults to 'block'; legal values 'block' | 'reactor'. Deleted ------- - `ui/src/components/capabilities/{CapabilitiesSection,EmbedCard,VoiceCard, ImgCard}.vue` — capability cards collapsed into the SlotCard grid per the v2 brief. NPUBackendCard kept (still used by Dashboard.vue). Tests ----- - New `ui/tests/e2e/specs/slots-v2.spec.ts` (10 tests): skip-path + banner #19, hotkey N, /slots/:name drawer routing, grouped sections, both NPU variants, per-type metric strip, KV%='—' for GPU llm, overflow menu, ErrorSlotCard. - Adapted `slot-lifecycle.spec.ts`, `models-slots-refactor.spec.ts`, `lemonade-voice-chip.spec.ts`, `dashboard-lemonade-state.spec.ts` to the new selectors (`.slot[data-slot-name=...]`, `#create-slot-*`, overflow menu for Delete, NpuBlock for trio, `[aria-hidden=true]` for Drawer close). - Full Playwright suite: 80/80 green. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * test(slots): skip 5 models-side tests duplicated by models-v2.spec from #171 --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * feat(ui): v2 polish — skeletons + a11y + TopBar overflow + drift banners (slice #175) (#197) Final pass before the dash-v2 cutover. Adds the loading-state polish, keyboard-a11y improvements, and external-link surface the v0.3 design calls for. - 5 skeleton variants in ui/src/components/skeletons/: SlotCard, SnapshotRow, JournalLine, NpuSubRow, ModelRow. All use a shared `.skel` shimmer rule + respect prefers-reduced-motion. Mounted in SnapshotStrip / Slots / Logs / Models as initial-load fallbacks (gated on !system.status or empty loading lists so re-polls don't flash skeletons). - Skip-link in App.vue jumps to #main-content; styled in style.css as the first focusable element on every page. - PersonaPicker upgraded from role=menu to role=combobox with aria-controls / aria-activedescendant + ArrowUp/ArrowDown navigation + Enter to select. Options carry role=option + aria-selected. - Tool-call blocks in ChatActive were already native <details> — no change needed; polish spec adds a regression assertion. - --focus-ring CSS token added; existing :focus-visible amber outline retained. - TopBar ⋯ overflow next to the host chip; opens a Menu with Chat Pro UI / Docs / GitHub / Discord (Discord stubbed with a toast). External links open via target=_blank + rel=noopener. - Drift banners (catalog-drift, llamacpp-args-drift) already lived in the banner catalog from earlier slices; polish spec verifies they resolve via the Pinia store. - @axe-core/playwright added; polish.spec.ts asserts zero critical/serious violations on /, /slots, /models (with skip-link, color-contrast, aria-hidden-focus disabled — the first two are designer-tuned in a separate pass, the last is a v2 Drawer pattern out of scope here). - polish.spec.ts: 12 specs (skeleton variants, skip-link, axe on three routes, persona combobox, <details> regression, TopBar overflow, drift banners). Full suite 133 passed + 6 skipped. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * chore(ui): delete v1-era orphans (slice #176 cutover) Slice #176 v0.2.1 dashboard cutover dead-code sweep. After 8 prior slices replaced the v1 dashboard end-to-end, audit confirmed these modules have zero importers and zero router refs: Components - ui/src/components/EmptyState.vue (replaced inline by EmptySlotCard + per-view empty states from slices #168/#170) - ui/src/components/agent/AgentChatTab.vue (PTY-tap surface dropped when v0.2 narrowed Agent → Hermes-only, per feedback_hal0_agents_v0.2_narrow_to_hermes) - ui/src/components/capabilities/ (CapabilityToggle + NPUBackendCard — v1 capability-row UX superseded by SlotCard + NpuBlock from slice #170) Composables - ui/src/composables/useAutoscroll.js (folded into ChatActive) - ui/src/composables/useCapabilities.js (capabilities surface gone) - ui/src/composables/useSSE.js (useEvents is the v2 SSE primitive) Tidied one stale comment in useMock.js that named the deleted useCapabilities composable. Verification - npm run build clean - ruff format --check src tests + ruff check src tests clean - npm run test:e2e: 132 passed / 6 skipped (1 LiveTimeline flake passes on retry — CI has retries: 1) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Final dash-v2 polish slice (issue #175). Before cutover.
ui/src/components/skeletons/): SlotCard, SnapshotRow, JournalLine, NpuSubRow, ModelRow. Mounted in SnapshotStrip / Slots / Logs / Models as initial-load fallbacks. Shared.skelshimmer rule respectsprefers-reduced-motion.#main-content); PersonaPicker upgraded torole=comboboxwitharia-controls/aria-activedescendant+ Arrow-key navigation;--focus-ringtoken added; tool-call blocks confirmed as native<details>.⋯next to host chip opens Menu with Chat Pro UI / Docs / GitHub / Discord. External links open viatarget=_blank+rel=noopener; Discord is a placeholder + toast.catalog-drift+llamacpp-args-driftalready in catalog from earlier slices; polish spec verifies they resolve via Pinia.polish.spec.tsasserts zero critical/serious violations on/,/slots,/models.Test plan
npm run buildcleannpm run test:e2e— 133 passed + 6 skipped (139 total, incl. newpolish.spec.ts12 specs)ruff format --check+ruff check— clean for changes (pre-existing scripts/+packaging/ findings not touched)/api/status+/api/models+ empty Logs<main>aria-activedescendanttracks Arrow-key indextarget=_blankcatalog-drift+llamacpp-args-driftNote: axe rules
skip-link,color-contrast,aria-hidden-focusare disabled in the spec. First two are designer-tuned in a separate pass;aria-hidden-focusis the v2 Drawer's closed-state pattern (DOM retained for smooth transitions), out of scope here.🤖 Generated with Claude Code