Fix hotkey bugs (#17273)

- Fix a race condition due to a page change effect re-trigger which
reset the focus stack (A user had a bug which happened when he opened
the command menu quickly after the page load. The focus stack was reset
and the hotkeys listening were the one from the table instead of the one
from the command menu)
- Fix the focus id in the side panel input which prevented using the
hotkeys
This commit is contained in:
Raphaël Bosi
2026-01-20 13:19:58 +01:00
committed by GitHub
parent a004662221
commit f9c400cd78
5 changed files with 14 additions and 21 deletions
@@ -5,7 +5,7 @@ import { CommandMenuTopBarRightCornerIcon } from '@/command-menu/components/Comm
import { COMMAND_MENU_SEARCH_BAR_HEIGHT } from '@/command-menu/constants/CommandMenuSearchBarHeight';
import { COMMAND_MENU_SEARCH_BAR_HEIGHT_MOBILE } from '@/command-menu/constants/CommandMenuSearchBarHeightMobile';
import { COMMAND_MENU_SEARCH_BAR_PADDING } from '@/command-menu/constants/CommandMenuSearchBarPadding';
import { COMMAND_MENU_SEARCH_INPUT_FOCUS_ID } from '@/command-menu/constants/CommandMenuSearchInputFocusId';
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { useCommandMenuContextChips } from '@/command-menu/hooks/useCommandMenuContextChips';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
@@ -110,10 +110,10 @@ export const CommandMenuTopBar = () => {
const handleInputFocus = () => {
pushFocusItemToFocusStack({
focusId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
focusId: SIDE_PANEL_FOCUS_ID,
component: {
type: FocusComponentType.TEXT_INPUT,
instanceId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
instanceId: SIDE_PANEL_FOCUS_ID,
},
globalHotkeysConfig: {
enableGlobalHotkeysConflictingWithKeyboard: false,
@@ -123,7 +123,7 @@ export const CommandMenuTopBar = () => {
const handleInputBlur = () => {
removeFocusItemFromFocusStackById({
focusId: COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
focusId: SIDE_PANEL_FOCUS_ID,
});
};
@@ -175,7 +175,7 @@ export const CommandMenuTopBar = () => {
commandMenuPage === CommandMenuPages.SearchRecords) && (
<>
<StyledInput
data-testid={COMMAND_MENU_SEARCH_INPUT_FOCUS_ID}
data-testid={SIDE_PANEL_FOCUS_ID}
ref={inputRef}
value={commandMenuSearch}
placeholder={t`Type anything...`}
@@ -25,7 +25,7 @@ import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceSta
import { type CommandMenu } from '@/command-menu/components/CommandMenu';
import { CommandMenuRouter } from '@/command-menu/components/CommandMenuRouter';
import { COMMAND_MENU_COMPONENT_INSTANCE_ID } from '@/command-menu/constants/CommandMenuComponentInstanceId';
import { COMMAND_MENU_SEARCH_INPUT_FOCUS_ID } from '@/command-menu/constants/CommandMenuSearchInputFocusId';
import { SIDE_PANEL_FOCUS_ID } from '@/command-menu/constants/SidePanelFocusId';
import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
@@ -153,9 +153,7 @@ export const LimitedPermissions: Story = {
export const MatchingNavigate: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const searchInput = await canvas.findByTestId(
COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
);
const searchInput = await canvas.findByTestId(SIDE_PANEL_FOCUS_ID);
await sleep(openTimeout);
await userEvent.type(searchInput, 'ta');
expect(await canvas.findByText('Go to Tasks')).toBeVisible();
@@ -165,9 +163,7 @@ export const MatchingNavigate: Story = {
export const MatchingNavigateShortcuts: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const searchInput = await canvas.findByTestId(
COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
);
const searchInput = await canvas.findByTestId(SIDE_PANEL_FOCUS_ID);
await sleep(openTimeout);
await userEvent.type(searchInput, 'gp');
expect(await canvas.findByText('Go to People')).toBeVisible();
@@ -192,9 +188,7 @@ export const MatchingNavigateShortcuts: Story = {
export const NoResultsSearchFallback: Story = {
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const searchInput = await canvas.findByTestId(
COMMAND_MENU_SEARCH_INPUT_FOCUS_ID,
);
const searchInput = await canvas.findByTestId(SIDE_PANEL_FOCUS_ID);
await sleep(openTimeout);
await userEvent.type(searchInput, 'input without results');
expect(await canvas.findByText('No results found')).toBeVisible();