diff --git a/.jules/palette.md b/.jules/palette.md index 801392f2..dd1e43c3 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -17,3 +17,7 @@ **Learning:** When placing interactive elements (like `Select` or `Button`) inside data tables, relying solely on column headers is insufficient for screen reader users navigating by control. A simple "Edit" or "Select" announcement lacks context. **Action:** Pass the row entity's name (e.g., user name) to the interactive component and use it in a dynamic `aria-label` (e.g., "Change role for John Doe"). + +## 2025-05-21 - [Dynamic Accessible Names for Select Triggers] +**Learning:** Shadcn UI `SelectTrigger` with a static `aria-label` overrides the screen reader announcement of the selected value. This leaves users knowing "Select Status" but not the *current* status. +**Action:** Use a dynamic `aria-label` that includes the current value (e.g., `aria-label={`Status: ${valueLabel}`}`) to provide full context. diff --git a/src/components/issues/fields/ConsistencySelect.tsx b/src/components/issues/fields/ConsistencySelect.tsx index ac2055f5..d66accd3 100644 --- a/src/components/issues/fields/ConsistencySelect.tsx +++ b/src/components/issues/fields/ConsistencySelect.tsx @@ -41,7 +41,7 @@ export function ConsistencySelect({ > diff --git a/src/components/issues/fields/PrioritySelect.tsx b/src/components/issues/fields/PrioritySelect.tsx index f7bc571a..9a406653 100644 --- a/src/components/issues/fields/PrioritySelect.tsx +++ b/src/components/issues/fields/PrioritySelect.tsx @@ -37,7 +37,7 @@ export function PrioritySelect({ > diff --git a/src/components/issues/fields/SelectFields.test.tsx b/src/components/issues/fields/SelectFields.test.tsx new file mode 100644 index 00000000..6d04af13 --- /dev/null +++ b/src/components/issues/fields/SelectFields.test.tsx @@ -0,0 +1,64 @@ +import { render, screen } from "@testing-library/react"; +import { describe, it, expect, vi } from "vitest"; +import { StatusSelect } from "./StatusSelect"; +import { SeveritySelect } from "./SeveritySelect"; +import { PrioritySelect } from "./PrioritySelect"; +import { ConsistencySelect } from "./ConsistencySelect"; + +describe("SelectFields Accessibility", () => { + describe("StatusSelect", () => { + it("has a dynamic accessible name including the value", () => { + render( + + ); + + const trigger = screen.getByTestId("issue-status-select"); + expect(trigger).toHaveAttribute("aria-label", "Status: In Progress"); + }); + }); + + describe("SeveritySelect", () => { + it("has a dynamic accessible name including the value", () => { + render( + + ); + + const trigger = screen.getByTestId("issue-severity-select"); + expect(trigger).toHaveAttribute("aria-label", "Severity: Major"); + }); + }); + + describe("PrioritySelect", () => { + it("has a dynamic accessible name including the value", () => { + render( + + ); + + const trigger = screen.getByTestId("issue-priority-select"); + expect(trigger).toHaveAttribute("aria-label", "Priority: High"); + }); + }); + + describe("ConsistencySelect", () => { + it("has a dynamic accessible name including the value", () => { + render( + + ); + + const trigger = screen.getByTestId("issue-consistency-select"); + expect(trigger).toHaveAttribute("aria-label", "Consistency: Frequent"); + }); + }); +}); diff --git a/src/components/issues/fields/SeveritySelect.tsx b/src/components/issues/fields/SeveritySelect.tsx index 3be22e36..6156a8f7 100644 --- a/src/components/issues/fields/SeveritySelect.tsx +++ b/src/components/issues/fields/SeveritySelect.tsx @@ -42,7 +42,7 @@ export function SeveritySelect({ > diff --git a/src/components/issues/fields/StatusSelect.tsx b/src/components/issues/fields/StatusSelect.tsx index 82d7cf9d..b9a08a5f 100644 --- a/src/components/issues/fields/StatusSelect.tsx +++ b/src/components/issues/fields/StatusSelect.tsx @@ -44,7 +44,7 @@ export function StatusSelect({ >