Skip to content

[Frontend][Testing] Guard against dead affordances - six enabled-but-inert controls found in one audit pass #1949

Description

@Chris0Jeky

Found during the maintainer's hands-on dogfooding audit, 2026-08-22 (v0.7.2 at 127.0.0.1:5000). Tracker: #1947.

Realignment 2026-08-23 (main a43df082c): the instance table below is now historical — the five cleanly-attributable rows are fixed, cited per row. The remaining scope of this issue is the guard mechanism itself, not the six instances. AC1's anchor half is delivered; its button half plus AC2/AC3/AC4 are open. Rows were ticked only where a merged PR closed the owning issue.

The pattern

The single most common defect class in the audit was a control that looks interactive and does nothing. Verified instances, each with DOM evidence in its own issue:

Control Evidence Issue Status 2026-08-23
Topbar "Settings" icon (read as a theme toggle) button.paper-topbar__icon-btn, no effect; body HTML byte-identical before/after #1932 fixed — PR #1954 (now labelled Appearance settings)
Topbar notifications bell same #1932 fixed — PR #1954
Topbar avatar <div aria-label="Profile: D"> — not even a button, so not focusable #1932 fixed — PR #1954 (divbutton, real account menu)
Sidebar "Solo Workspace" <button aria-label="Switch workspace">, no dialog/menu/route change #1934 fixed — PR #1957 (rendered non-interactive)
Review "Tune heuristics →" <a href="#">, no handler #1941 fixed — PR #1957 (removed)
Inbox "Accept on board" with no board selected enabled, fires zero network requests, no message #1944, #1938 dead-affordance half fixed — PR #1952 (disabled until a board is chosen, re-verified by the horizon run). #1938 stays open for the separate error-toast defect.

Six instances across five surfaces, all found by a single afternoon of clicking. That density says the next skin change or refactor will produce more, and each was individually cheap to ship precisely because nothing failed loudly.

These are worse than missing features: a missing control tells the user to look elsewhere, a dead control tells them the product is broken. That is the exact sentence the maintainer ended their walkthrough with — "it feels like it's just there for someone that doesn't exist."

Proposal

A mechanical guard, cheaper than fixing this class one instance at a time:

Note on scope

This is a guard, not a redesign — it does not decide what each control should do. Each dead control still needs its own fix in its own issue. The value here is preventing the seventh.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Priority IRelease-blocking/trust-breaking now. Per q-3 (2026-08-23) this tranche + #1876 = the v0.1.2 scope.bugSomething isn't workingdogfoodingFrom real personal/beta use; evidence-grade product feedback (exempt from intake severity bar).frontendPrimary implementation impact in Vue/TypeScript UI and client runtime.product-truthProduct or docs claim something unsupported, misleading, or silently untrue; truth-repair work.testingTest coverage, harnesses, regression prevention, and verification pipeline work.uxDiscoverability, accessibility, interaction model, and user workflow quality.

    Projects

    Status
    Next

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions