# MeshCore Analytics — Frontend UI/UX Audit **Date:** 2026-08-01 **Branch audited:** `fix/repeater-tree-modal` (working tree, uncommitted changes included) **Scope:** `frontend/src/**` (57 `.tsx`, 63 `.ts`, 12 `.css`), `frontend/index.html`, `backend/src/backend-site/login.html` **Type:** Read-only static audit. **No fixes were applied.** > **Resolution update — 2026-08-01:** The audit itself was read-only, but the > follow-up implementation has now resolved UI-01 through UI-28 in the current > working tree. Verification includes 38 frontend unit tests, 27 desktop/axe > browser tests, 21 responsive/mobile browser tests, production builds, the CSS > structure gate, and the asset-size budget. The browser suite covers every > public route, keyboard/focus flows, touch-only map controls, and modal geometry > from 320px through 1440px. The source gates report no undefined CSS custom > properties, no text below the 10px floor, no duplicate selectors, no missing > button `type`, no missing table-header `scope`, and no diff whitespace errors. --- ## 0. How to use this document Each finding has a stable ID (`UI-01`…`UI-28`), a severity, exact file/line anchors, the *measured* evidence, the user-visible impact, and a concrete fix with acceptance criteria. Findings are independent unless a **Depends on** line says otherwise. **Recommended order of work:** §7 has a sequenced plan. Do not work top-to-bottom by ID — several P1 items share a root cause and are cheaper to fix together. **Before you start:** read §6 ("Verified correct — do not re-investigate"). Several plausible-looking problems were checked and are *not* bugs. Re-chasing them wastes time and risks regressions. --- ## 1. Method 1. **Full read** of `tokens.css`, `globals.css`, `map-app.css`, `site-shell.css`, `site-content.css`, `network-intelligence.css`, `path-modal.css`, plus targeted reads of `feed-page.css`, `spam-page.css`, `stats-page.css`, `docs-pages.css`, `owner-portal.css`. 2. **Undefined CSS custom property scan** — parsed every `--x:` definition and every `var(--x)` usage across all CSS/TSX, flagged usages with no definition and no fallback. 3. **WCAG 2.1 contrast computation** — a scripted sRGB relative-luminance calculator (script in §8) was run on every foreground/background pair discovered, including alpha compositing for `rgba()` and `opacity`. 4. **Typography scan** — every `font-size` and `font` shorthand across all CSS, normalised px/rem, flagged `< 11px`. 5. **Cascade verification** — checked the *built* CSS in `frontend/dist/assets/` and Vite's preload manifest to confirm real-world stylesheet load order, because specificity ties are resolved by load order here. 6. **Dead-code cross-check** — every class named in a finding was checked against all TSX/HTML to confirm it actually renders. Findings on dead classes are demoted to P3 and labelled. 7. **Structured a11y scan** — form-control labelling, ``, `role=` correctness, icon-only buttons, `` - `frontend/src/pages/ukmesh/UKFeedPage.tsx:680` — `` Both are labelled only by the bare glyph `✕` (U+2715). Screen readers announce it as "multiplication X", "times", or nothing depending on the AT and its punctuation settings. Every other close control in the codebase is done correctly — `App.tsx:656` (`aria-label="Close"`), `MapLibreMap.tsx:1393` (`aria-label="Close node details"`), `WatchlistPanel.tsx:54`, `NodeSearch.tsx:172`, `Combobox.tsx:91`. These two are the outliers. **Fix** ```tsx /* PacketDetailPanel.tsx:272 */ /* UKFeedPage.tsx:680 */ ``` (The `type="button"` on the second also resolves one instance of **UI-20**.) --- ### UI-14 — P2 — Feed packet search has no accessible name **File** `frontend/src/pages/ukmesh/UKFeedPage.tsx:530–536` ```tsx ``` No `