diff --git a/README.md b/README.md
index 2ea7eedc..38a8010b 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,6 @@ React TreeSelect Component
 
 <img src="https://os.alipayobjects.com/rmsportal/HUhyhmpWyiGKnZF.png" width="288"/>
 
-
 ## Development
 
 ```
@@ -55,76 +54,77 @@ online example: https://tree-select-react-component.vercel.app/
 
 ### TreeSelect props
 
-| name     | description    | type     | default      |
-|----------|----------------|----------|--------------|
-|className | additional css class of root dom node | String | '' |
-|prefixCls | prefix class | String | '' |
-|animation | dropdown animation name. only support slide-up now | String | '' |
-|transitionName | dropdown css animation name | String | '' |
-|choiceTransitionName | css animation name for selected items at multiple mode | String | '' |
-|dropdownMatchSelectWidth | whether dropdown's with is same with select. Default set `min-width` same as input | bool | true |
-|dropdownClassName | additional className applied to dropdown | String | - |
-|dropdownStyle | additional style applied to dropdown | Object | {} |
-|onDropdownVisibleChange | control dropdown visible | function | `() => { return true; }` |
-|notFoundContent | specify content to show when no result matches. | String | 'Not Found' |
-|showSearch | whether show search input in single mode | bool | true |
-|allowClear | whether allowClear | bool | false |
-|maxTagTextLength | max tag text length to show | number | - |
-|maxTagCount | max tag count to show | number | - |
-|maxTagPlaceholder | placeholder for omitted values | ReactNode/function(omittedValues) | - |
-|multiple | whether multiple select (true when enable treeCheckable) | bool | false |
-|disabled | whether disabled select | bool | false |
-|searchValue | work with `onSearch` to make search value controlled. | string | '' |
-|defaultValue | initial selected treeNode(s) | same as value type | - |
-|value | current selected treeNode(s). | normal: String/Array<String>. labelInValue: {value:String,label:React.Node}/Array<{value,label}>. treeCheckStrictly(halfChecked default false): {value:String,label:React.Node, halfChecked}/Array<{value,label,halfChecked}>. | - |
-|labelInValue| whether to embed label in value, see above value type | Bool | false |
-|onChange | called when select treeNode or input value change | function(value, label(null), extra) | - |
-|onSelect | called when select treeNode | function(value, node, extra) | - |
-|onSearch | called when input changed | function | - |
-|onTreeExpand | called when tree node expand | function(expandedKeys) | - |
-|onPopupScroll | called when popup scroll | function(event) | - |
-|showCheckedStrategy | `TreeSelect.SHOW_ALL`: show all checked treeNodes (Include parent treeNode). `TreeSelect.SHOW_PARENT`: show checked treeNodes (Just show parent treeNode). Default just show child. | enum{TreeSelect.SHOW_ALL, TreeSelect.SHOW_PARENT, TreeSelect.SHOW_CHILD } | TreeSelect.SHOW_CHILD |
-|treeIcon | show tree icon | bool | false |
-|treeLine | show tree line | bool | false |
-|treeDefaultExpandAll | default expand all treeNode | bool | false |
-|treeDefaultExpandedKeys | default expanded treeNode keys | Array<String> | - |
-|treeExpandedKeys | set tree expanded keys | Array<String> | - |
-|treeExpandAction | Tree open logic, optional: false \| `click` \| `doubleClick`, same as `expandAction` of `rc-tree` | string \| boolean | `click` |
-|treeCheckable | whether tree show checkbox (select callback will not fire) | bool | false |
-|treeCheckStrictly | check node precisely, parent and children nodes are not associated| bool | false |
-|filterTreeNode | whether filter treeNodes by input value. default filter by treeNode's treeNodeFilterProp prop's value | bool/Function(inputValue:string, treeNode:TreeNode) | Function |
-|treeNodeFilterProp | which prop value of treeNode will be used for filter if filterTreeNode return true | String | 'value' |
-|treeNodeLabelProp | which prop value of treeNode will render as content of select | String | 'title' |
-|treeData | treeNodes data Array, if set it then you need not to construct children TreeNode. (value should be unique across the whole array) | array<{value,label,children, [disabled,selectable]}> | [] |
-|treeDataSimpleMode | enable simple mode of treeData.(treeData should be like this: [{id:1, pId:0, value:'1', label:"test1",...},...], `pId` is parent node's id) | bool/object{id:'id', pId:'pId', rootPId:null} | false |
-|treeTitleRender | Custom render nodes | (nodeData: OptionType) => ReactNode |
-|loadData | load data asynchronously | function(node) | - |
-|getPopupContainer | container which popup select menu rendered into | function(trigger:Node):Node | function(){return document.body;} |
-|autoClearSearchValue | auto clear search input value when multiple select is selected/deselected | boolean | true |
-| suffixIcon | specify the select arrow icon | ReactNode \| (props: TreeProps) => ReactNode | - |
-| clearIcon | specify the clear icon | ReactNode \| (props: TreeProps) => ReactNode | - |
-| removeIcon | specify the remove icon | ReactNode \| (props: TreeProps) => ReactNode | - |
-|switcherIcon| specify the switcher icon | ReactNode \| (props: TreeProps) => ReactNode | - |
-|virtual| Disable virtual when `false` | false | - |
-
+| name                     | description                                                                                                                                                                         | type                                                                                                                                                                                                                           | default                           |
+| ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------- |
+| className                | additional css class of root dom node                                                                                                                                               | String                                                                                                                                                                                                                         | ''                                |
+| prefixCls                | prefix class                                                                                                                                                                        | String                                                                                                                                                                                                                         | ''                                |
+| animation                | dropdown animation name. only support slide-up now                                                                                                                                  | String                                                                                                                                                                                                                         | ''                                |
+| transitionName           | dropdown css animation name                                                                                                                                                         | String                                                                                                                                                                                                                         | ''                                |
+| choiceTransitionName     | css animation name for selected items at multiple mode                                                                                                                              | String                                                                                                                                                                                                                         | ''                                |
+| dropdownMatchSelectWidth | whether dropdown's with is same with select. Default set `min-width` same as input                                                                                                  | bool                                                                                                                                                                                                                           | true                              |
+| dropdownClassName        | additional className applied to dropdown                                                                                                                                            | String                                                                                                                                                                                                                         | -                                 |
+| dropdownStyle            | additional style applied to dropdown                                                                                                                                                | Object                                                                                                                                                                                                                         | {}                                |
+| onDropdownVisibleChange  | control dropdown visible                                                                                                                                                            | function                                                                                                                                                                                                                       | `() => { return true; }`          |
+| notFoundContent          | specify content to show when no result matches.                                                                                                                                     | String                                                                                                                                                                                                                         | 'Not Found'                       |
+| showSearch               | whether show search input in single mode                                                                                                                                            | bool                                                                                                                                                                                                                           | true                              |
+| allowClear               | whether allowClear                                                                                                                                                                  | bool                                                                                                                                                                                                                           | false                             |
+| maxTagTextLength         | max tag text length to show                                                                                                                                                         | number                                                                                                                                                                                                                         | -                                 |
+| maxTagCount              | max tag count to show                                                                                                                                                               | number                                                                                                                                                                                                                         | -                                 |
+| maxCount                 | Limit the maximum number of items that can be selected in multiple mode                                                                                                             | number                                                                                                                                                                                                                         | -                                 |
+| maxTagPlaceholder        | placeholder for omitted values                                                                                                                                                      | ReactNode/function(omittedValues)                                                                                                                                                                                              | -                                 |
+| multiple                 | whether multiple select (true when enable treeCheckable)                                                                                                                            | bool                                                                                                                                                                                                                           | false                             |
+| disabled                 | whether disabled select                                                                                                                                                             | bool                                                                                                                                                                                                                           | false                             |
+| searchValue              | work with `onSearch` to make search value controlled.                                                                                                                               | string                                                                                                                                                                                                                         | ''                                |
+| defaultValue             | initial selected treeNode(s)                                                                                                                                                        | same as value type                                                                                                                                                                                                             | -                                 |
+| value                    | current selected treeNode(s).                                                                                                                                                       | normal: String/Array<String>. labelInValue: {value:String,label:React.Node}/Array<{value,label}>. treeCheckStrictly(halfChecked default false): {value:String,label:React.Node, halfChecked}/Array<{value,label,halfChecked}>. | -                                 |
+| labelInValue             | whether to embed label in value, see above value type                                                                                                                               | Bool                                                                                                                                                                                                                           | false                             |
+| onChange                 | called when select treeNode or input value change                                                                                                                                   | function(value, label(null), extra)                                                                                                                                                                                            | -                                 |
+| onSelect                 | called when select treeNode                                                                                                                                                         | function(value, node, extra)                                                                                                                                                                                                   | -                                 |
+| onSearch                 | called when input changed                                                                                                                                                           | function                                                                                                                                                                                                                       | -                                 |
+| onTreeExpand             | called when tree node expand                                                                                                                                                        | function(expandedKeys)                                                                                                                                                                                                         | -                                 |
+| onPopupScroll            | called when popup scroll                                                                                                                                                            | function(event)                                                                                                                                                                                                                | -                                 |
+| showCheckedStrategy      | `TreeSelect.SHOW_ALL`: show all checked treeNodes (Include parent treeNode). `TreeSelect.SHOW_PARENT`: show checked treeNodes (Just show parent treeNode). Default just show child. | enum{TreeSelect.SHOW_ALL, TreeSelect.SHOW_PARENT, TreeSelect.SHOW_CHILD }                                                                                                                                                      | TreeSelect.SHOW_CHILD             |
+| treeIcon                 | show tree icon                                                                                                                                                                      | bool                                                                                                                                                                                                                           | false                             |
+| treeLine                 | show tree line                                                                                                                                                                      | bool                                                                                                                                                                                                                           | false                             |
+| treeDefaultExpandAll     | default expand all treeNode                                                                                                                                                         | bool                                                                                                                                                                                                                           | false                             |
+| treeDefaultExpandedKeys  | default expanded treeNode keys                                                                                                                                                      | Array<String>                                                                                                                                                                                                                  | -                                 |
+| treeExpandedKeys         | set tree expanded keys                                                                                                                                                              | Array<String>                                                                                                                                                                                                                  | -                                 |
+| treeExpandAction         | Tree open logic, optional: false \| `click` \| `doubleClick`, same as `expandAction` of `rc-tree`                                                                                   | string \| boolean                                                                                                                                                                                                              | `click`                           |
+| treeCheckable            | whether tree show checkbox (select callback will not fire)                                                                                                                          | bool                                                                                                                                                                                                                           | false                             |
+| treeCheckStrictly        | check node precisely, parent and children nodes are not associated                                                                                                                  | bool                                                                                                                                                                                                                           | false                             |
+| filterTreeNode           | whether filter treeNodes by input value. default filter by treeNode's treeNodeFilterProp prop's value                                                                               | bool/Function(inputValue:string, treeNode:TreeNode)                                                                                                                                                                            | Function                          |
+| treeNodeFilterProp       | which prop value of treeNode will be used for filter if filterTreeNode return true                                                                                                  | String                                                                                                                                                                                                                         | 'value'                           |
+| treeNodeLabelProp        | which prop value of treeNode will render as content of select                                                                                                                       | String                                                                                                                                                                                                                         | 'title'                           |
+| treeData                 | treeNodes data Array, if set it then you need not to construct children TreeNode. (value should be unique across the whole array)                                                   | array<{value,label,children, [disabled,selectable]}>                                                                                                                                                                           | []                                |
+| treeDataSimpleMode       | enable simple mode of treeData.(treeData should be like this: [{id:1, pId:0, value:'1', label:"test1",...},...], `pId` is parent node's id)                                         | bool/object{id:'id', pId:'pId', rootPId:null}                                                                                                                                                                                  | false                             |
+| treeTitleRender          | Custom render nodes                                                                                                                                                                 | (nodeData: OptionType) => ReactNode                                                                                                                                                                                            |
+| loadData                 | load data asynchronously                                                                                                                                                            | function(node)                                                                                                                                                                                                                 | -                                 |
+| getPopupContainer        | container which popup select menu rendered into                                                                                                                                     | function(trigger:Node):Node                                                                                                                                                                                                    | function(){return document.body;} |
+| autoClearSearchValue     | auto clear search input value when multiple select is selected/deselected                                                                                                           | boolean                                                                                                                                                                                                                        | true                              |
+| suffixIcon               | specify the select arrow icon                                                                                                                                                       | ReactNode \| (props: TreeProps) => ReactNode                                                                                                                                                                                   | -                                 |
+| clearIcon                | specify the clear icon                                                                                                                                                              | ReactNode \| (props: TreeProps) => ReactNode                                                                                                                                                                                   | -                                 |
+| removeIcon               | specify the remove icon                                                                                                                                                             | ReactNode \| (props: TreeProps) => ReactNode                                                                                                                                                                                   | -                                 |
+| switcherIcon             | specify the switcher icon                                                                                                                                                           | ReactNode \| (props: TreeProps) => ReactNode                                                                                                                                                                                   | -                                 |
+| virtual                  | Disable virtual when `false`                                                                                                                                                        | false                                                                                                                                                                                                                          | -                                 |
 
 ### TreeNode props
-> note: you'd better to use `treeData` instead of using TreeNode.
 
-| name     | description    | type     | default      |
-|----------|----------------|----------|--------------|
-|disabled | disable treeNode | bool | false |
-|key | it's value must be unique across the tree's all TreeNode, you must set it  | String | - |
-|value | default as treeNodeFilterProp (be unique across the tree's all TreeNode) | String | '' |
-|title | tree/subTree's title | String/element | '---' |
-|isLeaf | whether it's leaf node | bool | false |
+> note: you'd better to use `treeData` instead of using TreeNode.
 
+| name     | description                                                               | type           | default |
+| -------- | ------------------------------------------------------------------------- | -------------- | ------- |
+| disabled | disable treeNode                                                          | bool           | false   |
+| key      | it's value must be unique across the tree's all TreeNode, you must set it | String         | -       |
+| value    | default as treeNodeFilterProp (be unique across the tree's all TreeNode)  | String         | ''      |
+| title    | tree/subTree's title                                                      | String/element | '---'   |
+| isLeaf   | whether it's leaf node                                                    | bool           | false   |
 
 ## note
+
 1. Optimization tips(when there are large amounts of data, like more than 5000 nodes)
-    - Do not Expand all nodes.
-    - Recommend not exist many `TreeSelect` components in a page at the same time.
-    - Recommend not use `treeCheckable` mode, or use `treeCheckStrictly`.
+   - Do not Expand all nodes.
+   - Recommend not exist many `TreeSelect` components in a page at the same time.
+   - Recommend not use `treeCheckable` mode, or use `treeCheckStrictly`.
 2. In `treeCheckable` mode, It has the same effect when click `x`(node in Selection box) or uncheck in the treeNode(in dropdown panel), but the essence is not the same. So, even if both of them trigger `onChange` method, but the parameters (the third parameter) are different. (中文:在`treeCheckable`模式下,已选择节点上的`x`删除操作、和相应 treeNode 节点上 checkbox 的 uncheck 操作,最终效果相同,但本质不一样。前者跟弹出的 tree 组件可以“毫无关系”(例如 dropdown 没展开过,tree 也就没渲染好),而后者是 tree 组件上的节点 uncheck 事件。所以、即便两者都会触发`onChange`方法、但它们的参数(第三个参数)是不同的。)
 
 ## Test Case
@@ -137,4 +137,4 @@ http://localhost:8000/node_modules/rc-server/node_modules/node-jscover/lib/front
 
 ## License
 
-rc-tree-select is released under the MIT license.
\ No newline at end of file
+rc-tree-select is released under the MIT license.
diff --git a/docs/demo/mutiple-with-maxCount.md b/docs/demo/mutiple-with-maxCount.md
new file mode 100644
index 00000000..2df96692
--- /dev/null
+++ b/docs/demo/mutiple-with-maxCount.md
@@ -0,0 +1,8 @@
+---
+title: mutiple-with-maxCount
+nav:
+  title: Demo
+  path: /demo
+---
+
+<code src="../../examples/mutiple-with-maxCount.tsx"></code>
diff --git a/examples/mutiple-with-maxCount.tsx b/examples/mutiple-with-maxCount.tsx
new file mode 100644
index 00000000..41a9b77e
--- /dev/null
+++ b/examples/mutiple-with-maxCount.tsx
@@ -0,0 +1,94 @@
+import React, { useState } from 'react';
+import TreeSelect from '../src';
+
+export default () => {
+  const [value, setValue] = useState<string[]>(['1']);
+  const [checkValue, setCheckValue] = useState<string[]>(['1']);
+
+  const treeData = [
+    {
+      key: '1',
+      value: '1',
+      title: '1',
+      children: [
+        {
+          key: '1-1',
+          value: '1-1',
+          title: '1-1',
+        },
+        {
+          key: '1-2',
+          value: '1-2',
+          title: '1-2',
+        },
+        {
+          key: '1-3',
+          value: '1-3',
+          title: '1-3',
+        },
+      ],
+    },
+    {
+      key: '2',
+      value: '2',
+      title: '2',
+    },
+    {
+      key: '3',
+      value: '3',
+      title: '3',
+    },
+    {
+      key: '4',
+      value: '4',
+      title: '4',
+    },
+  ];
+
+  const onChange = (val: string[]) => {
+    setValue(val);
+  };
+
+  const onCheckChange = (val: string[]) => {
+    setCheckValue(val);
+  };
+
+  return (
+    <>
+      <h2>multiple with maxCount</h2>
+      <TreeSelect
+        style={{ width: 300 }}
+        fieldNames={{ value: 'value', label: 'title' }}
+        multiple
+        maxCount={3}
+        treeData={treeData}
+      />
+
+      <h2>checkable with maxCount</h2>
+      <TreeSelect
+        style={{ width: 300 }}
+        multiple
+        treeCheckable
+        // showCheckedStrategy="SHOW_ALL"
+        showCheckedStrategy="SHOW_PARENT"
+        // showCheckedStrategy="SHOW_CHILD"
+        maxCount={4}
+        treeData={treeData}
+        onChange={onChange}
+        value={value}
+      />
+
+      <h2>checkable with maxCount and treeCheckStrictly</h2>
+      <TreeSelect
+        style={{ width: 300 }}
+        multiple
+        treeCheckable
+        treeCheckStrictly
+        maxCount={3}
+        treeData={treeData}
+        onChange={onCheckChange}
+        value={checkValue}
+      />
+    </>
+  );
+};
diff --git a/package.json b/package.json
index 89bf0997..ecc3e84a 100644
--- a/package.json
+++ b/package.json
@@ -47,7 +47,7 @@
     "@babel/runtime": "^7.25.7",
     "classnames": "2.x",
     "rc-select": "~14.16.2",
-    "rc-tree": "~5.10.1",
+    "rc-tree": "~5.11.0",
     "rc-util": "^5.43.0"
   },
   "devDependencies": {
diff --git a/src/OptionList.tsx b/src/OptionList.tsx
index bbfa37f9..b49e552e 100644
--- a/src/OptionList.tsx
+++ b/src/OptionList.tsx
@@ -2,14 +2,16 @@ import { useBaseProps } from 'rc-select';
 import type { RefOptionListProps } from 'rc-select/lib/OptionList';
 import type { TreeProps } from 'rc-tree';
 import Tree from 'rc-tree';
+import { UnstableContext } from 'rc-tree';
 import type { EventDataNode, ScrollTo } from 'rc-tree/lib/interface';
 import KeyCode from 'rc-util/lib/KeyCode';
 import useMemo from 'rc-util/lib/hooks/useMemo';
 import * as React from 'react';
 import LegacyContext from './LegacyContext';
 import TreeSelectContext from './TreeSelectContext';
-import type { Key, SafeKey } from './interface';
+import type { DataNode, Key, SafeKey } from './interface';
 import { getAllKeys, isCheckDisabled } from './utils/valueUtil';
+import { useEvent } from 'rc-util';
 
 const HIDDEN_STYLE = {
   width: 0,
@@ -45,6 +47,8 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
     treeExpandAction,
     treeTitleRender,
     onPopupScroll,
+    displayValues,
+    isOverMaxCount,
   } = React.useContext(TreeSelectContext);
 
   const {
@@ -76,6 +80,11 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
     (prev, next) => next[0] && prev[1] !== next[1],
   );
 
+  const memoRawValues = React.useMemo(
+    () => (displayValues || []).map(v => v.value),
+    [displayValues],
+  );
+
   // ========================== Values ==========================
   const mergedCheckedKeys = React.useMemo(() => {
     if (!checkable) {
@@ -154,6 +163,10 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
     // eslint-disable-next-line react-hooks/exhaustive-deps
   }, [searchValue]);
 
+  const nodeDisabled = useEvent((node: DataNode) => {
+    return isOverMaxCount && !memoRawValues.includes(node[fieldNames.value]);
+  });
+
   // ========================== Get First Selectable Node ==========================
   const getFirstMatchingNode = (nodes: EventDataNode<any>[]): EventDataNode<any> | null => {
     for (const node of nodes) {
@@ -221,8 +234,9 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
         // >>> Select item
         case KeyCode.ENTER: {
           if (activeEntity) {
+            const isNodeDisabled = nodeDisabled(activeEntity.node);
             const { selectable, value, disabled } = activeEntity?.node || {};
-            if (selectable !== false && !disabled) {
+            if (selectable !== false && !disabled && !isNodeDisabled) {
               onInternalSelect(null, {
                 node: { key: activeKey },
                 selected: !checkedKeys.includes(value),
@@ -276,42 +290,43 @@ const OptionList: React.ForwardRefRenderFunction<ReviseRefOptionListProps> = (_,
           {activeEntity.node.value}
         </span>
       )}
-
-      <Tree
-        ref={treeRef}
-        focusable={false}
-        prefixCls={`${prefixCls}-tree`}
-        treeData={memoTreeData}
-        height={listHeight}
-        itemHeight={listItemHeight}
-        itemScrollOffset={listItemScrollOffset}
-        virtual={virtual !== false && dropdownMatchSelectWidth !== false}
-        multiple={multiple}
-        icon={treeIcon}
-        showIcon={showTreeIcon}
-        switcherIcon={switcherIcon}
-        showLine={treeLine}
-        loadData={syncLoadData}
-        motion={treeMotion}
-        activeKey={activeKey}
-        // We handle keys by out instead tree self
-        checkable={checkable}
-        checkStrictly
-        checkedKeys={mergedCheckedKeys}
-        selectedKeys={!checkable ? checkedKeys : []}
-        defaultExpandAll={treeDefaultExpandAll}
-        titleRender={treeTitleRender}
-        {...treeProps}
-        // Proxy event out
-        onActiveChange={setActiveKey}
-        onSelect={onInternalSelect}
-        onCheck={onInternalSelect}
-        onExpand={onInternalExpand}
-        onLoad={onTreeLoad}
-        filterTreeNode={filterTreeNode}
-        expandAction={treeExpandAction}
-        onScroll={onPopupScroll}
-      />
+      <UnstableContext.Provider value={{ nodeDisabled }}>
+        <Tree
+          ref={treeRef}
+          focusable={false}
+          prefixCls={`${prefixCls}-tree`}
+          treeData={memoTreeData}
+          height={listHeight}
+          itemHeight={listItemHeight}
+          itemScrollOffset={listItemScrollOffset}
+          virtual={virtual !== false && dropdownMatchSelectWidth !== false}
+          multiple={multiple}
+          icon={treeIcon}
+          showIcon={showTreeIcon}
+          switcherIcon={switcherIcon}
+          showLine={treeLine}
+          loadData={syncLoadData}
+          motion={treeMotion}
+          activeKey={activeKey}
+          // We handle keys by out instead tree self
+          checkable={checkable}
+          checkStrictly
+          checkedKeys={mergedCheckedKeys}
+          selectedKeys={!checkable ? checkedKeys : []}
+          defaultExpandAll={treeDefaultExpandAll}
+          titleRender={treeTitleRender}
+          {...treeProps}
+          // Proxy event out
+          onActiveChange={setActiveKey}
+          onSelect={onInternalSelect}
+          onCheck={onInternalSelect}
+          onExpand={onInternalExpand}
+          onLoad={onTreeLoad}
+          filterTreeNode={filterTreeNode}
+          expandAction={treeExpandAction}
+          onScroll={onPopupScroll}
+        />
+      </UnstableContext.Provider>
     </div>
   );
 };
diff --git a/src/TreeSelect.tsx b/src/TreeSelect.tsx
index db63f710..c46f49a8 100644
--- a/src/TreeSelect.tsx
+++ b/src/TreeSelect.tsx
@@ -72,6 +72,7 @@ export interface TreeSelectProps<ValueType = any, OptionType extends DataNode =
   treeCheckable?: boolean | React.ReactNode;
   treeCheckStrictly?: boolean;
   labelInValue?: boolean;
+  maxCount?: number;
 
   // >>> Data
   treeData?: OptionType[];
@@ -136,6 +137,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
     treeCheckable,
     treeCheckStrictly,
     labelInValue,
+    maxCount,
 
     // FieldNames
     fieldNames,
@@ -413,6 +415,20 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
       extra: { triggerValue?: SafeKey; selected?: boolean },
       source: SelectSource,
     ) => {
+      const formattedKeyList = formatStrategyValues(
+        newRawValues,
+        mergedShowCheckedStrategy,
+        keyEntities,
+        mergedFieldNames,
+      );
+
+      // if multiple and maxCount is set, check if exceed maxCount
+      if (mergedMultiple && maxCount !== undefined) {
+        if (formattedKeyList.length > maxCount) {
+          return;
+        }
+      }
+
       const labeledValues = convert2LabelValues(newRawValues);
       setInternalValue(labeledValues);
 
@@ -425,12 +441,6 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
       if (onChange) {
         let eventValues: SafeKey[] = newRawValues;
         if (treeConduction) {
-          const formattedKeyList = formatStrategyValues(
-            newRawValues,
-            mergedShowCheckedStrategy,
-            keyEntities,
-            mergedFieldNames,
-          );
           eventValues = formattedKeyList.map(key => {
             const entity = valueEntities.get(key);
             return entity ? entity.node[mergedFieldNames.value] : key;
@@ -558,6 +568,7 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
       onDeselect,
       rawCheckedValues,
       rawHalfCheckedValues,
+      maxCount,
     ],
   );
 
@@ -596,8 +607,11 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
   });
 
   // ========================== Context ===========================
-  const treeSelectContext = React.useMemo<TreeSelectContextProps>(
-    () => ({
+  const isOverMaxCount =
+    mergedMultiple && maxCount !== undefined && cachedDisplayValues?.length >= maxCount;
+
+  const treeSelectContext = React.useMemo<TreeSelectContextProps>(() => {
+    return {
       virtual,
       dropdownMatchSelectWidth,
       listHeight,
@@ -609,21 +623,25 @@ const TreeSelect = React.forwardRef<BaseSelectRef, TreeSelectProps>((props, ref)
       treeExpandAction,
       treeTitleRender,
       onPopupScroll,
-    }),
-    [
-      virtual,
-      dropdownMatchSelectWidth,
-      listHeight,
-      listItemHeight,
-      listItemScrollOffset,
-      filteredTreeData,
-      mergedFieldNames,
-      onOptionSelect,
-      treeExpandAction,
-      treeTitleRender,
-      onPopupScroll,
-    ],
-  );
+      displayValues: cachedDisplayValues,
+      isOverMaxCount,
+    };
+  }, [
+    virtual,
+    dropdownMatchSelectWidth,
+    listHeight,
+    listItemHeight,
+    listItemScrollOffset,
+    filteredTreeData,
+    mergedFieldNames,
+    onOptionSelect,
+    treeExpandAction,
+    treeTitleRender,
+    onPopupScroll,
+    maxCount,
+    cachedDisplayValues,
+    mergedMultiple,
+  ]);
 
   // ======================= Legacy Context =======================
   const legacyContext = React.useMemo(
diff --git a/src/TreeSelectContext.ts b/src/TreeSelectContext.ts
index b0aff525..2d335e4b 100644
--- a/src/TreeSelectContext.ts
+++ b/src/TreeSelectContext.ts
@@ -1,6 +1,6 @@
 import * as React from 'react';
 import type { ExpandAction } from 'rc-tree/lib/Tree';
-import type { DataNode, FieldNames, Key } from './interface';
+import type { DataNode, FieldNames, Key, LabeledValueType } from './interface';
 
 export interface TreeSelectContextProps {
   virtual?: boolean;
@@ -14,6 +14,8 @@ export interface TreeSelectContextProps {
   treeExpandAction?: ExpandAction;
   treeTitleRender?: (node: any) => React.ReactNode;
   onPopupScroll?: React.UIEventHandler<HTMLDivElement>;
+  displayValues?: LabeledValueType[];
+  isOverMaxCount?: boolean;
 }
 
 const TreeSelectContext = React.createContext<TreeSelectContextProps>(null as any);
diff --git a/tests/Select.SearchInput.spec.js b/tests/Select.SearchInput.spec.js
index 77fced28..cd2d15c3 100644
--- a/tests/Select.SearchInput.spec.js
+++ b/tests/Select.SearchInput.spec.js
@@ -221,14 +221,22 @@ describe('TreeSelect.SearchInput', () => {
       const input = getByRole('combobox');
       fireEvent.change(input, { target: { value: '1' } });
       fireEvent.keyDown(input, { keyCode: KeyCode.ENTER });
+      fireEvent.keyUp(input, { keyCode: KeyCode.ENTER });
       expect(onSelect).toHaveBeenCalledWith('1', expect.anything());
       onSelect.mockReset();
 
       // Search disabled node and press enter, should not select
       fireEvent.change(input, { target: { value: '2' } });
       fireEvent.keyDown(input, { keyCode: KeyCode.ENTER });
+      fireEvent.keyUp(input, { keyCode: KeyCode.ENTER });
       expect(onSelect).not.toHaveBeenCalled();
       onSelect.mockReset();
+
+      // Search and press enter, should select first matched non-disabled node
+      fireEvent.change(input, { target: { value: '3' } });
+      fireEvent.keyDown(input, { keyCode: KeyCode.ENTER });
+      fireEvent.keyUp(input, { keyCode: KeyCode.ENTER });
+      expect(onSelect).toHaveBeenCalledWith('3', expect.anything());
     });
 
     it('should not select node when no matches found', () => {
diff --git a/tests/Select.maxCount.spec.tsx b/tests/Select.maxCount.spec.tsx
new file mode 100644
index 00000000..79fe48b8
--- /dev/null
+++ b/tests/Select.maxCount.spec.tsx
@@ -0,0 +1,374 @@
+import { render, fireEvent, within } from '@testing-library/react';
+import KeyCode from 'rc-util/lib/KeyCode';
+import { keyDown, keyUp } from './util';
+import React from 'react';
+import TreeSelect from '../src';
+
+describe('TreeSelect.maxCount', () => {
+  const treeData = [
+    { key: '0', value: '0', title: '0 label' },
+    { key: '1', value: '1', title: '1 label' },
+    { key: '2', value: '2', title: '2 label' },
+    { key: '3', value: '3', title: '3 label' },
+  ];
+
+  const renderTreeSelect = (props?: any) => {
+    return render(<TreeSelect multiple maxCount={2} treeData={treeData} open {...props} />);
+  };
+
+  const selectOptions = (container, optionTexts) => {
+    const dropdownList = container.querySelector('.rc-tree-select-dropdown');
+    optionTexts.forEach(text => {
+      fireEvent.click(within(dropdownList).getByText(text));
+    });
+  };
+
+  it('should disable unselected options when selection reaches maxCount', () => {
+    const { container } = renderTreeSelect();
+
+    selectOptions(container, ['0 label', '1 label']);
+
+    // Check if third and fourth options are disabled
+    const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement;
+    const option3 = within(dropdownList).getByText('2 label');
+    const option4 = within(dropdownList).getByText('3 label');
+
+    expect(option3.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled');
+    expect(option4.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled');
+  });
+
+  it('should allow deselecting options after reaching maxCount', () => {
+    const { container } = renderTreeSelect();
+    const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement;
+
+    selectOptions(container, ['0 label', '1 label']);
+
+    // Try selecting third option, should be disabled
+    const option3 = within(dropdownList).getByText('2 label');
+    fireEvent.click(option3);
+    expect(option3.closest('div')).toHaveClass('rc-tree-select-tree-treenode-disabled');
+
+    // Deselect first option
+    fireEvent.click(within(dropdownList).getByText('0 label'));
+    expect(within(dropdownList).queryByText('0 label')).toBeInTheDocument();
+
+    // Now should be able to select third option
+    fireEvent.click(option3);
+    expect(option3.closest('div')).not.toHaveClass('rc-tree-select-tree-treenode-disabled');
+  });
+
+  it('should not trigger onChange when trying to select beyond maxCount', () => {
+    const handleChange = jest.fn();
+    const { container } = renderTreeSelect({ onChange: handleChange });
+
+    selectOptions(container, ['0 label', '1 label']);
+    expect(handleChange).toHaveBeenCalledTimes(2);
+
+    // Try selecting third option
+    const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement;
+    fireEvent.click(within(dropdownList).getByText('2 label'));
+    expect(handleChange).toHaveBeenCalledTimes(2); // Should not increase
+  });
+
+  it('should not affect deselection operations when maxCount is reached', () => {
+    const handleChange = jest.fn();
+    const { container } = renderTreeSelect({ onChange: handleChange });
+
+    selectOptions(container, ['0 label', '1 label']);
+    expect(handleChange).toHaveBeenCalledTimes(2);
+
+    // Deselect first option
+    const dropdownList = container.querySelector('.rc-tree-select-dropdown') as HTMLElement;
+    fireEvent.click(within(dropdownList).getByText('0 label'));
+    expect(handleChange).toHaveBeenCalledTimes(3);
+
+    // Should be able to select third option
+    fireEvent.click(within(dropdownList).getByText('2 label'));
+    expect(handleChange).toHaveBeenCalledTimes(4);
+  });
+
+  it('should not allow any selection when maxCount is 0', () => {
+    const handleChange = jest.fn();
+    const { container } = renderTreeSelect({ maxCount: 0, onChange: handleChange });
+
+    selectOptions(container, ['0 label', '1 label']);
+    expect(handleChange).not.toHaveBeenCalled();
+  });
+
+  it('should not limit selection when maxCount is greater than number of options', () => {
+    const handleChange = jest.fn();
+    const { container } = renderTreeSelect({ maxCount: 5, onChange: handleChange });
+
+    selectOptions(container, ['0 label', '1 label', '2 label', '3 label']);
+    expect(handleChange).toHaveBeenCalledTimes(4);
+  });
+
+  it('should respect maxCount when checking parent node in treeCheckable mode', () => {
+    const treeData = [
+      {
+        key: '0',
+        value: '0',
+        title: 'parent',
+        children: [
+          { key: '0-0', value: '0-0', title: 'child 1' },
+          { key: '0-1', value: '0-1', title: 'child 2' },
+          { key: '0-2', value: '0-2', title: 'child 3' },
+        ],
+      },
+    ];
+
+    const handleChange = jest.fn();
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        treeCheckable
+        multiple
+        maxCount={2}
+        onChange={handleChange}
+        open
+      />,
+    );
+
+    // Try to check parent node which would select all children
+    const checkbox = container.querySelector('.rc-tree-select-tree-checkbox');
+    fireEvent.click(checkbox);
+
+    // onChange should not be called since it would exceed maxCount
+    expect(handleChange).not.toHaveBeenCalled();
+
+    // Parent node should still be unchecked
+    expect(checkbox).not.toHaveClass('rc-tree-select-tree-checkbox-checked');
+  });
+});
+
+describe('TreeSelect.maxCount keyboard operations', () => {
+  const treeData = [
+    { key: '0', value: '0', title: '0 label' },
+    { key: '1', value: '1', title: '1 label' },
+    { key: '2', value: '2', title: '2 label' },
+  ];
+
+  it('keyboard operations should not exceed maxCount limit', () => {
+    const onSelect = jest.fn();
+    const { container } = render(
+      <TreeSelect treeData={treeData} multiple open maxCount={2} onSelect={onSelect} />,
+    );
+
+    const input = container.querySelector('input');
+
+    keyDown(input, KeyCode.ENTER);
+    keyUp(input, KeyCode.ENTER);
+
+    expect(onSelect).toHaveBeenCalledWith('0', expect.anything());
+
+    keyDown(input, KeyCode.DOWN);
+    keyDown(input, KeyCode.ENTER);
+    keyUp(input, KeyCode.ENTER);
+
+    expect(onSelect).toHaveBeenCalledWith('1', expect.anything());
+
+    keyDown(input, KeyCode.DOWN);
+    keyDown(input, KeyCode.ENTER);
+    keyUp(input, KeyCode.ENTER);
+  });
+
+  it('when maxCount is reached, the option should be disabled', () => {
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        multiple
+        open
+        treeDefaultExpandAll
+        maxCount={2}
+        value={['0', '1']}
+      />,
+    );
+
+    // verify that the third option is disabled
+    expect(container.querySelector('.rc-tree-select-tree-treenode-disabled')?.textContent).toBe(
+      '2 label',
+    );
+  });
+
+  it('should be able to unselect after reaching maxCount', () => {
+    const { container } = render(
+      <TreeSelect treeData={treeData} multiple open maxCount={3} defaultValue={['0', '1', '2']} />,
+    );
+
+    const input = container.querySelector('input');
+
+    // cancel first selection
+    keyDown(input, KeyCode.ENTER);
+    keyUp(input, KeyCode.ENTER);
+
+    // verify only two options are selected
+    expect(container.querySelectorAll('.rc-tree-select-tree-treenode-selected')).toHaveLength(2);
+  });
+});
+
+describe('TreeSelect.maxCount with different strategies', () => {
+  const treeData = [
+    {
+      key: '0',
+      value: '0',
+      title: 'parent',
+      children: [
+        { key: '0-0', value: '0-0', title: 'child 1' },
+        { key: '0-1', value: '0-1', title: 'child 2' },
+        { key: '0-2', value: '0-2', title: 'child 3' },
+      ],
+    },
+  ];
+
+  it('should respect maxCount with SHOW_PARENT strategy', () => {
+    const handleChange = jest.fn();
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        treeCheckable
+        treeDefaultExpandAll
+        multiple
+        maxCount={1}
+        showCheckedStrategy={TreeSelect.SHOW_PARENT}
+        onChange={handleChange}
+        open
+      />,
+    );
+
+    // Select parent node - should work as it only shows as one option
+    const parentCheckbox = within(container).getByText('parent');
+    fireEvent.click(parentCheckbox);
+    expect(handleChange).toHaveBeenCalledTimes(1);
+  });
+
+  it('should respect maxCount with SHOW_CHILD strategy', () => {
+    const handleChange = jest.fn();
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        treeCheckable
+        treeDefaultExpandAll
+        multiple
+        maxCount={2}
+        showCheckedStrategy={TreeSelect.SHOW_CHILD}
+        onChange={handleChange}
+        open
+      />,
+    );
+
+    // Select parent node - should not work as it would show three children
+    const parentCheckbox = within(container).getByText('parent');
+    fireEvent.click(parentCheckbox);
+    expect(handleChange).not.toHaveBeenCalled();
+
+    // Select individual children - should work until maxCount
+    const childCheckboxes = within(container).getAllByText(/child/);
+    fireEvent.click(childCheckboxes[0]); // first child
+    fireEvent.click(childCheckboxes[1]); // second child
+    expect(handleChange).toHaveBeenCalledTimes(2);
+
+    // Try to select third child - should not work
+    fireEvent.click(childCheckboxes[2]);
+    expect(handleChange).toHaveBeenCalledTimes(2);
+  });
+
+  it('should respect maxCount with SHOW_ALL strategy', () => {
+    const handleChange = jest.fn();
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        treeCheckable
+        treeDefaultExpandAll
+        multiple
+        maxCount={2}
+        showCheckedStrategy={TreeSelect.SHOW_ALL}
+        onChange={handleChange}
+        open
+      />,
+    );
+
+    // Select parent node - should not work as it would show both parent and children
+    const parentCheckbox = within(container).getByText('parent');
+    fireEvent.click(parentCheckbox);
+    expect(handleChange).not.toHaveBeenCalled();
+
+    // Select individual children
+    const childCheckboxes = within(container).getAllByText(/child/);
+    fireEvent.click(childCheckboxes[0]);
+    fireEvent.click(childCheckboxes[1]);
+    expect(handleChange).toHaveBeenCalledTimes(2);
+  });
+});
+
+describe('TreeSelect.maxCount with treeCheckStrictly', () => {
+  const treeData = [
+    {
+      key: '0',
+      value: '0',
+      title: 'parent',
+      children: [
+        { key: '0-0', value: '0-0', title: 'child 1' },
+        { key: '0-1', value: '0-1', title: 'child 2' },
+      ],
+    },
+  ];
+
+  it('should count parent and children separately when treeCheckStrictly is true', () => {
+    const handleChange = jest.fn();
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        treeCheckable
+        treeCheckStrictly
+        treeDefaultExpandAll
+        multiple
+        maxCount={2}
+        onChange={handleChange}
+        open
+      />,
+    );
+
+    // Select parent and one child - should work as they are counted separately
+    const parentCheckbox = within(container).getByText('parent');
+    const checkboxes = within(container).getAllByText(/child/);
+    fireEvent.click(parentCheckbox);
+    fireEvent.click(checkboxes[0]); // first child
+    expect(handleChange).toHaveBeenCalledTimes(2);
+
+    // Try to select second child - should not work as maxCount is reached
+    fireEvent.click(checkboxes[1]);
+    expect(handleChange).toHaveBeenCalledTimes(2);
+  });
+
+  it('should allow deselecting when maxCount is reached', () => {
+    const handleChange = jest.fn();
+    const { container } = render(
+      <TreeSelect
+        treeData={treeData}
+        treeCheckable
+        treeCheckStrictly
+        treeDefaultExpandAll
+        multiple
+        maxCount={2}
+        onChange={handleChange}
+        open
+      />,
+    );
+
+    const parentCheckbox = within(container).getByText('parent');
+    const checkboxes = within(container).getAllByText(/child/);
+
+    // Select parent and first child
+    fireEvent.click(parentCheckbox);
+    fireEvent.click(checkboxes[0]);
+    expect(handleChange).toHaveBeenCalledTimes(2);
+
+    // Deselect parent
+    fireEvent.click(parentCheckbox);
+    expect(handleChange).toHaveBeenCalledTimes(3);
+
+    // Now should be able to select second child
+    fireEvent.click(checkboxes[1]);
+    expect(handleChange).toHaveBeenCalledTimes(4);
+  });
+});
diff --git a/tests/Select.multiple.spec.js b/tests/Select.multiple.spec.js
index eba8a620..5f2cebca 100644
--- a/tests/Select.multiple.spec.js
+++ b/tests/Select.multiple.spec.js
@@ -1,5 +1,5 @@
 /* eslint-disable no-undef */
-import { render } from '@testing-library/react';
+import { render, fireEvent, within } from '@testing-library/react';
 import { mount } from 'enzyme';
 import KeyCode from 'rc-util/lib/KeyCode';
 import React from 'react';
@@ -32,7 +32,10 @@ describe('TreeSelect.multiple', () => {
 
   it('remove by backspace key', () => {
     const wrapper = mount(createSelect({ defaultValue: ['0', '1'] }));
-    wrapper.find('input').first().simulate('keyDown', { which: KeyCode.BACKSPACE, key: 'Backspace' });
+    wrapper
+      .find('input')
+      .first()
+      .simulate('keyDown', { which: KeyCode.BACKSPACE, key: 'Backspace' });
     expect(wrapper.getSelection()).toHaveLength(1);
     expect(wrapper.getSelection(0).text()).toBe('label0');
   });
@@ -59,9 +62,15 @@ describe('TreeSelect.multiple', () => {
       }
     }
     const wrapper = mount(<App />);
-    wrapper.find('input').first().simulate('keyDown', { which: KeyCode.BACKSPACE, key: 'Backspace' });
+    wrapper
+      .find('input')
+      .first()
+      .simulate('keyDown', { which: KeyCode.BACKSPACE, key: 'Backspace' });
     wrapper.selectNode(1);
-    wrapper.find('input').first().simulate('keyDown', { which: KeyCode.BACKSPACE, key: 'Backspace' });
+    wrapper
+      .find('input')
+      .first()
+      .simulate('keyDown', { which: KeyCode.BACKSPACE, key: 'Backspace' });
     expect(wrapper.getSelection()).toHaveLength(1);
     expect(wrapper.getSelection(0).text()).toBe('label0');
   });
@@ -337,9 +346,7 @@ describe('TreeSelect.multiple', () => {
       />,
     );
 
-    const values = Array.from(
-      container.querySelectorAll('.rc-tree-select-selection-item-content'),
-    ); //.map(ele => ele.textContent);
+    const values = Array.from(container.querySelectorAll('.rc-tree-select-selection-item-content')); //.map(ele => ele.textContent);
 
     expect(values).toHaveLength(0);
 
@@ -347,5 +354,4 @@ describe('TreeSelect.multiple', () => {
     expect(placeholder).toBeTruthy();
     expect(placeholder.textContent).toBe('Fake placeholder');
   });
-
 });
diff --git a/tests/__snapshots__/Select.checkable.spec.tsx.snap b/tests/__snapshots__/Select.checkable.spec.tsx.snap
index d13b495b..7ee92e82 100644
--- a/tests/__snapshots__/Select.checkable.spec.tsx.snap
+++ b/tests/__snapshots__/Select.checkable.spec.tsx.snap
@@ -142,7 +142,6 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -167,6 +166,7 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -179,9 +179,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-checkbox-checked rc-tree-select-tree-treenode-active rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -191,7 +192,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="true"
+                        aria-label="Select 0"
                         class="rc-tree-select-tree-checkbox rc-tree-select-tree-checkbox-checked"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -208,9 +212,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-checkbox-checked rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -224,7 +229,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="true"
+                        aria-label="Select 0-0"
                         class="rc-tree-select-tree-checkbox rc-tree-select-tree-checkbox-checked"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -241,9 +249,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="false"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-checkbox-checked rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -260,7 +269,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 1
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher-noop"
                       />
                       <span
+                        aria-checked="true"
+                        aria-label="Select 0-0-0"
                         class="rc-tree-select-tree-checkbox rc-tree-select-tree-checkbox-checked"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-normal"
@@ -352,7 +364,6 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -377,6 +388,7 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -389,9 +401,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-active rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -401,7 +414,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="false"
+                        aria-label="Select 0"
                         class="rc-tree-select-tree-checkbox"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -418,9 +434,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -434,7 +451,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="false"
+                        aria-label="Select 0-0"
                         class="rc-tree-select-tree-checkbox"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -451,9 +471,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="false"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -470,7 +491,10 @@ exports[`TreeSelect.checkable uncheck remove by selector not treeCheckStrictly 2
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher-noop"
                       />
                       <span
+                        aria-checked="false"
+                        aria-label="Select 0-0-0"
                         class="rc-tree-select-tree-checkbox"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-normal"
@@ -640,7 +664,6 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -665,6 +688,7 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -677,9 +701,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-checkbox-checked rc-tree-select-tree-treenode-active rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -689,7 +714,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="true"
+                        aria-label="Select 0"
                         class="rc-tree-select-tree-checkbox rc-tree-select-tree-checkbox-checked"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -706,9 +734,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-checkbox-checked rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -722,7 +751,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="true"
+                        aria-label="Select 0-0"
                         class="rc-tree-select-tree-checkbox rc-tree-select-tree-checkbox-checked"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -739,9 +771,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-checkbox-checked rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -758,7 +791,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 1`] = `
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher-noop"
                       />
                       <span
+                        aria-checked="true"
+                        aria-label="Select 0-0-0"
                         class="rc-tree-select-tree-checkbox rc-tree-select-tree-checkbox-checked"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-normal"
@@ -847,7 +883,6 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -872,6 +907,7 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -884,9 +920,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-active rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -896,7 +933,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="false"
+                        aria-label="Select 0"
                         class="rc-tree-select-tree-checkbox"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -913,9 +953,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -929,7 +970,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher_open"
                       />
                       <span
+                        aria-checked="false"
+                        aria-label="Select 0-0"
                         class="rc-tree-select-tree-checkbox"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-open"
@@ -946,9 +990,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -965,7 +1010,10 @@ exports[`TreeSelect.checkable uncheck remove by tree check 2`] = `
                         class="rc-tree-select-tree-switcher rc-tree-select-tree-switcher-noop"
                       />
                       <span
+                        aria-checked="false"
+                        aria-label="Select 0-0-0"
                         class="rc-tree-select-tree-checkbox"
+                        role="checkbox"
                       />
                       <span
                         class="rc-tree-select-tree-node-content-wrapper rc-tree-select-tree-node-content-wrapper-normal"
diff --git a/tests/__snapshots__/Select.spec.tsx.snap b/tests/__snapshots__/Select.spec.tsx.snap
index 7ffb246e..965c177a 100644
--- a/tests/__snapshots__/Select.spec.tsx.snap
+++ b/tests/__snapshots__/Select.spec.tsx.snap
@@ -49,7 +49,6 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
         </span>
         <div
           class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-          role="tree"
         >
           <div>
             <input
@@ -74,6 +73,7 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
           </div>
           <div
             class="rc-tree-select-tree-list"
+            role="tree"
             style="position: relative;"
           >
             <div
@@ -86,9 +86,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
                   style="display: flex; flex-direction: column;"
                 >
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-active"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -112,9 +113,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="true"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-leaf-last"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -138,9 +140,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -168,9 +171,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly 1`] = `
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -257,7 +261,6 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
         </span>
         <div
           class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-          role="tree"
         >
           <div>
             <input
@@ -282,6 +285,7 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
           </div>
           <div
             class="rc-tree-select-tree-list"
+            role="tree"
             style="position: relative;"
           >
             <div
@@ -294,9 +298,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
                   style="display: flex; flex-direction: column;"
                 >
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-active"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -320,9 +325,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="true"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-leaf-last"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -346,9 +352,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -376,9 +383,10 @@ exports[`TreeSelect.basic render renders TreeNode correctly with falsy child 1`]
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -614,7 +622,6 @@ exports[`TreeSelect.basic render renders treeDataSimpleMode correctly 1`] = `
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -639,6 +646,7 @@ exports[`TreeSelect.basic render renders treeDataSimpleMode correctly 1`] = `
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -651,9 +659,10 @@ exports[`TreeSelect.basic render renders treeDataSimpleMode correctly 1`] = `
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-active rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -677,9 +686,10 @@ exports[`TreeSelect.basic render renders treeDataSimpleMode correctly 1`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="false"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -766,7 +776,6 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 1`] = `
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -791,6 +800,7 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 1`] = `
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -803,9 +813,10 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 1`] = `
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-active rc-tree-select-tree-treenode-leaf-last filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -888,7 +899,6 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 2`] = `
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -913,6 +923,7 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 2`] = `
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -925,9 +936,10 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 2`] = `
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="true"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-open rc-tree-select-tree-treenode-active"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -951,9 +963,10 @@ exports[`TreeSelect.basic search nodes check tree changed by filter 2`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="false"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -1036,7 +1049,6 @@ exports[`TreeSelect.basic search nodes filter node but not remove then 1`] = `
           </span>
           <div
             class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-            role="tree"
           >
             <div>
               <input
@@ -1061,6 +1073,7 @@ exports[`TreeSelect.basic search nodes filter node but not remove then 1`] = `
             </div>
             <div
               class="rc-tree-select-tree-list"
+              role="tree"
               style="position: relative;"
             >
               <div
@@ -1073,9 +1086,10 @@ exports[`TreeSelect.basic search nodes filter node but not remove then 1`] = `
                     style="display: flex; flex-direction: column;"
                   >
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="false"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-active filter-node"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -1099,9 +1113,10 @@ exports[`TreeSelect.basic search nodes filter node but not remove then 1`] = `
                       </span>
                     </div>
                     <div
-                      aria-grabbed="false"
+                      aria-expanded="false"
                       class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                       draggable="false"
+                      role="treeitem"
                     >
                       <span
                         aria-hidden="true"
@@ -1182,7 +1197,6 @@ exports[`TreeSelect.basic search nodes renders search input 1`] = `
         </span>
         <div
           class="rc-tree-select-tree rc-tree-select-tree-active-focused"
-          role="tree"
         >
           <div>
             <input
@@ -1207,6 +1221,7 @@ exports[`TreeSelect.basic search nodes renders search input 1`] = `
           </div>
           <div
             class="rc-tree-select-tree-list"
+            role="tree"
             style="position: relative;"
           >
             <div
@@ -1219,9 +1234,10 @@ exports[`TreeSelect.basic search nodes renders search input 1`] = `
                   style="display: flex; flex-direction: column;"
                 >
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-active"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
@@ -1245,9 +1261,10 @@ exports[`TreeSelect.basic search nodes renders search input 1`] = `
                     </span>
                   </div>
                   <div
-                    aria-grabbed="false"
+                    aria-expanded="false"
                     class="rc-tree-select-tree-treenode rc-tree-select-tree-treenode-switcher-close rc-tree-select-tree-treenode-leaf-last"
                     draggable="false"
+                    role="treeitem"
                   >
                     <span
                       aria-hidden="true"
diff --git a/tests/util.tsx b/tests/util.tsx
index d9f7123d..0f25ca97 100644
--- a/tests/util.tsx
+++ b/tests/util.tsx
@@ -1,6 +1,16 @@
-import { fireEvent } from '@testing-library/react';
+import { fireEvent, createEvent } from '@testing-library/react';
 
 export function selectNode(index = 0) {
   const treeNode = document.querySelectorAll('.rc-tree-select-tree-node-content-wrapper')[index];
   fireEvent.click(treeNode);
 }
+
+export function keyDown(element: HTMLElement, keyCode: number) {
+  const event = createEvent.keyDown(element, { keyCode });
+  fireEvent(element, event);
+}
+
+export function keyUp(element: HTMLElement, keyCode: number) {
+  const event = createEvent.keyUp(element, { keyCode });
+  fireEvent(element, event);
+}