From eec54ee5a8e803943b04f9a8a963000e4b34a1ef Mon Sep 17 00:00:00 2001 From: CyberSparkx Date: Wed, 9 Sep 2026 11:58:50 +0530 Subject: [PATCH 1/2] fix(hud): label recording controls for assistive technology Adds accessible aria-labels to recording state controls (pause, restart, stop/cancel) and window control buttons in the HUD overlay. Fixes #627. --- src/components/launch/HudControls.tsx | 45 ++++++++++++++++++--- src/components/launch/LaunchWindow.test.tsx | 18 +++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/src/components/launch/HudControls.tsx b/src/components/launch/HudControls.tsx index 360499c79..a78925ffb 100644 --- a/src/components/launch/HudControls.tsx +++ b/src/components/launch/HudControls.tsx @@ -160,6 +160,7 @@ export const HudSystemAudioButton = memo(function HudSystemAudioButton({ )} - - @@ -493,10 +516,22 @@ export const HudWindowControls = memo(function HudWindowControls({ }) { return (
- -
diff --git a/src/components/launch/LaunchWindow.test.tsx b/src/components/launch/LaunchWindow.test.tsx index 73cc4ea5a..f59ffc054 100644 --- a/src/components/launch/LaunchWindow.test.tsx +++ b/src/components/launch/LaunchWindow.test.tsx @@ -377,6 +377,24 @@ describe("LaunchWindow record button", () => { expect(recorderState.value.toggleRecording).not.toHaveBeenCalled(); }); + it("provides accessible aria-labels on HUD icon controls", async () => { + renderLaunchWindow(); + + const recordButton = await screen.findByTestId("launch-record-button"); + const systemAudioButton = screen.getByTestId("launch-system-audio-button"); + const micButton = screen.getByTestId("launch-microphone-button"); + const webcamButton = screen.getByTestId("launch-webcam-button"); + const cursorButton = screen.getByTestId("launch-cursor-mode-button"); + const studioButton = screen.getByTestId("launch-open-studio-button"); + + expect(recordButton).toHaveAttribute("aria-label"); + expect(systemAudioButton).toHaveAttribute("aria-label"); + expect(micButton).toHaveAttribute("aria-label"); + expect(webcamButton).toHaveAttribute("aria-label"); + expect(cursorButton).toHaveAttribute("aria-label"); + expect(studioButton).toHaveAttribute("aria-label"); + }); + it("clears record-after-selection intent when the source picker closes without a selection", async () => { renderLaunchWindow(); await waitForSourceSelectionSubscription(); From bfaee103657d5a0dc59a4b0acc3e2a7b61c4b56b Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Tue, 15 Sep 2026 09:19:06 +0200 Subject: [PATCH 2/2] test(hud): pin the exact accessible name of every HUD control The previous assertions only checked that aria-label existed, so an empty or wrong label passed, and the pause, restart, cancel, hide and close controls the fix labels were never rendered. --- src/components/launch/LaunchWindow.test.tsx | 58 ++++++++++++++++----- 1 file changed, 44 insertions(+), 14 deletions(-) diff --git a/src/components/launch/LaunchWindow.test.tsx b/src/components/launch/LaunchWindow.test.tsx index f59ffc054..201cbfd8d 100644 --- a/src/components/launch/LaunchWindow.test.tsx +++ b/src/components/launch/LaunchWindow.test.tsx @@ -296,6 +296,7 @@ function resetLaunchMocks() { recorderState.value.softwareEncoderFallbackNoticeVisible = false; recorderState.value.dismissSoftwareEncoderFallbackNotice.mockClear(); recorderState.value.recording = false; + recorderState.value.canPauseRecording = false; recorderState.value.microphoneEnabled = false; recorderState.value.setMicrophoneEnabled.mockClear(); recorderState.value.setMicrophoneDeviceId.mockClear(); @@ -377,22 +378,51 @@ describe("LaunchWindow record button", () => { expect(recorderState.value.toggleRecording).not.toHaveBeenCalled(); }); - it("provides accessible aria-labels on HUD icon controls", async () => { + it("names the idle HUD icon controls for assistive technology", async () => { renderLaunchWindow(); + await screen.findByTestId("launch-record-button"); - const recordButton = await screen.findByTestId("launch-record-button"); - const systemAudioButton = screen.getByTestId("launch-system-audio-button"); - const micButton = screen.getByTestId("launch-microphone-button"); - const webcamButton = screen.getByTestId("launch-webcam-button"); - const cursorButton = screen.getByTestId("launch-cursor-mode-button"); - const studioButton = screen.getByTestId("launch-open-studio-button"); - - expect(recordButton).toHaveAttribute("aria-label"); - expect(systemAudioButton).toHaveAttribute("aria-label"); - expect(micButton).toHaveAttribute("aria-label"); - expect(webcamButton).toHaveAttribute("aria-label"); - expect(cursorButton).toHaveAttribute("aria-label"); - expect(studioButton).toHaveAttribute("aria-label"); + expect(screen.getByTestId("launch-system-audio-button")).toHaveAttribute( + "aria-label", + "Enable system audio", + ); + expect(screen.getByTestId("launch-microphone-button")).toHaveAttribute( + "aria-label", + "Enable microphone", + ); + expect(screen.getByTestId("launch-webcam-button")).toHaveAttribute( + "aria-label", + "Enable webcam", + ); + expect(screen.getByTestId("launch-cursor-mode-button")).toHaveAttribute( + "aria-label", + "Use system cursor", + ); + expect(screen.getByTestId("launch-open-studio-button")).toHaveAttribute( + "aria-label", + "Open Studio", + ); + expect(screen.getByTitle("Hide HUD")).toHaveAttribute("aria-label", "Hide HUD"); + expect(screen.getByTitle("Close App")).toHaveAttribute("aria-label", "Close App"); + }); + + it("names the recording-state HUD controls for assistive technology", async () => { + recorderState.value.recording = true; + recorderState.value.canPauseRecording = true; + renderLaunchWindow(); + + expect(await screen.findByTestId("launch-pause-button")).toHaveAttribute( + "aria-label", + "tooltips.pauseRecording", + ); + expect(screen.getByTestId("launch-restart-button")).toHaveAttribute( + "aria-label", + "tooltips.restartRecording", + ); + expect(screen.getByTestId("launch-cancel-button")).toHaveAttribute( + "aria-label", + "tooltips.cancelRecording", + ); }); it("clears record-after-selection intent when the source picker closes without a selection", async () => {