mirror of
https://github.com/suitenumerique/docs.git
synced 2026-04-25 17:15:01 +02:00
✨(frontend) fix tree keyboard toggle when children not yet loaded
node expansion now triggers lazy loading even without prior mouse interaction Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
@@ -12,6 +12,7 @@ and this project adheres to
|
||||
|
||||
- ♿(frontend) improve accessibility:
|
||||
- #1354
|
||||
- ✨fix tree keyboard toggle when children not yet loaded #1388
|
||||
|
||||
### Fixed
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import { useLeftPanelStore } from '@/features/left-panel';
|
||||
import { useResponsiveStore } from '@/stores';
|
||||
|
||||
import { useKeyboardActivation } from '../hooks/useKeyboardActivation';
|
||||
import { useLoadChildrenOnOpen } from '../hooks/useLoadChildrenOnOpen';
|
||||
|
||||
import SubPageIcon from './../assets/sub-page-logo.svg';
|
||||
import { DocTreeItemActions } from './DocTreeItemActions';
|
||||
@@ -96,6 +97,14 @@ export const DocSubPageItem = (props: TreeViewNodeProps<Doc>) => {
|
||||
'.c__tree-view',
|
||||
);
|
||||
|
||||
useLoadChildrenOnOpen(
|
||||
node.data.value.id,
|
||||
node.isOpen,
|
||||
treeContext?.treeData.handleLoadChildren,
|
||||
treeContext?.treeData.setChildren,
|
||||
(doc.children?.length ?? 0) > 0 || doc.childrenCount === 0,
|
||||
);
|
||||
|
||||
const docTitle = doc.title || untitledDocument;
|
||||
const hasChildren = (doc.children?.length || 0) > 0;
|
||||
const isExpanded = node.isOpen;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
/**
|
||||
* Lazily loads children for a tree node the first time it is expanded.
|
||||
*/
|
||||
export const useLoadChildrenOnOpen = <T>(
|
||||
nodeId: string,
|
||||
isOpen: boolean,
|
||||
handleLoadChildren?: (id: string, signal: AbortSignal) => Promise<T[]>,
|
||||
setChildren?: (id: string, children: T[]) => void,
|
||||
isAlreadyLoaded: boolean = false,
|
||||
) => {
|
||||
const hasLoadedRef = useRef(false);
|
||||
|
||||
// Reset only if node changes AND it's not already loaded externally
|
||||
useEffect(() => {
|
||||
hasLoadedRef.current = isAlreadyLoaded;
|
||||
}, [nodeId, isAlreadyLoaded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
if (isAlreadyLoaded || hasLoadedRef.current) {
|
||||
return;
|
||||
}
|
||||
if (!handleLoadChildren || !setChildren) {
|
||||
return;
|
||||
}
|
||||
|
||||
const abortCtrl = new AbortController();
|
||||
hasLoadedRef.current = true; // prevent multiple fetches
|
||||
|
||||
void handleLoadChildren(nodeId, abortCtrl.signal)
|
||||
.then((children) => {
|
||||
if (!abortCtrl.signal.aborted) {
|
||||
setChildren(nodeId, children);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
// allow retry on next open
|
||||
if (!abortCtrl.signal.aborted) {
|
||||
hasLoadedRef.current = false;
|
||||
}
|
||||
});
|
||||
|
||||
return () => {
|
||||
abortCtrl.abort();
|
||||
};
|
||||
}, [isOpen, nodeId, handleLoadChildren, setChildren, isAlreadyLoaded]);
|
||||
};
|
||||
Reference in New Issue
Block a user