Skip to content

feat(site/src/modules/dashboard/Navbar): replace proxy emoji with latency radio icon in trigger - #28128

Open
tracyjohnsonux wants to merge 7 commits into
mainfrom
latency-dropdown-radio-icon
Open

feat(site/src/modules/dashboard/Navbar): replace proxy emoji with latency radio icon in trigger#28128
tracyjohnsonux wants to merge 7 commits into
mainfrom
latency-dropdown-radio-icon

Conversation

@tracyjohnsonux

@tracyjohnsonux tracyjohnsonux commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Updates the latency dropdown's collapsed views in the navbar:

  • Removes the proxy emoji (ExternalImage) from the desktop trigger and the mobile "Workspace proxy settings" row.
  • Shows a lucide RadioIcon instead, colored via getLatencyColor (matching the loading state used by the Latency component on desktop).
  • Keeps the latency text in content-primary; only the icon carries the latency color.

The expanded proxy lists are unchanged (they keep the proxy icon and colored latency text).

Story changes:

  • Added ClosedWarningLatency and ClosedCriticalLatency to cover the icon color per latency level.
  • Right-aligned the ProxyMenu story trigger to match its navbar placement, so the end-aligned menu renders without collision shifting in the story canvas.

Generated by Coder Agents on behalf of @tracyjohnsonux.

@tracyjohnsonux
tracyjohnsonux marked this pull request as ready for review August 13, 2026 16:20

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review

coder-agents-review Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Chat: Review posted | View chat
Requested: 2026-08-13 19:39 UTC by @tracyjohnsonux

Review history
  • R1 (2026-08-13): 12 reviewers, 1 Nit, 2 Note, 1 P2, 2 P3, REQUEST_CHANGES. Review
  • R2 (2026-08-13): 10 reviewers, 1 Nit, 2 Note, 1 P2, 4 P3, COMMENT. Review
  • R3 (2026-08-13), 1 Nit, 2 Note, 1 P2, 4 P3, COMMENT. Review
  • R4 (2026-08-13): 10 reviewers, 2 Nit, 2 Note, 1 P2, 4 P3, COMMENT. Review
  • R5 (2026-08-13): 10 reviewers, 2 Nit, 2 Note, 1 P2, 4 P3, APPROVE. Review

deep-review v0.9.0 | Round 5 | 48e1e28..0ceeed3

Last posted: Round 5, 9 findings (1 P2, 4 P3, 2 Nit, 2 Note), APPROVE. Review

Finding inventory

Finding inventory - PR #28128

Findings

# Sev Status Location Summary Round Reviewer Posted
CRF-1 P2 Author fixed (c1a5ea3) site/src/modules/dashboard/Navbar/MobileMenu.tsx:137 Mobile trigger no longer announces the selected proxy to screen readers R1 Leorio P2, Hisoka Nit Yes
CRF-2 P3 Author fixed (c1a5ea3) site/src/modules/dashboard/Navbar/ProxyMenu.tsx:94 text-content-primary override paints CircleHelpIcon bright while the sibling RadioIcon stays muted in the unknown-latency state R1 Pariston P3, Zoro P3, Nami Note Yes
CRF-3 P3 Author fixed (c1a5ea3) site/src/modules/dashboard/Navbar/ProxyMenu.stories.tsx:108 New loading-branch ternary (proxyLatencyLoading ? undefined : ...) has no story coverage R1 Bisky Yes
CRF-4 Nit Author accepted R2 (two-caller extraction is borderline; revisit at third caller) site/src/modules/dashboard/Navbar/ProxyMenu.tsx:85 RadioIcon + getLatencyColor + neutral-text pattern duplicated between ProxyMenu and MobileMenu; candidate for a Latency variant R1 Pariston Yes
CRF-5 Note Author accepted R2 (removing visible proxy identity is the intent) site/src/modules/dashboard/Navbar/ProxyMenu.tsx:83 Collapsed trigger no longer visually identifies the proxy for sighted users; two proxies in the same latency band render identically R1 Hisoka, Pariston Yes
CRF-6 Note Author accepted R2 (keep hard-coded values until more level-specific stories exist) site/src/modules/dashboard/Navbar/ProxyMenu.stories.tsx:116 Story latency values (224, 471) are coupled to getLatencyLevel thresholds with no test enforcing the coupling R1 Gon Yes
CRF-7 P3 Author fixed (4c229e9) site/src/modules/dashboard/Navbar/MobileMenu.tsx:144 Mobile sr-only "Latency for {name}" (added by CRF-1 fix) is followed by silence when latency is undefined; desktop announces "Latency not available." R2 Mafuuu P3, Razor P3 Yes
CRF-8 P3 Author fixed (4c229e9) site/src/modules/dashboard/Navbar/MobileMenu.tsx:140 Mobile trigger uses the same getLatencyColor(latency?.latencyMS) logic as desktop but no story exercises the warning, critical, or no-latency bands; asymmetric with the R1 CRF-3 fix on desktop R2 Bisky Yes
CRF-9 Nit Author fixed (0ceeed3) site/src/modules/dashboard/Navbar/MobileMenu.tsx:145 Mobile className gate tests the report object; desktop's CRF-2 fix gates on latencyMS. Divergent predicate; would reintroduce the CRF-2 symptom if a report ever carries latencyMS === 0 R4 Mafuuu Yes

Contested and acknowledged

CRF-4 (Nit, ProxyMenu.tsx:85) - Duplicated RadioIcon + getLatencyColor + neutral-text pattern

  • Finding: Pattern duplicated between ProxyMenu.tsx:85-98 and MobileMenu.tsx:137-146; proposal was to fold the color-split rule into a Latency variant or LatencyBadge wrapper.
  • Author accepted (R2): "Declining for this PR to keep it single-purpose; two call sites is borderline for extraction as noted. Worth revisiting if a third caller appears." Matches the finding's own "two call sites is borderline for extraction" language.

CRF-5 (Note, ProxyMenu.tsx:83) - Collapsed trigger loses visible proxy identity

  • Finding: After the emoji swap, sighted users can no longer distinguish two proxies whose latencies fall in the same color band from the collapsed trigger.
  • Author accepted (R2): "Acknowledged; removing the visible proxy identity from the collapsed trigger is the intent of this change. The badge-overlay idea is a good option if visible identity is wanted back later." The PR description makes the intent explicit; the badge-overlay alternative is captured for future work.

CRF-6 (Note, ProxyMenu.stories.tsx:116) - Story latencies coupled to level thresholds without enforcement

  • Finding: Story values (224, 471) sit inside the getLatencyLevel warning/critical bands with no code enforcing the coupling; a future threshold shift silently invalidates the story labels.
  • Author accepted (R2): "Acknowledged; keeping the hard-coded values for now per the note. A shared per-level sample constant makes sense once more level-specific stories exist." Matches the finding's own "not worth a shared constant for two stories today" framing.

Round log

Round 1

Panel. Netero + 12 panel reviewers. 1 P2, 2 P3, 1 Nit, 2 Notes. Reviewed against 48e1e28..732942e.

Round 2

Churn guard PROCEED (3 addressed, 3 acknowledged, 0 contested/silent). Panel re-review against 48e1e28..c1a5ea3. Netero R2 verified all three R1 fixes and found no new findings. Panel raised 2 new P3 findings, both mobile-only asymmetries with the R2 fixes.

Round 3 update

BLOCKED. All open findings (CRF-7, CRF-8) silent since R2. Head SHA unchanged (c1a5ea341302). No review.

Round 4

Churn guard PROCEED (2 addressed, 0 silent). Panel re-review against 48e1e28..4c229e9. Netero R4 verified both R2 fixes and found no new findings. Panel raised 1 new Nit (mobile className gate predicate drift; Mafuuu; noted-but-not-raised by Pariston and Knov, higher severity wins).

Round 5

Churn guard PROCEED (1 addressed, 0 silent). Panel re-review against 48e1e28..0ceeed3.

About deep-review

CRF = Coder Review Finding (P0-P4, Nit, Note)

Reviewer Focus
Bisky tests
Chopper ops/errors
Churn-guard change verification
Ging language modernization
Gon naming
Hisoka edge cases
Killua perf
Kite change integrity
Knov contracts
Knuckle SQL
Komugi flake/determinism
Kurapika security
Law decomposition
Leorio docs
Luffy product
Mafu-san process
Mafuuu contracts
Melody dispatch/pairing
Meruem structural
Nami frontend
Netero mechanical checks
Pariston premise testing
Pen-botter product gaps
Razor verification
Robin duplication
Ryosuke Go arch
Takumi concurrency
Zoro shape

🤖 Managed by Coder Agents.

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small, focused swap: proxy emoji out, latency-colored RadioIcon in, expanded lists untouched. The pieces that worked: getLatencyColor(loading ? undefined : latency) at ProxyMenu.tsx:87 mirrors Latency.tsx:25 so both surfaces share the same loading-vs-value rule; twMerge collapses text-content-primary over the internal latencyColor in Latency's number branch exactly as intended; story latencies (224, 471) land inside the real getLatencyLevel bands with margin; and the mobile row deliberately guards <Latency> with latency && ... to sidestep the CircleHelpIcon fallback.

What needs attention: 1 P2, 2 P3, 1 Nit, 2 Notes.

  • P2 The mobile trigger row loses the selected proxy's name from the accessible name. The removed <ExternalImage alt={selectedProxy.name}> was carrying that identity; the desktop trigger keeps the equivalent via an sr-only span, but the mobile row was left without one.
  • P3 In the unknown-latency state, <Latency className="text-content-primary"> erases the muted color that CircleHelpIcon uses to signal "no data", so the fallback icon renders bright next to a muted RadioIcon. Reachable when the selected proxy has no latency entry (unhealthy, pending, etc.).
  • P3 The new loading-branch ternary (proxyLatencyLoading ? undefined : latencyMS) has no story: Chromatic sees good, warning, and critical, never the loading gray. Break the ternary and no visual test catches it.

One quote worth keeping, from Pariston on the mismatched icons: "the class override strips the color from the icon that's supposed to carry it (CircleHelpIcon is the icon here, and its 'muted' is the unknown signal), and leaves the sibling RadioIcon muted alongside a bright question mark."

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/modules/dashboard/Navbar/MobileMenu.tsx
Comment thread site/src/modules/dashboard/Navbar/ProxyMenu.tsx
Comment thread site/src/modules/dashboard/Navbar/ProxyMenu.stories.tsx
Comment thread site/src/modules/dashboard/Navbar/ProxyMenu.tsx
Comment thread site/src/modules/dashboard/Navbar/ProxyMenu.tsx
Comment thread site/src/modules/dashboard/Navbar/ProxyMenu.stories.tsx
…tency icon states

- Restore proxy name in the mobile proxy row's accessible name via an
  sr-only span, matching the desktop trigger.
- Apply the text-content-primary override only when a latency value is
  shown, so the unknown-latency CircleHelpIcon keeps its muted color.
- Add a ClosedNoLatency story covering the unknown icon color state.

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

1 similar comment

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R1 findings addressed. All three fixes verified against c1a5ea3413:

  • CRF-1 Mobile sr-only span is placed above the aria-hidden RadioIcon; screen readers now name the selected proxy on the mobile trigger row.
  • CRF-2 text-content-primary override is guarded by latencies?.[selectedProxy.id]?.latencyMS, so the CircleHelpIcon fallback keeps its muted text-content-secondary alongside the muted RadioIcon.
  • CRF-3 ClosedNoLatency story exercises getLatencyColor(undefined) on the selected proxy by filtering its entry out of MockProxyLatencies.

CRF-4, CRF-5, CRF-6 acknowledged as author-scoped; author responses match each finding's own hedges.

Two new P3 findings, both mobile-only asymmetries opened by (or missed by) the R1 fixes:

  • P3 [CRF-7] Mobile's new sr-only "Latency for {name}" promises latency information that the pre-existing {latency && <Latency ...>} guard withholds when the selected proxy has no latency entry. Desktop's <Latency> renders CircleHelpIcon with aria-label="Latency not available" in the same state; mobile falls silent.
  • P3 [CRF-8] Mobile trigger uses the same getLatencyColor(latency?.latencyMS) pattern as desktop but no MobileMenu.stories.tsx story exercises warning, critical, or no-latency bands. MockProxyLatencies caps at 250 ms and puts the primary proxy in the good band, so mobile ships with only the good-band render covered.

One quote worth keeping, from Razor on the a11y regression: "This is a fresh gap opened by the R2 fix for CRF-1: the new sr-only span promises latency information without changing the sibling conditional that decides whether the status ever gets rendered."

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/modules/dashboard/Navbar/MobileMenu.tsx Outdated
Comment thread site/src/modules/dashboard/Navbar/MobileMenu.tsx
…and cover mobile icon states

- Render Latency unconditionally in the mobile proxy row so screen
  readers hear "Latency not available" instead of silence, matching
  the desktop trigger.
- Add warning, critical, and no-latency MobileMenu stories mirroring
  the desktop trigger coverage.

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocked. Head SHA is unchanged since round 2 (c1a5ea341302), and both open P3 findings from that round have no author response, no linked ticket, and no code change.

Unaddressed:

  • P3 [CRF-7] MobileMenu.tsx:144 - sr-only "Latency for {name}" (added by the CRF-1 fix) is followed by silence when the selected proxy has no latency entry; desktop announces "Latency not available." via <Latency>'s CircleHelpIcon fallback. Reachable during initial load and for any selected proxy without a latency entry.
  • P3 [CRF-8] MobileMenu.tsx:140 - mobile trigger renders the same latency-colored RadioIcon as desktop but no MobileMenu.stories.tsx story exercises the warning, critical, or no-latency bands. Asymmetric with the R1 CRF-3 fix on desktop.

Further review is blocked until the author responds on each thread or pushes fixes. A response can be a fix in this PR, a linked follow-up issue, or a technical rationale for why the finding should not be fixed. A bare "won't fix" is not a resolution.

Separately, CI is failing on this head (test-e2e, required); worth investigating independently of the review findings.

🤖 This review was automatically generated with Coder Agents.

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R2 findings addressed. Both fixes verified against 4c229e9efaff:

  • CRF-7 Mobile now renders <Latency> unconditionally, so Latency's built-in CircleHelpIcon fallback (with aria-label="Latency not available") closes the sr-only sentence in the no-latency state. Screen readers hear "Latency for {name}. Latency not available." mirroring desktop.
  • CRF-8 MobileMenu.stories.tsx gains ProxyWarningLatency (224 ms), ProxyCriticalLatency (471 ms), and ProxyNoLatency on MockPrimaryWorkspaceProxy.id. Coverage now matches the desktop trio. defaultProxyContextValue was hoisted out of meta.args cleanly so the new stories can spread it.

One new Nit [CRF-9] noticed while verifying CRF-2's pattern across the two triggers: mobile's className gate tests the report object (latency ? ... : undefined), desktop's tests the number (latencies?.[selectedProxy.id]?.latencyMS ? ...). Divergent predicate for the same class-of-bug fix. Not observable today because ProxyLatencyReport.latencyMS: number never comes back as 0 in practice, but the safety argument travels with the desktop shape.

One quote worth keeping, from Pariston verifying the fix depth: "The chain reads symptom (silent screen reader) → visible cause (guard-only rendering of <Latency>) → actual cause (mobile did not adopt the 'always render <Latency>' shape that desktop had). The fix is at the actual cause."

🤖 This review was automatically generated with Coder Agents.

Comment thread site/src/modules/dashboard/Navbar/MobileMenu.tsx Outdated

Copy link
Copy Markdown
Contributor Author

/coder-agents-review

@coder-agents-review coder-agents-review Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R4 finding addressed. CRF-9 verified against 0ceeed37fa.

All findings across 5 rounds are now either author-fixed or author-accepted with reasoning:

  • CRF-1, CRF-2, CRF-3, CRF-7, CRF-8, CRF-9: author-fixed and verified.
  • CRF-4, CRF-5, CRF-6: author-accepted with proportional reasoning.

One verification detail worth noting: while confirming CRF-9, Netero traced ProxyLatencyReport.latencyMS: number and observed the value is initialized to 0 and populated from responseStart - requestStart or entry.duration in useProxyLatency.ts:163-183, so latencyMS === 0 is actually reachable in practice. CRF-9's original framing hedged it as "not observable today"; the fix turns out to have been more consequential than the Nit severity suggested. Filing this as an observation, not a re-classification: the code is right, the pattern is now consistent across triggers, and the class-of-bug fix is complete.

One quote worth keeping, from Hisoka on the fix depth: "The predicate also aligns with the Latency component's own !latency gate that swaps in CircleHelpIcon. Same falsy shape at both layers: when Latency would render the help icon, the caller no longer paints it text-content-primary. That is the whole beauty of the fix."

Approving.

🤖 This review was automatically generated with Coder Agents.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant