From c0a9b2da6b6112006a0e2c328f9f5889f42bdc81 Mon Sep 17 00:00:00 2001 From: Lotus CI Date: Thu, 24 Sep 2026 11:59:45 -0400 Subject: [PATCH] fix(a11y): call toggles no longer contradict their labels (#187 DP7/8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The call-bar and status-bar toggles change their label with the state ("Deafen"/"Undeafen", "Turn off/on microphone", "Start/Stop Video", …) AND set aria-pressed, which made screen readers say "Deafen, pressed" while you were not deafened, and gave mic/screenshare a pressed state in one bar but not the other. Per the ARIA practice, a toggle uses either a changing action label or aria-pressed with a fixed label; these use the former, so aria-pressed is removed from all nine. Checked in a live call: every control now announces only its action, in both states (deafen → "Undeafen", mic → "Turn on microphone", …). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA --- src/app/features/call-status/CallControl.tsx | 7 +++---- src/app/features/call/Controls.tsx | 8 +++----- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/app/features/call-status/CallControl.tsx b/src/app/features/call-status/CallControl.tsx index c1667a6ac..c37dd3a33 100644 --- a/src/app/features/call-status/CallControl.tsx +++ b/src/app/features/call-status/CallControl.tsx @@ -40,7 +40,6 @@ function MicrophoneButton({ enabled, onToggle, disabled }: MicrophoneButtonProps outlined disabled={disabled || loading} aria-label={enabled ? 'Turn off microphone' : 'Turn on microphone'} - aria-pressed={enabled} > @@ -73,8 +72,10 @@ function SoundButton({ enabled, onToggle, disabled }: SoundButtonProps) { size="300" className={MobileTouchTarget} onClick={() => onToggle()} + // No aria-pressed on these call toggles (#187 DP7/8): their labels already + // name the action ("Deafen" / "Undeafen"), and pressed-state on top + // read as "Deafen, pressed" while NOT deafened. aria-label={enabled ? 'Deafen' : 'Undeafen'} - aria-pressed={enabled} outlined disabled={disabled} > @@ -117,7 +118,6 @@ function VideoButton({ enabled, onToggle, disabled }: VideoButtonProps) { className={MobileTouchTarget} onClick={toggleVideo} aria-label={enabled ? 'Stop Video' : 'Start Video'} - aria-pressed={enabled} outlined disabled={disabled || loading} > @@ -157,7 +157,6 @@ function ScreenShareButton({ enabled, onToggle, disabled }: ScreenShareButtonPro className={MobileTouchTarget} onClick={onToggle} aria-label={enabled ? 'Stop Screenshare' : 'Start Screenshare'} - aria-pressed={enabled} outlined disabled={disabled} > diff --git a/src/app/features/call/Controls.tsx b/src/app/features/call/Controls.tsx index 698ae0ee2..bbe764ff7 100644 --- a/src/app/features/call/Controls.tsx +++ b/src/app/features/call/Controls.tsx @@ -74,8 +74,10 @@ export function SoundButton({ enabled, onToggle }: SoundButtonProps) { size="400" className={MobileTouchTarget} onClick={() => onToggle()} + // No aria-pressed on these call toggles (#187 DP7/8): their labels already + // name the action ("Deafen" / "Undeafen"), and pressed-state on top + // read as "Deafen, pressed" while NOT deafened. aria-label={enabled ? 'Deafen' : 'Undeafen'} - aria-pressed={enabled} outlined > {isFullscreen ? : } @@ -244,7 +244,6 @@ export function ScreenshareAudioButton({ muted, onToggle }: ScreenshareAudioButt className={MobileTouchTarget} onClick={onToggle} aria-label={muted ? 'Unmute Screenshare Audio' : 'Mute Screenshare Audio'} - aria-pressed={muted} outlined > @@ -277,7 +276,6 @@ export function ChatButton() { className={MobileTouchTarget} onClick={() => setChat(!chat)} aria-label={chat ? 'Close Chat' : 'Open Chat'} - aria-pressed={chat} outlined >