fix(a11y): call toggles no longer contradict their labels (#187 DP7/8)
CI / Build & Quality Checks (push) Successful in 2m9s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 9s
CI / Trigger Desktop Build (push) Successful in 3s
CI / Playwright smoke (e2e) (push) Successful in 10m15s
CI / Build & Quality Checks (push) Successful in 2m9s
CI / Docker image build & smoke test (push) Skipped
CI / Secret scan (gitleaks) (push) Successful in 9s
CI / Trigger Desktop Build (push) Successful in 3s
CI / Playwright smoke (e2e) (push) Successful in 10m15s
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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ed87b700d9
commit
c0a9b2da6b
@@ -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}
|
||||
>
|
||||
<Icon size="100" src={enabled ? Icons.Mic : Icons.MicMute} filled={!enabled} />
|
||||
</IconButton>
|
||||
@@ -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}
|
||||
>
|
||||
|
||||
@@ -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
|
||||
>
|
||||
<Icon
|
||||
@@ -124,7 +126,6 @@ export function VideoButton({ enabled, onToggle, disabled }: VideoButtonProps) {
|
||||
aria-label={
|
||||
disabled ? 'Camera disabled in settings' : enabled ? 'Stop camera' : 'Start camera'
|
||||
}
|
||||
aria-pressed={enabled}
|
||||
style={disabled ? { opacity: 0.4, cursor: 'not-allowed' } : undefined}
|
||||
>
|
||||
<Icon
|
||||
@@ -209,7 +210,6 @@ export function FullscreenButton({ isFullscreen, onToggle }: FullscreenButtonPro
|
||||
className={MobileTouchTarget}
|
||||
onClick={onToggle}
|
||||
aria-label={isFullscreen ? 'Exit Fullscreen' : 'Fullscreen'}
|
||||
aria-pressed={isFullscreen}
|
||||
outlined
|
||||
>
|
||||
{isFullscreen ? <ExitFullscreenIcon /> : <FullscreenIcon />}
|
||||
@@ -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
|
||||
>
|
||||
<Icon size="400" src={muted ? Icons.VolumeMute : Icons.VolumeHigh} filled={muted} />
|
||||
@@ -277,7 +276,6 @@ export function ChatButton() {
|
||||
className={MobileTouchTarget}
|
||||
onClick={() => setChat(!chat)}
|
||||
aria-label={chat ? 'Close Chat' : 'Open Chat'}
|
||||
aria-pressed={chat}
|
||||
outlined
|
||||
>
|
||||
<Icon size="400" src={Icons.Message} filled={chat} />
|
||||
|
||||
Reference in New Issue
Block a user