️(frontend) improve background effect announcements

ensure sr announces clear and virtual background state
This commit is contained in:
Cyril
2026-01-16 11:51:49 +01:00
committed by aleb_the_flash
parent 78ab3cdbdf
commit 144a4e1b85
2 changed files with 48 additions and 30 deletions

View File

@@ -14,6 +14,7 @@ and this project adheres to
- ♿️(frontend) improve participants toggle a11y label #880 - ♿️(frontend) improve participants toggle a11y label #880
- ♿️(frontend) make carousel image decorative #871 - ♿️(frontend) make carousel image decorative #871
- ♿️(frontend) reactions are now vocalized and configurable #849 - ♿️(frontend) reactions are now vocalized and configurable #849
- ♿️(frontend) improve background effect announcements #879
### Fixed ### Fixed

View File

@@ -56,11 +56,11 @@ export const EffectsConfiguration = ({
const [processorPending, setProcessorPending] = useState(false) const [processorPending, setProcessorPending] = useState(false)
const processorPendingReveal = useSyncAfterDelay(processorPending) const processorPendingReveal = useSyncAfterDelay(processorPending)
const hasFunnyEffectsAccess = useHasFunnyEffectsAccess() const hasFunnyEffectsAccess = useHasFunnyEffectsAccess()
const [blurStatusMessage, setBlurStatusMessage] = useState('') const [effectStatusMessage, setEffectStatusMessage] = useState('')
const blurAnnouncementTimeout = useRef<ReturnType<typeof setTimeout> | null>( const effectAnnouncementTimeout = useRef<ReturnType<
null typeof setTimeout
) > | null>(null)
const blurAnnouncementId = useRef(0) const effectAnnouncementId = useRef(0)
useEffect(() => { useEffect(() => {
const videoElement = videoRef.current const videoElement = videoRef.current
@@ -89,27 +89,27 @@ export const EffectsConfiguration = ({
useEffect( useEffect(
() => () => { () => () => {
if (blurAnnouncementTimeout.current) { if (effectAnnouncementTimeout.current) {
clearTimeout(blurAnnouncementTimeout.current) clearTimeout(effectAnnouncementTimeout.current)
} }
}, },
[] []
) )
const announceBlurStatusMessage = (message: string) => { const announceEffectStatusMessage = (message: string) => {
blurAnnouncementId.current += 1 effectAnnouncementId.current += 1
const currentId = blurAnnouncementId.current const currentId = effectAnnouncementId.current
if (blurAnnouncementTimeout.current) { if (effectAnnouncementTimeout.current) {
clearTimeout(blurAnnouncementTimeout.current) clearTimeout(effectAnnouncementTimeout.current)
} }
// Clear the region first so screen readers drop queued announcements. // Clear the region first so screen readers drop queued announcements.
setBlurStatusMessage('') setEffectStatusMessage('')
blurAnnouncementTimeout.current = setTimeout(() => { effectAnnouncementTimeout.current = setTimeout(() => {
if (currentId !== blurAnnouncementId.current) return if (currentId !== effectAnnouncementId.current) return
setBlurStatusMessage(message) setEffectStatusMessage(message)
}, 80) }, 80)
} }
@@ -118,25 +118,42 @@ export const EffectsConfiguration = ({
onSubmit?.(undefined) onSubmit?.(undefined)
} }
const updateBlurStatusMessage = ( const getVirtualBackgroundName = (imagePath?: string) => {
if (!imagePath) return ''
const match = imagePath.match(/\/backgrounds\/(\d+)\.jpg$/)
if (!match) return ''
const index = Number(match[1]) - 1
if (Number.isNaN(index)) return ''
return t(`virtual.descriptions.${index}`)
}
const updateEffectStatusMessage = (
type: ProcessorType, type: ProcessorType,
options: BackgroundOptions, options: BackgroundOptions,
wasSelectedBeforeToggle: boolean wasSelectedBeforeToggle: boolean
) => { ) => {
if (type !== ProcessorType.BLUR) return
let message = ''
if (wasSelectedBeforeToggle) { if (wasSelectedBeforeToggle) {
message = t('blur.status.none') announceEffectStatusMessage(t('blur.status.none'))
} else if (options.blurRadius === BlurRadius.LIGHT) { return
message = t('blur.status.light')
} else if (options.blurRadius === BlurRadius.NORMAL) {
message = t('blur.status.strong')
} }
if (message) { if (type === ProcessorType.BLUR) {
announceBlurStatusMessage(message) const message =
options.blurRadius === BlurRadius.LIGHT
? t('blur.status.light')
: t('blur.status.strong')
announceEffectStatusMessage(message)
return
}
if (type === ProcessorType.VIRTUAL) {
const backgroundName = getVirtualBackgroundName(options.imagePath)
if (backgroundName) {
announceEffectStatusMessage(
`${t('virtual.selectedLabel')} ${backgroundName}`
)
return
}
} }
} }
@@ -200,7 +217,7 @@ export const EffectsConfiguration = ({
onSubmit?.(processor) onSubmit?.(processor)
} }
updateBlurStatusMessage(type, options, wasSelectedBeforeToggle) updateEffectStatusMessage(type, options, wasSelectedBeforeToggle)
} catch (error) { } catch (error) {
console.error('Error applying effect:', error) console.error('Error applying effect:', error)
} finally { } finally {
@@ -407,7 +424,7 @@ export const EffectsConfiguration = ({
</ToggleButton> </ToggleButton>
</div> </div>
<div aria-live="polite" className="sr-only"> <div aria-live="polite" className="sr-only">
{blurStatusMessage} {effectStatusMessage}
</div> </div>
</div> </div>
<div <div