diff --git a/src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx b/src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx index 30dcefe5..4c34d7e9 100644 --- a/src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx +++ b/src/frontend/src/features/rooms/livekit/components/ReactionPortal.tsx @@ -15,18 +15,6 @@ export const FADE_OUT_THRESHOLD = 0.7 export const REACTION_SPAWN_WIDTH_RATIO = 0.2 export const INITIAL_POSITION = 200 -const srOnly = css({ - position: 'absolute', - width: '1px', - height: '1px', - padding: 0, - margin: '-1px', - overflow: 'hidden', - clip: 'rect(0, 0, 0, 0)', - whiteSpace: 'nowrap', - border: 0, -}) - interface FloatingReactionProps { emoji: string name?: string @@ -176,7 +164,8 @@ export const ReactionPortals = ({ reactions }: { reactions: Reaction[] }) => { const emojiLabel = getEmojiLabel(latestReaction.emoji, t) const participantName = latestReaction.participant?.isLocal ? t('you') - : (latestReaction.participant?.name ?? '') + : latestReaction.participant?.name?.trim() || + t('someone', { defaultValue: 'Someone' }) setAnnouncement(t('announce', { name: participantName, emoji: emojiLabel })) setLastAnnouncedId(latestReaction.id) @@ -197,7 +186,7 @@ export const ReactionPortals = ({ reactions }: { reactions: Reaction[] }) => { role="status" aria-live="polite" aria-atomic="true" - className={srOnly} + className="sr-only" > {announcement ?? ''} diff --git a/src/frontend/src/styles/a11y.ts b/src/frontend/src/styles/a11y.ts new file mode 100644 index 00000000..2c8b55a3 --- /dev/null +++ b/src/frontend/src/styles/a11y.ts @@ -0,0 +1,14 @@ +import { css } from '@/styled-system/css' + +// Reusable visually hidden style for screen-reader-only content +export const srOnly = css({ + position: 'absolute', + width: '1px', + height: '1px', + padding: 0, + margin: '-1px', + overflow: 'hidden', + clip: 'rect(0, 0, 0, 0)', + whiteSpace: 'nowrap', + border: 0, +})