Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .jules/palette.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2024-05-19 - Replace HTML disabled with aria-disabled="true" for Accessible Tooltips
**Learning:** Native HTML `disabled` attributes completely hide elements from screen readers and block all pointer/hover events, preventing tooltips from functioning for disabled elements.
**Action:** Replace `disabled` with `aria-disabled="true"`, enforce block click handlers via `e.preventDefault()`, and add a title tooltip directly to the element to maintain full tooltip accessibility and keyboard focus support for visually impaired and mouse users.
## 2025-02-27 - Icon-only button tooltips
**Learning:** Icon-only buttons (like lucide-react icons inside a `<Button>`) need a `title` attribute matching their `aria-label` to display native browser hover tooltips for mouse users, improving accessibility and discoverability.
**Action:** When adding or modifying icon-only buttons, always ensure both `aria-label` (for screen readers) and `title` (for mouse hover) are present and match.
1 change: 1 addition & 0 deletions apps/desktop/src/features/score/ScoreView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ export function ScoreView({ song, projectId, onSongUpdate }: ScoreViewProps) {
onClick={projectId ? () => void handleRemove(projectId, attachment) : undefined}
disabled={!projectId}
aria-label={`${t("scoreRemove")}: ${attachment.fileName}`}
title={`${t("scoreRemove")}: ${attachment.fileName}`}

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.

๐ŸŽฏ Functional Correctness | ๐ŸŸก Minor | โšก Quick win

๋„ค์ดํ‹ฐ๋ธŒ disabled ์ปจํŠธ๋กค์—์„œ๋Š” ์ถ”๊ฐ€ํ•œ ํˆดํŒ์ด ๋™์ž‘ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ ์œ„์น˜๋“ค์€ title์„ ์ถ”๊ฐ€ํ–ˆ์ง€๋งŒ ์ธ์ ‘ํ•œ disabled ์กฐ๊ฑด์ด ํ˜ธ๋ฒ„ ์ด๋ฒคํŠธ๋ฅผ ์ฐจ๋‹จํ•ฉ๋‹ˆ๋‹ค. ์•„์ด์ฝ˜ ๋ฒ„ํŠผ์˜ ํˆดํŒ๊ณผ ํ‚ค๋ณด๋“œ ์ ‘๊ทผ์„ฑ์„ ๋ณด์žฅํ•˜๋ ค๋ฉด aria-disabled๋กœ ์ „ํ™˜ํ•˜๊ณ  ๋น„ํ™œ์„ฑ ํด๋ฆญ์„ ํ•ธ๋“ค๋Ÿฌ์—์„œ ์ฐจ๋‹จํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

  • apps/desktop/src/features/score/ScoreView.tsx#L201-L201: ํ”„๋กœ์ ํŠธ๊ฐ€ ์—†์„ ๋•Œ ํœด์ง€ํ†ต ๋ฒ„ํŠผ์— aria-disabled๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • apps/desktop/src/features/score/ScoreViewer.tsx#L297-L297: ์ฒซ ํŽ˜์ด์ง€์˜ ์ด์ „ ๋ฒ„ํŠผ์— aria-disabled๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
  • apps/desktop/src/features/score/ScoreViewer.tsx#L311-L311: ๋งˆ์ง€๋ง‰ ํŽ˜์ด์ง€์˜ ๋‹ค์Œ ๋ฒ„ํŠผ์— aria-disabled๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
๐Ÿ“ Affects 2 files
  • apps/desktop/src/features/score/ScoreView.tsx#L201-L201 (this comment)
  • apps/desktop/src/features/score/ScoreViewer.tsx#L297-L297
  • apps/desktop/src/features/score/ScoreViewer.tsx#L311-L311
๐Ÿค– Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/desktop/src/features/score/ScoreView.tsx` at line 201, Replace native
disabled handling with aria-disabled for the trash button in
apps/desktop/src/features/score/ScoreView.tsx at lines 201-201, and for the
previous and next pagination buttons in
apps/desktop/src/features/score/ScoreViewer.tsx at lines 297-297 and 311-311.
Update each click handler to block activation when its disabled condition
applies, preserving tooltip display and keyboard accessibility.

Source: Coding guidelines

className="size-10 border-rose-300/25 text-rose-200 hover:bg-rose-400/10"
Comment on lines 198 to 202
>
<Trash2 className="size-4" aria-hidden="true" />
Expand Down
4 changes: 4 additions & 0 deletions apps/desktop/src/features/score/ScoreViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ export function ScoreViewer({ data, fileName, onStatusChange }: ScoreViewerProps
size="icon-lg"
className="size-12"
aria-label={t("scoreViewerZoomOut")}
title={t("scoreViewerZoomOut")}
onClick={zoomOut}
>
<ZoomOut aria-hidden="true" />
Expand All @@ -267,6 +268,7 @@ export function ScoreViewer({ data, fileName, onStatusChange }: ScoreViewerProps
size="icon-lg"
className="size-12"
aria-label={t("scoreViewerZoomIn")}
title={t("scoreViewerZoomIn")}
onClick={zoomIn}
>
<ZoomIn aria-hidden="true" />
Expand All @@ -292,6 +294,7 @@ export function ScoreViewer({ data, fileName, onStatusChange }: ScoreViewerProps
size="icon-lg"
className="size-14"
aria-label={t("scoreViewerPrevPage")}
title={t("scoreViewerPrevPage")}
disabled={pageNumber <= 1}
onClick={goToPreviousPage}
>
Comment on lines 296 to 300
Expand All @@ -305,6 +308,7 @@ export function ScoreViewer({ data, fileName, onStatusChange }: ScoreViewerProps
size="icon-lg"
className="size-14"
aria-label={t("scoreViewerNextPage")}
title={t("scoreViewerNextPage")}
disabled={pageNumber >= pageCount}
onClick={goToNextPage}
>
Expand Down
Loading