Skip to content

Commit a5acdf2

Browse files
flyFatSealzombieJ
andauthored
fix: TreeSelect keyboard navigation has inconsistent focusing (#433)
* fix: TreeSelect keyboard navigation has inconsistent focusing * chore: reorder --------- Co-authored-by: flyFatSeal <@flyFatSeal> Co-authored-by: 二货机器人 <[email protected]>
1 parent f647626 commit a5acdf2

File tree

2 files changed

+66
-3
lines changed

2 files changed

+66
-3
lines changed

src/OptionList.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ const OptionList: React.RefForwardingComponent<ReviseRefOptionListProps> = (_, r
7272
(prev, next) => next[0] && prev[1] !== next[1],
7373
);
7474

75+
// ========================== Active ==========================
76+
const [activeKey, setActiveKey] = React.useState<Key>(null);
77+
const activeEntity = keyEntities[activeKey];
78+
7579
// ========================== Values ==========================
7680
const mergedCheckedKeys = React.useMemo(() => {
7781
if (!checkable) {
@@ -89,6 +93,7 @@ const OptionList: React.RefForwardingComponent<ReviseRefOptionListProps> = (_, r
8993
// Single mode should scroll to current key
9094
if (open && !multiple && checkedKeys.length) {
9195
treeRef.current?.scrollTo({ key: checkedKeys[0] });
96+
setActiveKey(checkedKeys[0]);
9297
}
9398
}, [open]);
9499

@@ -149,9 +154,6 @@ const OptionList: React.RefForwardingComponent<ReviseRefOptionListProps> = (_, r
149154
};
150155

151156
// ========================= Keyboard =========================
152-
const [activeKey, setActiveKey] = React.useState<Key>(null);
153-
const activeEntity = keyEntities[activeKey];
154-
155157
React.useImperativeHandle(ref, () => ({
156158
scrollTo: treeRef.current?.scrollTo,
157159
onKeyDown: event => {

tests/Select.spec.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,67 @@ describe('TreeSelect.basic', () => {
468468
keyDown(KeyCode.ENTER);
469469
expect(onChange).not.toHaveBeenCalled();
470470
});
471+
472+
it('active index matches value', () => {
473+
const wrapper = mount(
474+
<TreeSelect
475+
value={['10']}
476+
treeDefaultExpandAll
477+
treeData={[
478+
{ key: '0', value: '0', title: '0 label' },
479+
{
480+
key: '1',
481+
value: '1',
482+
title: '1 label',
483+
children: [
484+
{ key: '10', value: '10', title: '10 label' },
485+
{ key: '11', value: '11', title: '11 label' },
486+
],
487+
},
488+
]}
489+
/>,
490+
);
491+
wrapper.openSelect();
492+
expect(wrapper.find('.rc-tree-select-tree-treenode-active').text()).toBe('10 label');
493+
});
494+
495+
it('active index updates correctly with key operation', () => {
496+
const wrapper = mount(
497+
<TreeSelect
498+
value={['10']}
499+
treeDefaultExpandAll
500+
treeData={[
501+
{ key: '0', value: '0', title: '0 label' },
502+
{
503+
key: '1',
504+
value: '1',
505+
title: '1 label',
506+
children: [
507+
{ key: '10', value: '10', title: '10 label' },
508+
{ key: '11', value: '11', title: '11 label' },
509+
],
510+
},
511+
]}
512+
/>,
513+
);
514+
515+
function keyDown(code) {
516+
wrapper.find('input').first().simulate('keyDown', { which: code });
517+
wrapper.update();
518+
}
519+
520+
wrapper.openSelect();
521+
expect(wrapper.find('.rc-tree-select-tree-treenode-active').text()).toBe('10 label');
522+
523+
keyDown(KeyCode.DOWN);
524+
expect(wrapper.find('.rc-tree-select-tree-treenode-active').text()).toBe('11 label');
525+
526+
keyDown(KeyCode.DOWN);
527+
expect(wrapper.find('.rc-tree-select-tree-treenode-active').text()).toBe('0 label');
528+
529+
keyDown(KeyCode.UP);
530+
expect(wrapper.find('.rc-tree-select-tree-treenode-active').text()).toBe('11 label');
531+
});
471532
});
472533

473534
it('click in list should preventDefault', () => {

0 commit comments

Comments
 (0)