fix: modal autofocus close button (#11425)

* fix: improve focus behavior in FlowLogsModal

* fix: improve focus behavior in SaveChangesModal

* refactor: extract onOpenAutoFocus handlers

* check if element exists before prevent

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Antônio Alexandre Borges Lima
2026-02-04 17:47:13 -03:00
committed by GitHub
parent 52479fbe33
commit 71a61d424f
6 changed files with 42 additions and 4 deletions

View File

@ -217,6 +217,7 @@ interface BaseModalProps {
type?: "modal" | "dialog" | "full-screen";
onSubmit?: () => void;
onEscapeKeyDown?: (e: KeyboardEvent) => void;
onOpenAutoFocus?: (e: Event) => void;
closeButtonClassName?: string;
dialogContentWithouFixed?: boolean;
}
@ -230,6 +231,7 @@ function BaseModal({
type = "dialog",
onSubmit,
onEscapeKeyDown,
onOpenAutoFocus,
closeButtonClassName,
dialogContentWithouFixed = false,
}: BaseModalProps) {
@ -290,6 +292,7 @@ function BaseModal({
<DialogContentWithouFixed
onClick={(e) => e.stopPropagation()}
onEscapeKeyDown={onEscapeKeyDown}
onOpenAutoFocus={onOpenAutoFocus}
className={contentClasses}
closeButtonClassName={closeButtonClassName}
>
@ -311,6 +314,7 @@ function BaseModal({
<DialogContent
onClick={(e) => e.stopPropagation()}
onEscapeKeyDown={onEscapeKeyDown}
onOpenAutoFocus={onOpenAutoFocus}
className={contentClasses}
closeButtonClassName={closeButtonClassName}
>

View File

@ -41,6 +41,7 @@ function ConfirmationModal({
index,
onConfirm,
open,
onOpenAutoFocus,
onClose,
onCancel,
...props
@ -78,7 +79,12 @@ function ConfirmationModal({
};
return (
<BaseModal {...props} open={open} setOpen={setModalOpen}>
<BaseModal
{...props}
open={open}
setOpen={setModalOpen}
onOpenAutoFocus={onOpenAutoFocus}
>
<BaseModal.Trigger>{triggerChild}</BaseModal.Trigger>
<BaseModal.Header description={titleHeader ?? null}>
<span className="pr-2">{title}</span>

View File

@ -90,9 +90,25 @@ export default function FlowLogsModal({
}
}, []);
const handleOpenAutoFocus = useCallback((e: Event) => {
const viewport = document.querySelector(
".ag-body-viewport",
) as HTMLElement | null;
if (viewport) {
e.preventDefault();
viewport.focus();
}
// If viewport doesn't exist (empty table), let default focus behavior happen
}, []);
return (
<>
<BaseModal open={open} setOpen={setOpen} size="x-large">
<BaseModal
open={open}
setOpen={setOpen}
size="x-large"
onOpenAutoFocus={handleOpenAutoFocus}
>
<BaseModal.Trigger asChild>{children}</BaseModal.Trigger>
<BaseModal.Header description="Inspect component executions.">
<div className="flex w-full justify-between">

View File

@ -1,5 +1,5 @@
import { truncate } from "lodash";
import { useState } from "react";
import { useCallback, useState } from "react";
import ForwardedIconComponent from "@/components/common/genericIconComponent";
import Loading from "@/components/ui/loading";
import ConfirmationModal from "../confirmationModal";
@ -20,6 +20,14 @@ export function SaveChangesModal({
autoSave: boolean;
}): JSX.Element {
const [saving, setSaving] = useState(false);
const handleOpenAutoFocus = useCallback((e: Event) => {
e.preventDefault();
(
document.querySelector('[data-testid="replace-button"]') as HTMLElement
)?.focus();
}, []);
return (
<ConfirmationModal
open={true}
@ -42,6 +50,7 @@ export function SaveChangesModal({
onCancel={onProceed}
loading={autoSave ? true : saving}
size="x-small"
onOpenAutoFocus={handleOpenAutoFocus}
>
<ConfirmationModal.Content>
{autoSave ? (

View File

@ -407,6 +407,7 @@ export type ConfirmationModalType = {
| "small-h-full"
| "medium-h-full";
onEscapeKeyDown?: (e: KeyboardEvent) => void;
onOpenAutoFocus?: (e: Event) => void;
};
export type UserManagementType = {

View File

@ -89,7 +89,9 @@ test(
await expect(
page.getByText("timestamp", { exact: true }).last(),
).toBeAttached();
await expect(page.getByText("text", { exact: true }).last()).toBeAttached();
await expect(
page.getByText("files", { exact: true }).last(),
).toBeAttached();
await expect(
page.getByText("sender", { exact: true }).last(),
).toBeAttached();