Duplicate JSX attributes in BountyCard and Avatar break the build and silently revert the #654 and #653 accessibility fixes
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
- 78/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- next.js, react, typescript
- Ambito
- accessibility, frontend, testing
Direzione di ricerca
Leggi src/components/bounty/BountyCard.tsx e src/components/ui/Avatar.tsx nelle posizioni indicate, quindi esamina BountyCard.test.tsx e Avatar.test.tsx per individuare le asserzioni esistenti. Esegui npx tsc --noEmit per confermare gli errori dovuti agli attributi duplicati. Il lavoro è completato quando i duplicati sono risolti preservando l’etichetta accessibile descritta, la sorgente sicura dell’avatar e il testo alternativo fornito, e quando entrambe le asserzioni di regressione passano.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Location
src/components/bounty/BountyCard.tsx:37-40—BountyCardsrc/components/ui/Avatar.tsx:57-61—Avatar
Problem
Both components carry the same attribute twice on one JSX element, left behind by an unreconciled merge. React keeps the last occurrence and discards the earlier one, so in each case the newer accessibility fix is the one that gets thrown away.
BountyCard
<Link
href={`/issues/${bounty.id}`}
prefetch={false}
aria-label={accessibleLabel} // line 37 (#654 fix)
className={`... before:left-0 ...`} // line 38
aria-label={`${bounty.title}, ${formatCurrency(bounty.reward, bounty.asset)}`} // line 39 (old)
className={`... before:start-0 ...`} // line 40
>
aria-label and className are each specified twice. The surviving aria-label is the old short one, so accessibleLabel — the full "title, from org/repo, issue N, reward X, status: funded, difficulty: advanced, due in 5 days, claimed by Y" string built at lines 20-31 for closed issue #654 — is computed on every render and then dropped. The card is back to announcing only its title and reward, which is precisely what #654 reported. The variable also becomes unused, so no-unused-vars style lint rules flag it.
The two className values differ in one class: before:left-0 versus the logical before:start-0. The logical property is the one that survives, which is the correct outcome, but it is surviving by accident.
Avatar
<Image
src={src ?? seedToUrl(seed)} // line 58 — bypasses isSafeAvatarUrl
alt={alt ?? seed} // line 59 — honours the `alt` prop
src={resolved} // line 60 — safety-checked + error fallback
alt={seed} // line 61 — ignores the `alt` prop
...
Here the survivors are src={resolved} (good — the host-allowlist and onError fallback logic is the one that applies) and alt={seed} (bad — the alt prop is accepted by the component's signature, documented at lines 40-41 as "Use empty string when the avatar is decorative (next to a visible name)", and then silently ignored).
Every call site that passes alt="" therefore still gets alt={seed}. That reintroduces closed issue #653: src/components/dashboard/ActivityList.tsx:42 renders <Avatar seed={event.handle} /> immediately before a visible {event.handle}, so a screen reader reads the handle twice per activity row.
Both files fail to compile
Duplicate JSX attributes are a TypeScript error, not a warning: TS17001: JSX elements cannot have multiple attributes with the same name. tsc --noEmit and next build both fail on these two files, and react/jsx-no-duplicate-props would have caught them too.
Why it matters
- The app does not build, so no route is reachable.
- Once it does build (by resolving these duplicates the wrong way, i.e. keeping what React keeps today), two closed accessibility issues are quietly back in place: bounty cards on
/issueslose their status/deadline/claimant context for screen-reader users (#654), and decorative avatars double-announce every name in the activity feed (#653). Both regressions are invisible in code review because the "fix" code is still sitting right there in the file.
Reproduction
- Check out the current default branch, run
npm ci, thennpx tsc --noEmit. FourTS17001errors are reported across the two files. - Delete lines 39-40 of
BountyCard.tsxand lines 58-59 ofAvatar.tsx— i.e. resolve each duplicate the way React resolves it at runtime — and build again. - Open
/issueswith VoiceOver or NVDA and move through the links list. Each bounty card announces only "<title>, 500 USDC"; status, difficulty, deadline and claimant are not announced. - Open any dashboard with the activity feed and move through it. Each row announces the contributor handle twice: once as the avatar's alt text, once as the adjacent visible text.
Suggested fix
BountyCard.tsx: delete the oldaria-labelon line 39 and thebefore:left-0classNameon line 38, keepingaria-label={accessibleLabel}(line 37) and thebefore:start-0className (line 40).Avatar.tsx: delete the rawsrc={src ?? seedToUrl(seed)}(line 58) andalt={seed}(line 61), keepingsrc={resolved}(line 60) andalt={alt ?? seed}(line 59).- Enable
react/jsx-no-duplicate-propsas an error ineslint.config.mjsand runtsc --noEmitin CI, so this class of merge damage is caught mechanically. Two other components on this branch have the same kind of unresolved merge. - Re-add a regression assertion to each test file:
BountyCard.test.tsxshould assert the link's accessible name contains the status and deadline, andAvatar.test.tsxshould assertalt=""is honoured when passed.
- Lingua principale
- TypeScript
- Stelle
- 1
- Fork
- 94
- Merge medio
- 1h 2m
- PR unite (30g)
- 25
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di MergeFi/frontend
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
I maintainer di solito rispondono entro 1 giorno
-
bug testing
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
-
accessibility bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 85/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di MergeFi/frontend
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
zapcooking/frontend#946 ·
I maintainer di solito rispondono entro 1 giorno
-
enhancement good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 88/100
WiliamRosa/cosmos-semantic-platform#40 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 77/100
liberation-data/drivine#733 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
makecindy/cindy#10062 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno