They have great example how to do that https://codesandbox.io/s/material-demo-ui4dx
Also be careful with TreeView component as it is still in Lab and can be with some issues and not finished implementation.
Answer from Eugene Chybisov on Stack OverflowWhen you have questions about how to override the default Material-UI styles, the best resource is to look at how the default styles are defined.
Below are the default styles for TreeItemContent:
const StyledTreeItemContent = styled(TreeItemContent, {
name: 'MuiTreeItem',
slot: 'Content',
overridesResolver: (props, styles) => {
return [
styles.content,
styles.iconContainer && {
[`& .${treeItemClasses.iconContainer}`]: styles.iconContainer,
},
styles.label && {
[`& .${treeItemClasses.label}`]: styles.label,
},
];
},
})(({ theme }) => ({
padding: '0 8px',
width: '100%',
display: 'flex',
alignItems: 'center',
cursor: 'pointer',
WebkitTapHighlightColor: 'transparent',
'&:hover': {
backgroundColor: (theme.vars || theme).palette.action.hover,
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: 'transparent',
},
},
[`&.${treeItemClasses.disabled}`]: {
opacity: (theme.vars || theme).palette.action.disabledOpacity,
backgroundColor: 'transparent',
},
[`&.${treeItemClasses.focused}`]: {
backgroundColor: (theme.vars || theme).palette.action.focus,
},
[`&.${treeItemClasses.selected}`]: {
backgroundColor: theme.vars
? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})`
: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
'&:hover': {
backgroundColor: theme.vars
? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.hoverOpacity}))`
: alpha(
theme.palette.primary.main,
theme.palette.action.selectedOpacity + theme.palette.action.hoverOpacity,
),
// Reset on touch devices, it doesn't add specificity
'@media (hover: none)': {
backgroundColor: theme.vars
? `rgba(${theme.vars.palette.primary.mainChannel} / ${theme.vars.palette.action.selectedOpacity})`
: alpha(theme.palette.primary.main, theme.palette.action.selectedOpacity),
},
},
[`&.${treeItemClasses.focused}`]: {
backgroundColor: theme.vars
? `rgba(${theme.vars.palette.primary.mainChannel} / calc(${theme.vars.palette.action.selectedOpacity} + ${theme.vars.palette.action.focusOpacity}))`
: alpha(
theme.palette.primary.main,
theme.palette.action.selectedOpacity + theme.palette.action.focusOpacity,
),
},
},
[`& .${treeItemClasses.iconContainer}`]: {
marginRight: 4,
width: 15,
display: 'flex',
flexShrink: 0,
justifyContent: 'center',
'& svg': {
fontSize: 18,
},
},
[`& .${treeItemClasses.label}`]: {
width: '100%',
// fixes overflow - see https://github.com/mui/material-ui/issues/27372
minWidth: 0,
paddingLeft: 4,
position: 'relative',
...theme.typography.body1,
},
}));
The overall structure of TreeItem can be found by looking at TreeItem and TreeItemContent and is as follows (simplified slightly):
<li className="MuiTreeItem-root">
<div className="MuiTreeItem-content">
<div className="MuiTreeItem-iconContainer">
{icon}
</div>
<div className="MuiTreeItem-label">
{label}
</div>
</div>
{children}
</li>
Additionally, the Mui-selected, Mui-expanded, Mui-focused, and Mui-disabled classes get added to the MuiTreeItem-content div when applicable.
You can target the MuiTreeItem-content div as follows:
const TreeItem = styled(MuiTreeItem)`
& > .MuiTreeItem-content.Mui-selected {
color: red;
}
`;
If you don't want to include the icon in the styling, then you can just target the label within the content:
const TreeItem = styled(MuiTreeItem)`
& > .MuiTreeItem-content.Mui-selected .MuiTreeItem-label {
color: red;
}
`;
If you want to change the background color, you need to pay attention to a few more details in the default styling (since the default styling does a lot with background color) in order to deal appropriately with the hover and focused states.
The answers so far use withStyles from MUI v4 because that was the current version when they were posted. I'm pretty sure there is a MUI v5 approach, but I gave up on trying to get that to work.
The technique used doesn't really matter as much, anyway: The problem is getting all the selectors right.
I ended up adding this to index.css which seems to disable any most focused / hover / selected styles (some edge cases seem to persist):
.MuiTreeItem-root:hover {
background: transparent
}
.MuiTreeItem-root > .MuiTreeItem-content:hover {
background: transparent
}
.MuiTreeItem-root > .MuiTreeItem-content:hover > .MuiTreeItem-label {
background: transparent
}
.MuiTreeItem-root > .MuiTreeItem-content.Mui-selected {
background: transparent
}
.MuiTreeItem-root > .MuiTreeItem-content.Mui-selected:hover {
background: transparent
}
.MuiTreeItem-root > .MuiTreeItem-content.Mui-selected > .MuiTreeItem-label {
background: transparent
}
.MuiTreeItem-root > .MuiTreeItem-content.Mui-selected.Mui-focused {
background: transparent
}
Yes, as far as I can tell, they are all required. Probably still a few more.
NOTE: That's focused (with one s), using e.g. MUI-focussed fails silently.
You can achieve that using TreeView expanded prop.
The code below expands the TreeItem with id "1" on mount.
import React, {useEffect, useState} from 'react';
import TreeView from '@material-ui/lab/TreeView';
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
import TreeItem from '@material-ui/lab/TreeItem';
export default function FileSystemNavigator() {
const [expanded, setExpanded] = useState([]);
useEffect(() => {
setExpanded(["1"])
},[])
return (
<TreeView
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
expanded={expanded}
>
<TreeItem nodeId="1" label="Applications"
>
<TreeItem nodeId="2" label="Calendar" />
<TreeItem nodeId="3" label="Chrome" />
<TreeItem nodeId="4" label="Webstorm" />
</TreeItem>
<TreeItem nodeId="5" label="Documents"
>
<TreeItem nodeId="6" label="Material-UI">
<TreeItem nodeId="7" label="src">
<TreeItem nodeId="8" label="index.js" />
<TreeItem nodeId="9" label="tree-view.js" />
</TreeItem>
</TreeItem>
</TreeItem>
</TreeView>
);
}
Code Sandbox
This answer is for Riham Nour Question in the comment section of this answer (won't be able to reply in comments due to less reputation).
what if I only want the selected parent TreeItem to be selected while collapsing the others? like when I select node 1, then node 6 collapses ?
Just add the nodeId of the selected nodes then you can easily be able to get the desired outcome. You can go through the code Code SandBox.
PS: I hope I understood the question correctly and Sorry I added this in the answer section. Please let me know if there is any better way to communicate the answer to Riham.
Use ContentProps props, it will be merged with the original TreeItemContentProps
<CustomTreeItem
nodeId="1"
label="Applications"
ContentProps={{
myProps: "my props",
}}
>
const CustomContent = React.forwardRef(function CustomContent(
props: TreeItemContentProps,
ref
) {
console.log(props.myProps); // "my props"
EDIT: For typescript users, you also need to augment the prop interface of TreeItemContent to remove the error:
declare module "@material-ui/lab/TreeItem" {
interface TreeItemContentProps {
myProps: string;
}
}
The ContentProps itself can't be augmented, this is a shortcoming from the MUI API, a workaround is simply ignore it:
ContentProps={
{
myProps: "my props"
} as any
}
As per current document follow these steps
I found the way as mentioned on following document
Code Ref: https://github.com/mui/material-ui/blob/512896973499adbbda057e7f3685d1b23cc02de9/docs/src/components/productX/XTreeViewDemo.tsx
Step1 Add custom property along TreeItemContentProps on custom component create
const CustomContentChildContent = React.forwardRef(function CustomContent(
props: TreeItemContentProps & { myCustomData?: string },
ref,
)
Step2 Add custom property to with TreeItemProps
const CustomTreeItemChild = (
props: TreeItemProps & {
ContentProps?: { myCustomData?: string };
},
) => <StyledTreeItem ContentComponent={CustomContentChildContent} {...props} />;
Step3
Add property in the component you are calling
<CustomTreeItemChild nodeId="3" label={item.name} ContentProps={{ myCustomData: 'anything-i-can-pass' }} />
