Ensure composition input is focused when clicking to edit or reply to message

This commit is contained in:
trevor-signal
2026-01-06 13:04:09 -05:00
committed by GitHub
parent fd4a55ef42
commit 71c82e1b1e
5 changed files with 40 additions and 5 deletions

View File

@@ -238,6 +238,7 @@ export namespace AxoContextMenu {
className={AxoBaseMenu.menuContentStyles}
alignOffset={-6}
collisionPadding={6}
onCloseAutoFocus={props.onCloseAutoFocus}
>
{props.children}
</ContextMenu.Content>

View File

@@ -190,6 +190,7 @@ export namespace AxoDropdownMenu {
*/
export const Content: FC<ContentProps> = memo(props => {
const { context, labelId, descriptionId } = useCreateAriaLabellingContext();
const { open } = useStrictContext(RootContext);
return (
<AriaLabellingProvider value={context}>
<DropdownMenu.Portal>
@@ -200,6 +201,9 @@ export namespace AxoDropdownMenu {
className={AxoBaseMenu.menuContentStyles}
aria-labelledby={labelId}
aria-describedby={descriptionId}
onCloseAutoFocus={props.onCloseAutoFocus}
// @ts-expect-error -- React/TS doesn't know about inert
inert={open ? undefined : 'true'}
>
{props.children}
</DropdownMenu.Content>

View File

@@ -205,6 +205,7 @@ export namespace AxoBaseMenu {
*/
export type MenuContentProps = Readonly<{
onCloseAutoFocus?: (e: Event) => void;
children: ReactNode;
}>;

View File

@@ -1,7 +1,7 @@
// Copyright 2023 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
import React, { type ReactNode } from 'react';
import React, { useRef, type ReactNode } from 'react';
import type { LocalizerType } from '../../types/I18N.std.js';
import { AxoMenuBuilder } from '../../axo/AxoMenuBuilder.dom.js';
@@ -49,13 +49,21 @@ export function MessageContextMenu({
onPinMessage,
onUnpinMessage,
children,
}: MessageContextMenuProps): React.JSX.Element {
}: MessageContextMenuProps): JSX.Element {
const shouldReturnFocusToTrigger = useRef(true);
return (
<AxoMenuBuilder.Root renderer={renderer} onOpenChange={onOpenChange}>
<AxoMenuBuilder.Trigger disabled={disabled}>
{children}
</AxoMenuBuilder.Trigger>
<AxoMenuBuilder.Content>
<AxoMenuBuilder.Content
onCloseAutoFocus={e => {
if (!shouldReturnFocusToTrigger.current) {
e.preventDefault();
}
}}
>
{shouldShowAdditional && (
<>
{onDownload && (
@@ -64,7 +72,14 @@ export function MessageContextMenu({
</AxoMenuBuilder.Item>
)}
{onReplyToMessage && (
<AxoMenuBuilder.Item symbol="reply" onSelect={onReplyToMessage}>
<AxoMenuBuilder.Item
symbol="reply"
onSelect={() => {
// onReplyToMessage will focus the quill input
shouldReturnFocusToTrigger.current = false;
onReplyToMessage();
}}
>
{i18n('icu:MessageContextMenu__reply')}
</AxoMenuBuilder.Item>
)}
@@ -86,7 +101,14 @@ export function MessageContextMenu({
</AxoMenuBuilder.Item>
)}
{onEdit && (
<AxoMenuBuilder.Item symbol="pencil" onSelect={onEdit}>
<AxoMenuBuilder.Item
symbol="pencil"
onSelect={() => {
// onEdit will focus the quill input
shouldReturnFocusToTrigger.current = false;
onEdit();
}}
>
{i18n('icu:edit')}
</AxoMenuBuilder.Item>
)}

View File

@@ -2370,5 +2370,12 @@
"line": " message.innerHTML = window.SignalContext.i18n('icu:optimizingApplication');",
"reasonCategory": "usageTrusted",
"updated": "2021-09-17T21:02:59.414Z"
},
{
"rule": "React-useRef",
"path": "ts/components/conversation/MessageContextMenu.dom.tsx",
"line": " const shouldReturnFocusToTrigger = useRef(true);",
"reasonCategory": "usageTrusted",
"updated": "2025-12-19T16:03:53.849Z"
}
]