Repository navigation
ui: fix and improve panel UX and accessibility from the October 2026 audit #333
Copy link
Copy link
Closed as duplicate
Closed as duplicate
Copy link
Labels
bugSomething is broken or shows wrong dataSomething is broken or shows wrong datafeatureA feature request or a pull request that adds oneA feature request or a pull request that adds one
Description
Context
This comes from a code audit of the panel's UX and accessibility (app/src), done in October 2026 while comparing the panel with other devtools (Nuxt DevTools, Vue DevTools and vite-plugin-inspect). It checks the panel against docs/contributing/ui-guidelines.md. Roadmap items live in #310, #311, #312 and #313. Items marked (to confirm) were not reproduced.
Problems
Medium
- Error states without Retry: several error states tell the user to reload or reopen the panel and offer no button. Add a Retry button that calls the existing
refresh()or load function, aspipes-inspector.ts:188-192already does. In the shell, retry the devframe connection with backoff and show a "Reconnect" button (app/src/pages/network-inspector.ts:296-303,app/src/pages/dashboard.ts:234-241,app/src/app.ts:372-375). - Store has no loading state: before the first shared state arrives, the store page shows "No page is reporting NgRx state yet.", so NgRx users see a wrong message for a moment. Set a
loadedflag on the first shared state value and show arole="status""Loading…" state until then (app/src/pages/store-inspector.ts:130-143). - No arrow-key navigation in long lists: the network timeline (up to 2,000 rows), the store change and event lists and the signals node list need one Tab per row. Add roving tabindex with ArrowUp/Down and Home/End, like
onListKeyinpipes-inspector.ts:1341. A sharedappRovingListdirective would cover all of them (app/src/pages/network-inspector.ts:595-616,app/src/pages/store-inspector.ts:362,499).
Low
- Search fields differ from page to page: the guidelines ask for a search field with an icon, Escape to clear and a count. Only six pages have the search icon. It is missing on
signal-inspector.ts:159,store-inspector.ts:100,forms-inspector.ts:358,route-tree.ts:115,route-timeline.ts:37androute-inspector.ts:55. Placeholders mix "Filter" and "Find", and only some end with "…". Extract an<app-search-field>inapp/src/uiwith the icon, Escape,autocomplete="off",spellcheck="false"and an optional count, and pick one verb. - Route tree has no tree semantics: depth is shown only by
padding-left, with noaria-level,aria-expandedor treegrid role, so screen readers lose the hierarchy. Userole="treegrid"witharia-levelandaria-expanded, and support Left/Right to collapse and expand (app/src/pages/route-tree.ts:176-177). - Filtered lists tracked by
$index: when the filter changes, rows are reused by position, so focus and selection jump. Track by a stable key such asroute.file + route.fullPath, a finding's code and location, or a component id (app/src/pages/route-inspector.ts:118,route-current.ts:95,167,route-lint.ts:65,forms-report.ts:162,cd-recording.ts:89). - Hex colors in the Analog view: the info and kind colors are hard-coded hex values outside the token system and the tint-contrast test. Move them to
app/src/styles/_palette.scssorapp/src/view-accents.tswith dark and light pairs, and add them toapp/src/__tests__/tint-contrast.test.ts(app/src/pages/analog-inspector.ts:1133-1138,1693-1725). - "Inspector turned off" gives no next step: the message names the
inspectorskey but has no docs link and no snippet. Add a link (asLimitNotedoes withLIMITS_DOCS_URL) and the exact option to turn it on, for exampleinspectors: { store: true }(app/src/app.ts:380-384). - No shortcut to focus search or switch tabs: there is no
/to focus the current page's search and no key to switch tabs. Add ahostlistener inapp.tsfor/(expose each page's search through a small service) and Alt+1..9 for tabs, skipped while focus is in an input. The Cmd/Ctrl+K palette is tracked in phase 3 of 4: a devframe shell as good as Vue and Nuxt DevTools #312 (app/src/app.ts:149-153).
Improvements
- One shared
<app-state kind="loading|error|empty|no-match">component with Retry and "Clear filters" slots, plus a spec that checks every page renders all four states (app/src/ui,app/src/pages/*.ts). - A spec that lists the pages and checks each one uses
<app-search-field>and the roving-list directive (app/src/ui,app/src/pages/*.ts). - Resizable list and detail panes with a keyboard-accessible splitter (
role="separator",aria-valuenow, arrow keys), width saved per view (app/src/pages/network-inspector.ts,store-inspector.ts,di-inspector.ts,app/src/tab-memory.ts). - "Pause live updates" and "Auto-scroll to newest" toggles on the network timeline, store change log and route timeline (
app/src/pages/network-inspector.ts,store-inspector.ts,route-timeline.ts). - Sortable column headers with
aria-sorton the network table (time, status, duration) and the route config table (app/src/pages/network-inspector.ts:580-592,app/src/pages/route-inspector.ts). - Saved filter chips per view, for example "Failed only" and "SSR" on the network page, stored in
localStorageinside try/catch (app/src/pages/network-inspector.ts,app/src/tab-memory.ts). - Run
pnpm test:axeon the loading, error and no-match states too, not only the populated static report.
Already tracked elsewhere
- DI and Signals pages show an empty state when loading fails: phase 1 of 4: safe by default, open in editor and cheap shell wins #310.
- No virtualization of long lists and trees (network table, component tree, store log): phase 3 of 4: a devframe shell as good as Vue and Nuxt DevTools #312.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething is broken or shows wrong dataSomething is broken or shows wrong datafeatureA feature request or a pull request that adds oneA feature request or a pull request that adds one
Activity