From db15c8b6cc17c5a22a266e3fa8d22ea0d89b75dd Mon Sep 17 00:00:00 2001 From: Cyril Date: Tue, 27 Jan 2026 10:14:32 +0100 Subject: [PATCH] =?UTF-8?q?=E2=99=BF=EF=B8=8F(frontend)=20adjust=20visual-?= =?UTF-8?q?only=20tooltip=20a11y=20labels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure tooltips stay visual while exposing correct aria-labels. --- CHANGELOG.md | 9 +-- src/frontend/src/layout/Header.tsx | 39 ++++++----- src/frontend/src/locales/en/global.json | 2 +- src/frontend/src/locales/fr/global.json | 2 +- src/frontend/src/locales/nl/global.json | 2 +- .../src/primitives/VisualOnlyTooltip.tsx | 69 ++++++++++++++----- 6 files changed, 83 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ad5ac5f..bd853728 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,14 +8,15 @@ and this project adheres to ## [Unreleased] +### Changed + +- ♿️(frontend) adjust visual-only tooltip a11y labels #910 +- ♿(frontend) adjust sr announcements for idle disconnect timer #908 + ### Fixed - 🔒️(frontend) fix an XSS vulnerability on the recording page #911 -### Changed - -- ♿(frontend) adjust sr announcements for idle disconnect timer #908 - ## [1.4.0] - 2026-01-25 ### Added diff --git a/src/frontend/src/layout/Header.tsx b/src/frontend/src/layout/Header.tsx index b628eb1e..df247b29 100644 --- a/src/frontend/src/layout/Header.tsx +++ b/src/frontend/src/layout/Header.tsx @@ -10,6 +10,7 @@ import { FeedbackBanner } from '@/components/FeedbackBanner' import { Menu } from '@/primitives/Menu' import { MenuList } from '@/primitives/MenuList' import { LoginButton } from '@/components/LoginButton' +import { VisualOnlyTooltip } from '@/primitives/VisualOnlyTooltip' import { useLoginHint } from '@/hooks/useLoginHint' @@ -90,6 +91,11 @@ export const Header = () => { const isTermsOfService = useMatchesRoute('termsOfService') const isRoom = useMatchesRoute('room') const { user, isLoggedIn, logout } = useUser() + const userLabel = user?.full_name || user?.email + const loggedInTooltip = t('loggedInUserTooltip') + const loggedInAriaLabel = userLabel + ? `${loggedInTooltip} ${userLabel}` + : loggedInTooltip return ( <> @@ -153,23 +159,24 @@ export const Header = () => { )} {!!user && ( - { - const wrapperRef = useRef(null) const [isVisible, setIsVisible] = useState(false) + const wrapperRef = useRef(null) + const [position, setPosition] = useState<{ + top: number + left: number + } | null>(null) - const getPosition = () => { - if (!wrapperRef.current) return null + const isBottom = tooltipPosition === 'bottom' + + const showTooltip = () => { + if (!wrapperRef.current) return const rect = wrapperRef.current.getBoundingClientRect() - return { - top: rect.top - 8, + setPosition({ + top: isBottom ? rect.bottom + 8 : rect.top - 8, left: rect.left + rect.width / 2, - } + }) + setIsVisible(true) + } + + const hideTooltip = () => { + setIsVisible(false) + setPosition(null) } - const position = getPosition() const tooltipData = isVisible && position ? { isVisible, position } : null + const wrappedChild = isValidElement(children) + ? cloneElement(children, { + ...(ariaLabel ? { 'aria-label': ariaLabel } : {}), + }) + : children return ( <>
setIsVisible(true)} - onMouseLeave={() => setIsVisible(false)} - onFocus={() => setIsVisible(true)} - onBlur={() => setIsVisible(false)} + onMouseEnter={showTooltip} + onMouseLeave={hideTooltip} + onFocus={showTooltip} + onBlur={hideTooltip} > - {children} + {wrappedChild}
{tooltipData && createPortal( @@ -66,17 +92,26 @@ export const VisualOnlyTooltip = ({ '&::after': { content: '""', position: 'absolute', - top: '100%', left: '50%', transform: 'translateX(-50%)', border: '4px solid transparent', - borderTopColor: 'primaryDark.100', + ...(isBottom + ? { + bottom: '100%', + borderBottomColor: 'primaryDark.100', + } + : { + top: '100%', + borderTopColor: 'primaryDark.100', + }), }, })} style={{ top: `${tooltipData.position.top}px`, left: `${tooltipData.position.left}px`, - transform: 'translate(-50%, -100%)', + transform: isBottom + ? 'translate(-50%, 0)' + : 'translate(-50%, -100%)', }} > {tooltip}