Autofocus on close button when opening lightbox

Co-authored-by: trevor-signal <131492920+trevor-signal@users.noreply.github.com>
This commit is contained in:
automated-signal
2026-06-09 22:04:51 -05:00
committed by GitHub
parent 507384f645
commit 5427f5a2e3
4 changed files with 13 additions and 8 deletions
+4 -2
View File
@@ -332,8 +332,10 @@
width: 100%;
}
&:focus {
outline: 4px solid variables.$color-ultramarine;
@include mixins.keyboard-mode {
&:focus {
outline: 4px solid variables.$color-ultramarine;
}
}
&:disabled {
+2 -5
View File
@@ -729,11 +729,7 @@ export function Lightbox({
role="presentation"
>
<div className="Lightbox__animated">
<div
className="Lightbox__main-container"
tabIndex={-1}
ref={focusRef}
>
<div className="Lightbox__main-container">
<div className="Lightbox__header">
{getConversation && currentItem != null ? (
<LightboxHeader
@@ -765,6 +761,7 @@ export function Lightbox({
aria-label={i18n('icu:close')}
className="Lightbox__button Lightbox__button--close"
onClick={closeLightbox}
ref={focusRef}
type="button"
/>
</div>
@@ -3309,6 +3309,7 @@ export class Message extends PureComponent<Props, State> {
return;
}
window.enterKeyboardMode();
this.handleOpen(event);
};
+6 -1
View File
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: AGPL-3.0-only
import { useRef, useCallback, useEffect } from 'react';
import { clearTimeoutIfNecessary } from '../util/clearTimeoutIfNecessary.std.ts';
type CallbackType = (toFocus: HTMLElement | null | undefined) => void;
@@ -9,11 +10,15 @@ type CallbackType = (toFocus: HTMLElement | null | undefined) => void;
export const useRestoreFocus = (): [CallbackType] => {
const toFocusRef = useRef<HTMLElement | null>(null);
const lastFocusedRef = useRef<HTMLElement | null>(null);
const focusLastElementTimeoutRef =
useRef<ReturnType<typeof setTimeout>>(null);
// We need to use a callback here because refs aren't necessarily populated on first
// render. For example, ModalHost makes a top-level parent div first, and then renders
// into it. And the children you pass it don't have access to that root div.
const setFocusRef = useCallback((toFocus: HTMLElement | null | undefined) => {
clearTimeoutIfNecessary(focusLastElementTimeoutRef.current);
if (!toFocus) {
return;
}
@@ -32,7 +37,7 @@ export const useRestoreFocus = (): [CallbackType] => {
useEffect(() => {
return () => {
// On unmount, returned focus to element focused before we set the focus
setTimeout(() => {
focusLastElementTimeoutRef.current = setTimeout(() => {
if (lastFocusedRef.current && lastFocusedRef.current.focus) {
lastFocusedRef.current.focus();
}