Navbar declares `const roles` twice in the same scope — the component cannot compile, and the Dashboards trigger renders its label, chevron and role badge twice

Aperta Adatta ai principianti
#832 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
85/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
next.js, typescript

Direzione di ricerca

Inizia da src/components/layout/Navbar.tsx, in particolare dal componente Navbar, dalle dichiarazioni duplicate dei ruoli e dal trigger Dashboards individuati nell’issue. Mantieni l’elenco dei ruoli convalidato e riconcilia l’etichetta, il badge, il chevron e l’helper per le etichette dei ruoli duplicati come descritto. Esegui npx tsc --noEmit e i test di Navbar; il lavoro è completato quando il componente viene compilato e il trigger mostra e annuncia una sola volta la propria etichetta e il conteggio dei ruoli.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

accessibility bug

Location

src/components/layout/Navbar.tsx — the Navbar component.

  • :61 — const roles = Array.from(new Set(user?.roles ?? [])).filter(...)
  • :90 — const roles = user?.roles ?? [];
  • :118 / :129 — the literal string Dashboards and {messages["nav.dashboards"]}
  • :120-127 / :130-134 — two different multi-role count badges
  • :128 / :135 — two <ChevronDown /> elements
  • :45-49 — roleLabels, a second copy of roleLabel (:34-38)

Problem

Two unrelated versions of the multi-role work were merged into this file without reconciling them, and both survived.

1. Duplicate const roles — hard compile error
// line 61
const roles = Array.from(new Set(user?.roles ?? [])).filter(
  (role): role is UserRole => role in dashboardRoute,
);
const orderedRoles = roleOrder.filter((role) => roles.includes(role));
...
// line 90
const roles = user?.roles ?? [];
const multiRole = roles.length > 1;

Both const roles declarations live in the same function body. This is TS2451: Cannot redeclare block-scoped variable 'roles', and at runtime it is a SyntaxError — let/const redeclaration in one scope is not merely a lint warning. next build and tsc --noEmit both fail, and Navbar.test.tsx cannot even load the module.

Note that the two declarations are not equivalent: the one on line 61 deliberately de-duplicates and validates the backend-supplied roles array (unknown roles dropped), while the one on line 90 trusts it raw. Whichever is kept, the validated version is the one the surrounding code was written for.

2. The Dashboards trigger renders everything twice

Inside the single <button>, lines 118-135 render, in order: the literal text Dashboards, the line-120 count badge, a ChevronDown (no aria-hidden), {messages["nav.dashboards"]}, the line-130 count badge, and a second ChevronDown (with aria-hidden). Once the compile error is resolved, the trigger reads as "Dashboards 2 Dashboards 2" to both sighted and screen-reader users, and shows two chevrons.

The first ChevronDown (:128) also has no aria-hidden="true", which is the exact defect closed issue #434 fixed; the second one (:135) carries it. The surviving duplicate reintroduces #434.

3. roleLabels duplicates roleLabel

roleLabel (:34) is built from messages[...] and is Record<UserRole, string>; roleLabels (:45) is a hardcoded English Record<string, string> used only by the line-120 badge's title. The hardcoded one reintroduces the hardcoded-strings problem tracked by #51 and its regressions (#670-#673).

Why it matters

The Navbar is rendered by the root layout, so it is on every page. As the file stands, the app does not build at all: every route is unreachable, not just the navigation. After the build is fixed naively (deleting either const roles), the primary navigation still announces its own name twice and shows two chevrons and two role badges, so the "N roles" affordance that #589 added is doubled rather than restored.

Reproduction

  1. Check out the current default branch and run npm ci.
  2. Run npx tsc --noEmit. It reports TS2451: Cannot redeclare block-scoped variable 'roles' at src/components/layout/Navbar.tsx:90.
  3. Run npm run build. The build fails on the same file.
  4. Run npm test -- Navbar. The suite fails to load the module.
  5. Delete line 90-91 only, then sign in as a user with two roles and look at the header: the trigger reads Dashboards 2 Dashboards 2 with two chevrons. With VoiceOver or NVDA, the button's accessible name is announced with "Dashboards" twice.

Suggested fix

  1. Keep the validated roles on line 61 (and orderedRoles); delete the line 90-91 block and derive multiRole from orderedRoles.length > 1.
  2. Keep exactly one count badge — the line 130-134 one, which already uses orderedRoles — and delete the line 120-127 badge. Move its You have N roles: ... explanation onto the surviving badge (as title plus an sr-only span, since title alone is not reliably announced), built from roleLabel, not roleLabels.
  3. Keep one ChevronDown, the :135 one with aria-hidden="true" and rtl:rotate-180.
  4. Render the trigger label once, from messages["nav.dashboards"]; remove the hardcoded Dashboards literal.
  5. Delete the roleLabels constant.
  6. Add tsc --noEmit (or npm run build) as a required CI check so a redeclaration like this cannot merge again — this is the third merge-mangled component on this branch.
Lingua principale
TypeScript
Stelle
1
Fork
94
Merge medio
1h 2m
PR unite (30g)
25

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di MergeFi/frontend

Tutte le issue di MergeFi/frontend

Issue simili

Altre issue su TypeScript

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.