Skip to content

Commit 8fb8dd5

Browse files
committed
fixup! adds f2 shortcut using a fakenode since it's outside the treeview struct
1 parent 508be33 commit 8fb8dd5

File tree

5 files changed

+32
-174
lines changed

5 files changed

+32
-174
lines changed

src/frontend/apps/impress/src/features/docs/doc-tree/components/DocSubPageItem.tsx

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
useTreeContext,
66
} from '@gouvfr-lasuite/ui-kit';
77
import { useRouter } from 'next/navigation';
8-
import { useState } from 'react';
8+
import { useRef, useState } from 'react';
99
import { useTranslation } from 'react-i18next';
1010
import { css } from 'styled-components';
1111

@@ -20,9 +20,6 @@ import {
2020
import { useLeftPanelStore } from '@/features/left-panel';
2121
import { useResponsiveStore } from '@/stores';
2222

23-
import { useActionableMode } from '../hooks/useActionableMode';
24-
import { useKeyboardActivation } from '../hooks/useKeyboardActivation';
25-
2623
import SubPageIcon from './../assets/sub-page-logo.svg';
2724
import { DocTreeItemActions } from './DocTreeItemActions';
2825

@@ -47,7 +44,6 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
4744

4845
const [menuOpen, setMenuOpen] = useState(false);
4946
const isSelectedNow = treeContext?.treeData.selectedNode?.id === doc.id;
50-
const isActive = node.isFocused || menuOpen || isSelectedNow;
5147

5248
const router = useRouter();
5349
const { togglePanel } = useLeftPanelStore();
@@ -93,21 +89,24 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
9389
}
9490
};
9591

96-
useKeyboardActivation(
97-
['Enter'],
98-
isActive && !menuOpen,
99-
handleActivate,
100-
true,
101-
'.c__tree-view',
102-
);
103-
10492
const docTitle = doc.title || untitledDocument;
10593
const hasChildren = (doc.children?.length || 0) > 0;
10694
const isExpanded = node.isOpen;
10795
const isSelected = isSelectedNow;
10896
const ariaLabel = docTitle;
10997
const isDisabled = !!doc.deleted_at;
110-
const { actionsRef, onKeyDownCapture } = useActionableMode(node, menuOpen);
98+
const actionsRef = useRef<HTMLDivElement>(null);
99+
const buttonOptionRef = useRef<HTMLButtonElement | null>(null);
100+
101+
const handleKeyDown = (e: React.KeyboardEvent) => {
102+
// F2: focus first action button
103+
const shoulOpenActions = !menuOpen && node.isFocused;
104+
if (e.key === 'F2' && shoulOpenActions) {
105+
buttonOptionRef.current?.focus();
106+
e.stopPropagation();
107+
return;
108+
}
109+
};
111110

112111
return (
113112
<Box
@@ -119,7 +118,7 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
119118
aria-selected={isSelected}
120119
aria-expanded={hasChildren ? isExpanded : undefined}
121120
aria-disabled={isDisabled}
122-
onKeyDownCapture={onKeyDownCapture}
121+
onKeyDown={handleKeyDown}
123122
$css={css`
124123
background-color: var(--c--globals--colors--gray-000);
125124
.light-doc-item-actions {
@@ -186,7 +185,7 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
186185
parentId={node.data.parentKey}
187186
onCreateSuccess={afterCreate}
188187
actionsRef={actionsRef}
189-
onKeyDownCapture={onKeyDownCapture}
188+
buttonOptionRef={buttonOptionRef}
190189
/>
191190
</Box>
192191
<BoxButton

src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTree.tsx

Lines changed: 12 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ import { Doc, SimpleDocItem } from '@/docs/doc-management';
1616

1717
import { KEY_DOC_TREE, useDocTree } from '../api/useDocTree';
1818
import { useMoveDoc } from '../api/useMove';
19-
import { useActionableMode } from '../hooks/useActionableMode';
20-
import type { ActionableNodeLike } from '../hooks/useActionableMode';
2119
import { findIndexInTree } from '../utils';
2220

2321
import { DocSubPageItem } from './DocSubPageItem';
@@ -34,29 +32,15 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
3432
const treeContext = useTreeContext<Doc | null>();
3533
const router = useRouter();
3634
const [rootActionsOpen, setRootActionsOpen] = useState(false);
37-
const [rootItemFocused, setRootItemFocused] = useState(false);
3835
const rootIsSelected =
3936
!!treeContext?.root?.id &&
4037
treeContext?.treeData.selectedNode?.id === treeContext.root.id;
4138
const rootItemRef = useRef<HTMLDivElement>(null);
39+
const rootActionsRef = useRef<HTMLDivElement>(null);
40+
const rootButtonOptionRef = useRef<HTMLButtonElement | null>(null);
4241

4342
const { t } = useTranslation();
4443

45-
/**
46-
* Fake node to reuse useActionableMode hook for the root item.
47-
* This allows F2 keyboard navigation and Escape handling on the root item
48-
* without duplicating the logic from DocSubPageItem.
49-
*/
50-
const fakeRootNode: ActionableNodeLike = {
51-
isFocused: rootItemFocused,
52-
focus: () => {
53-
rootItemRef.current?.focus();
54-
},
55-
};
56-
57-
const { actionsRef: rootActionsRef, onKeyDownCapture: onRootToolbarKeys } =
58-
useActionableMode(fakeRootNode, rootActionsOpen);
59-
6044
const [initialOpenState, setInitialOpenState] = useState<OpenMap | undefined>(
6145
undefined,
6246
);
@@ -104,17 +88,19 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
10488
}, [router, treeContext?.root?.id]);
10589

10690
const handleRootFocus = useCallback(() => {
107-
setRootItemFocused(true);
10891
selectRoot();
10992
}, [selectRoot]);
11093

111-
const handleRootBlur = useCallback(() => {
112-
setRootItemFocused(false);
113-
}, []);
114-
115-
// activate root document with enter or space (only when not in actions)
94+
// Handle keyboard navigation for root item
11695
const handleRootKeyDown = useCallback(
11796
(e: React.KeyboardEvent) => {
97+
// F2: focus first action button
98+
if (e.key === 'F2' && !rootActionsOpen) {
99+
e.preventDefault();
100+
rootButtonOptionRef.current?.focus();
101+
return;
102+
}
103+
118104
// Ignore if focus is in actions
119105
const target = e.target as HTMLElement | null;
120106
if (target?.closest('.doc-tree-root-item-actions')) {
@@ -127,7 +113,7 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
127113
navigateToRoot();
128114
}
129115
},
130-
[selectRoot, navigateToRoot],
116+
[selectRoot, navigateToRoot, rootActionsOpen],
131117
);
132118

133119
/**
@@ -250,7 +236,6 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
250236
aria-selected={rootIsSelected}
251237
tabIndex={0}
252238
onFocus={handleRootFocus}
253-
onBlur={handleRootBlur}
254239
onKeyDown={handleRootKeyDown}
255240
$css={css`
256241
padding: ${spacingsTokens['2xs']};
@@ -327,7 +312,7 @@ export const DocTree = ({ currentDoc }: DocTreeProps) => {
327312
isRoot={true}
328313
onOpenChange={setRootActionsOpen}
329314
actionsRef={rootActionsRef}
330-
onKeyDownCapture={onRootToolbarKeys}
315+
buttonOptionRef={rootButtonOptionRef}
331316
/>
332317
</Box>
333318
</StyledLink>

src/frontend/apps/impress/src/features/docs/doc-tree/components/DocTreeItemActions.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ type DocTreeItemActionsProps = {
3333
onOpenChange?: (isOpen: boolean) => void;
3434
parentId?: string | null;
3535
actionsRef?: React.RefObject<HTMLDivElement | null>;
36-
onKeyDownCapture?: (e: React.KeyboardEvent) => void;
36+
buttonOptionRef?: React.RefObject<HTMLButtonElement | null>;
3737
};
3838

3939
export const DocTreeItemActions = ({
@@ -44,10 +44,12 @@ export const DocTreeItemActions = ({
4444
onOpenChange,
4545
parentId,
4646
actionsRef,
47-
onKeyDownCapture,
47+
buttonOptionRef,
4848
}: DocTreeItemActionsProps) => {
4949
const internalActionsRef = useRef<HTMLDivElement | null>(null);
5050
const targetActionsRef = actionsRef ?? internalActionsRef;
51+
const internalButtonRef = useRef<HTMLButtonElement | null>(null);
52+
const targetButtonRef = buttonOptionRef ?? internalButtonRef;
5153
const router = useRouter();
5254
const { t } = useTranslation();
5355
const deleteModal = useModal();
@@ -174,7 +176,6 @@ export const DocTreeItemActions = ({
174176
<Box className="doc-tree-root-item-actions actions">
175177
<Box
176178
ref={targetActionsRef}
177-
onKeyDownCapture={onKeyDownCapture}
178179
$direction="row"
179180
$align="center"
180181
className="--docs--doc-tree-item-actions"
@@ -188,6 +189,7 @@ export const DocTreeItemActions = ({
188189
>
189190
<Box
190191
as="button"
192+
ref={targetButtonRef}
191193
type="button"
192194
onClick={(e) => {
193195
e.stopPropagation();

src/frontend/apps/impress/src/features/docs/doc-tree/hooks/useActionableMode.ts

Lines changed: 0 additions & 83 deletions
This file was deleted.

src/frontend/apps/impress/src/features/docs/doc-tree/hooks/useKeyboardActivation.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.

0 commit comments

Comments
 (0)