dbeaver/cloudbeaver#4159 Add tree keyboard expand and open actions - #4658
sergeyteleshev wants to merge 10 commits into
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 49 |
NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.
There was a problem hiding this comment.
🟡 Changes recommended
TreeNew leaf state must be propagated to avoid incorrect expand behavior; add coverage for TreeNew leaves.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Adds keyboard expand, collapse, and open actions to the shared tree node control while preserving navigation and input handling.
Changes:
- Adds focus-scoped ArrowRight, ArrowLeft, and Enter handling.
- Covers keyboard actions and edge cases with 14 regression tests.
File summaries
| File | Summary |
|---|---|
webapp/packages/core-blocks/src/Tree/TreeNode/TreeNodeControl.tsx |
Implements shared keyboard tree actions. |
webapp/packages/core-blocks/src/Tree/TreeNode/TreeNodeControl.test.tsx |
Tests keyboard interactions, focus, navigation, and unavailable states. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| const expand = | ||
| !context.leaf && | ||
| !context.externalExpanded && | ||
| (event.key === 'Enter' || (event.key === 'ArrowRight' && !context.expanded) || (event.key === 'ArrowLeft' && context.expanded)); | ||
| const open = context.leaf && (event.key === 'Enter' || event.key === 'ArrowRight'); |
| const innerRef = useRef<HTMLDivElement>(null); | ||
| const mergedRef = useMergeRefs(innerRef, ref); | ||
| const [focusRef, focusState] = useFocus<HTMLDivElement>({}); | ||
| const hotkeysRef = useHotkeys<HTMLDivElement>('ArrowRight,ArrowLeft,Enter', handleKeyboardAction, { enabled: focusState.focus, useKey: true }); |
There was a problem hiding this comment.
i think more clear approach would be to define callback separately and move logic to hook
function useTreeNodeKeyboardActions(
context: ITreeNodeContext,
innerRef: React.RefObject<HTMLDivElement | null>,
enabled: boolean,
) {
const options = { enabled, useKey: true };
useHotkeys('ArrowRight', handleArrowRight, options);
useHotkeys('ArrowLeft', handleArrowLeft, options);
useHotkeys('Enter', handleEnter, options);
function handleArrowRight(event: KeyboardEvent) {
if (context.leaf) {
return handleAction(event, context.open);
}
if (!context.expanded && !context.externalExpanded) {
return handleAction(event, context.expand);
}
}
function handleArrowLeft(event: KeyboardEvent) {
if (context.expanded && !context.leaf && !context.externalExpanded) {
return handleAction(event, context.expand);
}
}
function handleEnter(event: KeyboardEvent) {
if (context.leaf) {
return handleAction(event, context.open);
}
if (!context.externalExpanded) {
return handleAction(event, context.expand);
}
}
async function handleAction(event: KeyboardEvent, action: () => Promise<void>) {
if (
event.target !== innerRef.current ||
event.defaultPrevented ||
EventContext.has(event, EventKeyboardNavigationFlag, EventStopPropagationFlag)
) {
return;
}
EventContext.set(event, EventKeyboardNavigationFlag);
EventContext.set(event, EventTreeNodeExpandFlag);
event.preventDefault();
if (context.disabled || context.loading || context.processing) {
return;
}
await action();
}
}
const [focusRef, focusState] = useFocus<HTMLDivElement>({});
useTreeNodeKeyboardActions(context, innerRef, focusState.focus);
const mergedRef = useMergeRefs(innerRef, focusRef, ref);
Closes #4159
Summary
Supersedes #4640.
Validation
yarn workspace @cloudbeaver/plugin-navigation-tree buildpassed, including core-blocks dependencies.yarn workspace @cloudbeaver/core-blocks test: 171 passed, 17 skipped.yarn workspace @cloudbeaver/plugin-navigation-tree test: 2 passed; one existing suite skipped.git diff --checkpassed.Companion PR
https://github.com/dbeaver/cloudbeaver-ee/pull/2679