diff --git a/.jules/palette.md b/.jules/palette.md index c0563889..771a35d4 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -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. +## 2026-08-08 - Adding Tooltips to Icon-Only Buttons +**Learning:** Icon-only buttons lacking `title` attributes may not provide sufficient visual cues on hover, making navigation less intuitive for mouse users. Relying purely on `aria-label` ensures screen reader accessibility but omits visual feedback. +**Action:** When adding `aria-label` to icon-only buttons, always accompany it with a matching `title` attribute to show native browser tooltips on hover. diff --git a/apps/desktop/package.json b/apps/desktop/package.json index e7685d6f..647047e3 100644 --- a/apps/desktop/package.json +++ b/apps/desktop/package.json @@ -20,7 +20,7 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "lucide-react": "^1.24.0", - "pdfjs-dist": "6.1.200", + "pdfjs-dist": "^6.2.108", "react": "^19.2.4", "react-dom": "^19.2.7", "sonner": "^2.0.7", diff --git a/apps/desktop/src/features/score/ScoreView.test.tsx b/apps/desktop/src/features/score/ScoreView.test.tsx index de4ccb95..c8bd72f9 100644 --- a/apps/desktop/src/features/score/ScoreView.test.tsx +++ b/apps/desktop/src/features/score/ScoreView.test.tsx @@ -98,6 +98,7 @@ describe("ScoreView", () => { expect(screen.getByRole("button", { name: "Add score" })).toBeDisabled(); expect(screen.getByRole("button", { name: "Open score: opener.pdf" })).toBeDisabled(); expect(screen.getByRole("button", { name: "Remove: opener.pdf" })).toBeDisabled(); + expect(screen.getByRole("button", { name: "Remove: opener.pdf" })).toHaveAttribute("title", "Remove: opener.pdf"); fireEvent.click(screen.getByRole("button", { name: "Open score: opener.pdf" })); expect(mockInvoke).not.toHaveBeenCalled(); diff --git a/apps/desktop/src/features/score/ScoreView.tsx b/apps/desktop/src/features/score/ScoreView.tsx index 72732450..53cab32f 100644 --- a/apps/desktop/src/features/score/ScoreView.tsx +++ b/apps/desktop/src/features/score/ScoreView.tsx @@ -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}`} className="size-10 border-rose-300/25 text-rose-200 hover:bg-rose-400/10" >