diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview
deleted file mode 100644
index 660542f7bf2cd..0000000000000
--- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx.preview
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/data/tree-view/rich-tree-view/customization/customization.md b/docs/data/tree-view/rich-tree-view/customization/customization.md
index 8f1552b6f0df4..4bedda31d7645 100644
--- a/docs/data/tree-view/rich-tree-view/customization/customization.md
+++ b/docs/data/tree-view/rich-tree-view/customization/customization.md
@@ -64,12 +64,6 @@ The demo below shows how to add an avatar and custom typography elements.
## Common examples
-### Limit expansion to icon container
-
-The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item surface.
-
-{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}}
-
### File explorer
:::warning
diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js
similarity index 55%
rename from docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js
rename to docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js
index fa2935769a638..db2d29f0fcfa8 100644
--- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.js
+++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.js
@@ -1,9 +1,6 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { useTreeItem2Utils } from '@mui/x-tree-view/hooks';
-
-import { TreeItem2 } from '@mui/x-tree-view/TreeItem2';
const MUI_X_PRODUCTS = [
{
@@ -35,37 +32,10 @@ const MUI_X_PRODUCTS = [
},
];
-const CustomTreeItem = React.forwardRef(function MyTreeItem(props, ref) {
- const { interactions } = useTreeItem2Utils({
- itemId: props.itemId,
- children: props.children,
- });
-
- const handleContentClick = (event) => {
- event.defaultMuiPrevented = true;
- interactions.handleSelection(event);
- };
-
- const handleIconContainerClick = (event) => {
- interactions.handleExpansion(event);
- };
-
- return (
-
- );
-});
-
export default function IconExpansionTreeView() {
return (
-
+
);
}
diff --git a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx
similarity index 51%
rename from docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx
rename to docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx
index 0d7345a1047d5..94b9816b9a897 100644
--- a/docs/data/tree-view/rich-tree-view/customization/IconExpansionTreeView.tsx
+++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx
@@ -1,9 +1,6 @@
import * as React from 'react';
import Box from '@mui/material/Box';
import { RichTreeView } from '@mui/x-tree-view/RichTreeView';
-import { useTreeItem2Utils } from '@mui/x-tree-view/hooks';
-import { UseTreeItem2ContentSlotOwnProps } from '@mui/x-tree-view/useTreeItem2';
-import { TreeItem2, TreeItem2Props } from '@mui/x-tree-view/TreeItem2';
import { TreeViewBaseItem } from '@mui/x-tree-view/models';
const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
@@ -36,40 +33,10 @@ const MUI_X_PRODUCTS: TreeViewBaseItem[] = [
},
];
-const CustomTreeItem = React.forwardRef(function MyTreeItem(
- props: TreeItem2Props,
- ref: React.Ref,
-) {
- const { interactions } = useTreeItem2Utils({
- itemId: props.itemId,
- children: props.children,
- });
-
- const handleContentClick: UseTreeItem2ContentSlotOwnProps['onClick'] = (event) => {
- event.defaultMuiPrevented = true;
- interactions.handleSelection(event);
- };
-
- const handleIconContainerClick = (event: React.MouseEvent) => {
- interactions.handleExpansion(event);
- };
-
- return (
-
- );
-});
-
export default function IconExpansionTreeView() {
return (
-
+
);
}
diff --git a/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview
new file mode 100644
index 0000000000000..49f8c4e181622
--- /dev/null
+++ b/docs/data/tree-view/rich-tree-view/expansion/IconExpansionTreeView.tsx.preview
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/data/tree-view/rich-tree-view/expansion/expansion.md b/docs/data/tree-view/rich-tree-view/expansion/expansion.md
index e36fe65d20c1e..47897f4c9170f 100644
--- a/docs/data/tree-view/rich-tree-view/expansion/expansion.md
+++ b/docs/data/tree-view/rich-tree-view/expansion/expansion.md
@@ -33,6 +33,12 @@ Use the `onItemExpansionToggle` prop if you want to react to an item expansion c
{{"demo": "TrackItemExpansionToggle.js"}}
+## Limit expansion to icon container
+
+You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content.
+
+{{"demo": "IconExpansionTreeView.js"}}
+
## Imperative API
:::success
diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js
deleted file mode 100644
index 36e9e200da117..0000000000000
--- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.js
+++ /dev/null
@@ -1,57 +0,0 @@
-import * as React from 'react';
-import Box from '@mui/material/Box';
-import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
-import { useTreeItem2Utils } from '@mui/x-tree-view/hooks';
-
-import { TreeItem2 } from '@mui/x-tree-view/TreeItem2';
-
-const CustomTreeItem = React.forwardRef(function MyTreeItem(props, ref) {
- const { interactions } = useTreeItem2Utils({
- itemId: props.itemId,
- children: props.children,
- });
-
- const handleContentClick = (event) => {
- event.defaultMuiPrevented = true;
- interactions.handleSelection(event);
- };
-
- const handleIconContainerClick = (event) => {
- interactions.handleExpansion(event);
- };
-
- return (
-
- );
-});
-
-export default function IconExpansionTreeView() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx
deleted file mode 100644
index f0a5de292e600..0000000000000
--- a/docs/data/tree-view/simple-tree-view/customization/IconExpansionTreeView.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import * as React from 'react';
-import Box from '@mui/material/Box';
-import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
-import { useTreeItem2Utils } from '@mui/x-tree-view/hooks';
-import { UseTreeItem2ContentSlotOwnProps } from '@mui/x-tree-view/useTreeItem2';
-import { TreeItem2, TreeItem2Props } from '@mui/x-tree-view/TreeItem2';
-
-const CustomTreeItem = React.forwardRef(function MyTreeItem(
- props: TreeItem2Props,
- ref: React.Ref,
-) {
- const { interactions } = useTreeItem2Utils({
- itemId: props.itemId,
- children: props.children,
- });
-
- const handleContentClick: UseTreeItem2ContentSlotOwnProps['onClick'] = (event) => {
- event.defaultMuiPrevented = true;
- interactions.handleSelection(event);
- };
-
- const handleIconContainerClick = (event: React.MouseEvent) => {
- interactions.handleExpansion(event);
- };
-
- return (
-
- );
-});
-
-export default function IconExpansionTreeView() {
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-}
diff --git a/docs/data/tree-view/simple-tree-view/customization/customization.md b/docs/data/tree-view/simple-tree-view/customization/customization.md
index e5e70b9e4aa89..7cf009836436f 100644
--- a/docs/data/tree-view/simple-tree-view/customization/customization.md
+++ b/docs/data/tree-view/simple-tree-view/customization/customization.md
@@ -70,19 +70,6 @@ Target the `treeItemClasses.groupTransition` class to add connection borders bet
{{"demo": "BorderedTreeView.js", "defaultCodeOpen": false}}
-### Limit expansion to icon container
-
-:::warning
-This example is built using the new `TreeItem2` component
-which adds several slots to modify the content of the Tree Item or change its behavior.
-
-You can learn more about this new component in the [Overview page](/x/react-tree-view/#tree-item-components).
-:::
-
-The demo below shows how to trigger the expansion interaction just by clicking on the icon container instead of the whole Tree Item surface.
-
-{{"demo": "IconExpansionTreeView.js", "defaultCodeOpen": false}}
-
### Gmail clone
:::warning
diff --git a/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js
new file mode 100644
index 0000000000000..3a046031d357a
--- /dev/null
+++ b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.js
@@ -0,0 +1,28 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
+import { TreeItem } from '@mui/x-tree-view/TreeItem';
+
+export default function IconExpansionTreeView() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx
new file mode 100644
index 0000000000000..3a046031d357a
--- /dev/null
+++ b/docs/data/tree-view/simple-tree-view/expansion/IconExpansionTreeView.tsx
@@ -0,0 +1,28 @@
+import * as React from 'react';
+import Box from '@mui/material/Box';
+import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
+import { TreeItem } from '@mui/x-tree-view/TreeItem';
+
+export default function IconExpansionTreeView() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/docs/data/tree-view/simple-tree-view/expansion/expansion.md b/docs/data/tree-view/simple-tree-view/expansion/expansion.md
index a6b0a3f4e46ac..a3648bd3697ff 100644
--- a/docs/data/tree-view/simple-tree-view/expansion/expansion.md
+++ b/docs/data/tree-view/simple-tree-view/expansion/expansion.md
@@ -32,6 +32,12 @@ Use the `onItemExpansionToggle` prop to trigger an action upon an item being exp
{{"demo": "TrackItemExpansionToggle.js"}}
+## Limit expansion to icon container
+
+You can use the `expansionTrigger` prop to decide if the expansion interaction should be triggered by clicking on the icon container instead of the whole Tree Item content.
+
+{{"demo": "IconExpansionTreeView.js"}}
+
## Imperative API
:::success
diff --git a/docs/pages/x/api/tree-view/rich-tree-view.json b/docs/pages/x/api/tree-view/rich-tree-view.json
index 7da4e28d56f04..302a091490e72 100644
--- a/docs/pages/x/api/tree-view/rich-tree-view.json
+++ b/docs/pages/x/api/tree-view/rich-tree-view.json
@@ -16,6 +16,10 @@
"disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" },
"disableSelection": { "type": { "name": "bool" }, "default": "false" },
"expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } },
+ "expansionTrigger": {
+ "type": { "name": "enum", "description": "'content'
| 'iconContainer'" },
+ "default": "'content'"
+ },
"experimentalFeatures": {
"type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" }
},
diff --git a/docs/pages/x/api/tree-view/simple-tree-view.json b/docs/pages/x/api/tree-view/simple-tree-view.json
index 1c52f9e03646b..24df95176eb56 100644
--- a/docs/pages/x/api/tree-view/simple-tree-view.json
+++ b/docs/pages/x/api/tree-view/simple-tree-view.json
@@ -17,6 +17,10 @@
"disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" },
"disableSelection": { "type": { "name": "bool" }, "default": "false" },
"expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } },
+ "expansionTrigger": {
+ "type": { "name": "enum", "description": "'content'
| 'iconContainer'" },
+ "default": "'content'"
+ },
"experimentalFeatures": {
"type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" }
},
diff --git a/docs/pages/x/api/tree-view/tree-view.json b/docs/pages/x/api/tree-view/tree-view.json
index a528b9927844b..b2eead268281a 100644
--- a/docs/pages/x/api/tree-view/tree-view.json
+++ b/docs/pages/x/api/tree-view/tree-view.json
@@ -17,6 +17,10 @@
"disabledItemsFocusable": { "type": { "name": "bool" }, "default": "false" },
"disableSelection": { "type": { "name": "bool" }, "default": "false" },
"expandedItems": { "type": { "name": "arrayOf", "description": "Array<string>" } },
+ "expansionTrigger": {
+ "type": { "name": "enum", "description": "'content'
| 'iconContainer'" },
+ "default": "'content'"
+ },
"experimentalFeatures": {
"type": { "name": "shape", "description": "{ indentationAtItemLevel?: bool }" }
},
diff --git a/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json b/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json
index b866f4dcc07a5..42345574e68d5 100644
--- a/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json
+++ b/docs/translations/api-docs/tree-view/rich-tree-view/rich-tree-view.json
@@ -21,6 +21,9 @@
"expandedItems": {
"description": "Expanded item ids. Used when the item's expansion is controlled."
},
+ "expansionTrigger": {
+ "description": "The slot that triggers the item's expansion when clicked."
+ },
"experimentalFeatures": {
"description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true
, the feature will be fully disabled and any property / method call will not have any effect."
},
diff --git a/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json b/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json
index a12a983517785..8d0b15e73d6ac 100644
--- a/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json
+++ b/docs/translations/api-docs/tree-view/simple-tree-view/simple-tree-view.json
@@ -22,6 +22,9 @@
"expandedItems": {
"description": "Expanded item ids. Used when the item's expansion is controlled."
},
+ "expansionTrigger": {
+ "description": "The slot that triggers the item's expansion when clicked."
+ },
"experimentalFeatures": {
"description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true
, the feature will be fully disabled and any property / method call will not have any effect."
},
diff --git a/docs/translations/api-docs/tree-view/tree-view/tree-view.json b/docs/translations/api-docs/tree-view/tree-view/tree-view.json
index c29df21217338..f61dba71a60ae 100644
--- a/docs/translations/api-docs/tree-view/tree-view/tree-view.json
+++ b/docs/translations/api-docs/tree-view/tree-view/tree-view.json
@@ -22,6 +22,9 @@
"expandedItems": {
"description": "Expanded item ids. Used when the item's expansion is controlled."
},
+ "expansionTrigger": {
+ "description": "The slot that triggers the item's expansion when clicked."
+ },
"experimentalFeatures": {
"description": "Unstable features, breaking changes might be introduced. For each feature, if the flag is not explicitly set to true
, the feature will be fully disabled and any property / method call will not have any effect."
},
diff --git a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx
index 5f94c0db2be7a..1af8e390626f8 100644
--- a/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx
+++ b/packages/x-tree-view/src/RichTreeView/RichTreeView.tsx
@@ -191,6 +191,11 @@ RichTreeView.propTypes = {
* Used when the item's expansion is controlled.
*/
expandedItems: PropTypes.arrayOf(PropTypes.string),
+ /**
+ * The slot that triggers the item's expansion when clicked.
+ * @default 'content'
+ */
+ expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']),
/**
* Unstable features, breaking changes might be introduced.
* For each feature, if the flag is not explicitly set to `true`,
diff --git a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx
index 472bf6208f582..9993677439e3d 100644
--- a/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx
+++ b/packages/x-tree-view/src/SimpleTreeView/SimpleTreeView.tsx
@@ -154,6 +154,11 @@ SimpleTreeView.propTypes = {
* Used when the item's expansion is controlled.
*/
expandedItems: PropTypes.arrayOf(PropTypes.string),
+ /**
+ * The slot that triggers the item's expansion when clicked.
+ * @default 'content'
+ */
+ expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']),
/**
* Unstable features, breaking changes might be introduced.
* For each feature, if the flag is not explicitly set to `true`,
diff --git a/packages/x-tree-view/src/TreeItem/TreeItem.tsx b/packages/x-tree-view/src/TreeItem/TreeItem.tsx
index 2f35d89749058..b048be14f8dc8 100644
--- a/packages/x-tree-view/src/TreeItem/TreeItem.tsx
+++ b/packages/x-tree-view/src/TreeItem/TreeItem.tsx
@@ -23,6 +23,7 @@ import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewCon
import { TreeViewCollapseIcon, TreeViewExpandIcon } from '../icons';
import { TreeItem2Provider } from '../TreeItem2Provider';
import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext';
+import { useTreeItemState } from './useTreeItemState';
const useThemeProps = createUseThemeProps('MuiTreeItem');
@@ -187,6 +188,7 @@ export const TreeItem = React.forwardRef(function TreeItem(
icons: contextIcons,
runItemPlugins,
selection: { multiSelect },
+ expansion: { expansionTrigger },
disabledItemsFocusable,
indentationAtItemLevel,
instance,
@@ -213,6 +215,8 @@ export const TreeItem = React.forwardRef(function TreeItem(
...other
} = props;
+ const { expanded, focused, selected, disabled, handleExpansion } = useTreeItemState(itemId);
+
const { contentRef, rootRef } = runItemPlugins(props);
const handleRootRef = useForkRef(inRef, rootRef);
const handleContentRef = useForkRef(ContentProps?.ref, contentRef);
@@ -232,10 +236,6 @@ export const TreeItem = React.forwardRef(function TreeItem(
return Boolean(reactChildren);
};
const expandable = isExpandable(children);
- const expanded = instance.isItemExpanded(itemId);
- const focused = instance.isItemFocused(itemId);
- const selected = instance.isItemSelected(itemId);
- const disabled = instance.isItemDisabled(itemId);
const ownerState: TreeItemOwnerState = {
...props,
@@ -263,6 +263,11 @@ export const TreeItem = React.forwardRef(function TreeItem(
className: classes.groupTransition,
});
+ const handleIconContainerClick = (event: React.MouseEvent) => {
+ if (expansionTrigger === 'iconContainer') {
+ handleExpansion(event);
+ }
+ };
const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon;
const { ownerState: expansionIconOwnerState, ...expansionIconProps } = useSlotProps({
elementType: ExpansionIcon,
@@ -280,6 +285,9 @@ export const TreeItem = React.forwardRef(function TreeItem(
...resolveComponentProps(inSlotProps?.expandIcon, tempOwnerState),
};
},
+ additionalProps: {
+ onClick: handleIconContainerClick,
+ },
});
const expansionIcon =
expandable && !!ExpansionIcon ? : null;
diff --git a/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx b/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx
index 11c31e401ceeb..c04b65ed08ea0 100644
--- a/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx
+++ b/packages/x-tree-view/src/TreeItem/TreeItemContent.tsx
@@ -82,6 +82,7 @@ const TreeItemContent = React.forwardRef(function TreeItemContent(
handleSelection,
handleCheckboxSelection,
preventSelection,
+ expansionTrigger,
} = useTreeItemState(itemId);
const icon = iconProp || expansionIcon || displayIcon;
@@ -100,7 +101,9 @@ const TreeItemContent = React.forwardRef(function TreeItemContent(
return;
}
- handleExpansion(event);
+ if (expansionTrigger === 'content') {
+ handleExpansion(event);
+ }
if (!checkboxSelection) {
handleSelection(event);
diff --git a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts
index 09f9ce6f88c2e..5a05ee89bf28b 100644
--- a/packages/x-tree-view/src/TreeItem/useTreeItemState.ts
+++ b/packages/x-tree-view/src/TreeItem/useTreeItemState.ts
@@ -18,6 +18,7 @@ export function useTreeItemState(itemId: string) {
const {
instance,
selection: { multiSelect, checkboxSelection, disableSelection },
+ expansion: { expansionTrigger },
} = useTreeViewContext();
const expandable = instance.isItemExpandable(itemId);
@@ -92,5 +93,6 @@ export function useTreeItemState(itemId: string) {
handleSelection,
handleCheckboxSelection,
preventSelection,
+ expansionTrigger,
};
}
diff --git a/packages/x-tree-view/src/TreeView/TreeView.tsx b/packages/x-tree-view/src/TreeView/TreeView.tsx
index 2149524f39fd0..55d215de61837 100644
--- a/packages/x-tree-view/src/TreeView/TreeView.tsx
+++ b/packages/x-tree-view/src/TreeView/TreeView.tsx
@@ -139,6 +139,11 @@ TreeView.propTypes = {
* Used when the item's expansion is controlled.
*/
expandedItems: PropTypes.arrayOf(PropTypes.string),
+ /**
+ * The slot that triggers the item's expansion when clicked.
+ * @default 'content'
+ */
+ expansionTrigger: PropTypes.oneOf(['content', 'iconContainer']),
/**
* Unstable features, breaking changes might be introduced.
* For each feature, if the flag is not explicitly set to `true`,
diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts
index d463f24e85bb0..3fd669acf55f9 100644
--- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts
+++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.ts
@@ -83,6 +83,14 @@ export const useTreeViewExpansion: TreeViewPlugin
}
};
+ const expansionTrigger = React.useMemo(() => {
+ if (params.expansionTrigger) {
+ return params.expansionTrigger;
+ }
+
+ return 'content';
+ }, [params.expansionTrigger]);
+
return {
publicAPI: {
setItemExpansion,
@@ -94,6 +102,11 @@ export const useTreeViewExpansion: TreeViewPlugin
toggleItemExpansion,
expandAllSiblings,
},
+ contextValue: {
+ expansion: {
+ expansionTrigger,
+ },
+ },
};
};
@@ -115,4 +128,5 @@ useTreeViewExpansion.params = {
defaultExpandedItems: true,
onExpandedItemsChange: true,
onItemExpansionToggle: true,
+ expansionTrigger: true,
};
diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts
index f3e93a059afd5..2b7c858d56719 100644
--- a/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts
+++ b/packages/x-tree-view/src/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.ts
@@ -72,6 +72,11 @@ export interface UseTreeViewExpansionParameters {
itemId: string,
isExpanded: boolean,
) => void;
+ /**
+ * The slot that triggers the item's expansion when clicked.
+ * @default 'content'
+ */
+ expansionTrigger?: 'content' | 'iconContainer';
}
export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps<
@@ -79,11 +84,16 @@ export type UseTreeViewExpansionDefaultizedParameters = DefaultizedProps<
'defaultExpandedItems'
>;
+interface UseTreeViewExpansionContextValue {
+ expansion: Pick;
+}
+
export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{
params: UseTreeViewExpansionParameters;
defaultizedParams: UseTreeViewExpansionDefaultizedParameters;
instance: UseTreeViewExpansionInstance;
publicAPI: UseTreeViewExpansionPublicAPI;
modelNames: 'expandedItems';
+ contextValue: UseTreeViewExpansionContextValue;
dependencies: [UseTreeViewItemsSignature];
}>;
diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts
index 54c6e3dc7435c..904a6706dcc5b 100644
--- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts
+++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.ts
@@ -27,6 +27,7 @@ export const useTreeItem2 = <
const {
runItemPlugins,
selection: { multiSelect, disableSelection, checkboxSelection },
+ expansion: { expansionTrigger },
disabledItemsFocusable,
indentationAtItemLevel,
instance,
@@ -85,7 +86,9 @@ export const useTreeItem2 = <
return;
}
- interactions.handleExpansion(event);
+ if (expansionTrigger === 'content') {
+ interactions.handleExpansion(event);
+ }
if (!checkboxSelection) {
interactions.handleSelection(event);
@@ -120,6 +123,17 @@ export const useTreeItem2 = <
interactions.handleCheckboxSelection(event);
};
+ const createIconContainerHandleClick =
+ (otherHandlers: EventHandlers) => (event: React.MouseEvent & MuiCancellableEvent) => {
+ otherHandlers.onClick?.(event);
+ if (event.defaultMuiPrevented) {
+ return;
+ }
+ if (expansionTrigger === 'iconContainer') {
+ interactions.handleExpansion(event);
+ }
+ };
+
const getRootProps = = {}>(
externalProps: ExternalProps = {} as ExternalProps,
): UseTreeItem2RootSlotProps => {
@@ -227,6 +241,7 @@ export const useTreeItem2 = <
return {
...externalEventHandlers,
...externalProps,
+ onClick: createIconContainerHandleClick(externalEventHandlers),
};
};
diff --git a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts
index 321b9d5a14083..c4abbc7d2220e 100644
--- a/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts
+++ b/packages/x-tree-view/src/useTreeItem2/useTreeItem2.types.ts
@@ -7,6 +7,7 @@ import { UseTreeViewItemsSignature } from '../internals/plugins/useTreeViewItems
import { UseTreeViewIdSignature } from '../internals/plugins/useTreeViewId';
import { UseTreeViewFocusSignature } from '../internals/plugins/useTreeViewFocus';
import { UseTreeViewKeyboardNavigationSignature } from '../internals/plugins/useTreeViewKeyboardNavigation';
+import { UseTreeViewExpansionSignature } from '../internals/plugins/useTreeViewExpansion';
export interface UseTreeItem2Parameters {
/**
@@ -68,7 +69,9 @@ export interface UseTreeItem2ContentSlotOwnProps {
export type UseTreeItem2ContentSlotProps = ExternalProps &
UseTreeItem2ContentSlotOwnProps;
-export interface UseTreeItem2IconContainerSlotOwnProps {}
+export interface UseTreeItem2IconContainerSlotOwnProps {
+ onClick: MuiCancellableEventHandler;
+}
export type UseTreeItemIconContainerSlotProps = ExternalProps &
UseTreeItem2IconContainerSlotOwnProps;
@@ -186,6 +189,7 @@ export interface UseTreeItem2ReturnValue<
*/
export type UseTreeItem2MinimalPlugins = readonly [
UseTreeViewSelectionSignature,
+ UseTreeViewExpansionSignature,
UseTreeViewItemsSignature,
UseTreeViewIdSignature,
UseTreeViewFocusSignature,
diff --git a/test/utils/tree-view/fakeContextValue.ts b/test/utils/tree-view/fakeContextValue.ts
index 5f4e44545102c..f310590520351 100644
--- a/test/utils/tree-view/fakeContextValue.ts
+++ b/test/utils/tree-view/fakeContextValue.ts
@@ -39,4 +39,5 @@ export const getFakeContextValue = (
rootRef: {
current: null,
},
+ expansion: { expansionTrigger: 'content' },
});