fix: Autofocus inside lazy-loaded modal and popover (#12146)

* fix: Autofocus inside lazy-loaded modal/popover

* use wrapperRef

* remove unused import
This commit is contained in:
Hemachandar
2026-05-01 17:45:14 +05:30
committed by GitHub
parent 1caf7f9221
commit e2c28f4b9f
3 changed files with 30 additions and 3 deletions
@@ -66,6 +66,7 @@ function SharePopover({
const share = shares.getByCollectionId(collection.id);
const prevPendingIds = usePrevious(pendingIds);
const wrapperRef = React.useRef<HTMLDivElement | null>(null);
const suggestionsRef = React.useRef<HTMLDivElement | null>(null);
const searchInputRef = React.useRef<HTMLInputElement | null>(null);
@@ -89,6 +90,15 @@ function SharePopover({
}
);
// Move focus into the popover to account for lazy-loading
React.useLayoutEffect(() => {
if (!hasRendered) {
return;
}
(searchInputRef.current ?? wrapperRef.current)?.focus();
}, [hasRendered]);
// Hide the picker when the popover is closed
React.useEffect(() => {
if (visible) {
@@ -351,7 +361,7 @@ function SharePopover({
);
return (
<Wrapper>
<Wrapper ref={wrapperRef} tabIndex={-1}>
{can.update && (
<SearchInput
ref={searchInputRef}
@@ -68,6 +68,7 @@ function SharePopover({
const prevPendingIds = usePrevious(pendingIds);
const wrapperRef = React.useRef<HTMLDivElement | null>(null);
const suggestionsRef = React.useRef<HTMLDivElement | null>(null);
const searchInputRef = React.useRef<HTMLInputElement | null>(null);
@@ -91,6 +92,15 @@ function SharePopover({
}
);
// Move focus into the popover to account for lazy-loading
React.useLayoutEffect(() => {
if (!hasRendered) {
return;
}
(searchInputRef.current ?? wrapperRef.current)?.focus();
}, [hasRendered]);
React.useEffect(() => {
if (visible) {
if (externalLoading === undefined) {
@@ -358,7 +368,7 @@ function SharePopover({
);
return (
<Wrapper>
<Wrapper ref={wrapperRef} tabIndex={-1}>
{can.manageUsers && (
<SearchInput
ref={searchInputRef}
+8 -1
View File
@@ -15,6 +15,7 @@ import { useTextStats } from "~/hooks/useTextStats";
import type Document from "~/models/Document";
import { useFormatNumber } from "~/hooks/useFormatNumber";
import { ProsemirrorHelper } from "~/models/helpers/ProsemirrorHelper";
import { useLayoutEffect, useRef } from "react";
type Props = {
document: Document;
@@ -22,13 +23,19 @@ type Props = {
function Insights({ document }: Props) {
const { t } = useTranslation();
const wrapperRef = useRef<HTMLDivElement | null>(null);
const selectedText = useTextSelection();
const text = ProsemirrorHelper.toPlainText(document);
const stats = useTextStats(text ?? "", selectedText);
const formatNumber = useFormatNumber();
// Move focus into the modal to account for lazy-loading
useLayoutEffect(() => {
wrapperRef.current?.focus();
}, []);
return (
<div>
<div ref={wrapperRef} tabIndex={-1}>
{document ? (
<Flex
column