Skip to content

Commit

Permalink
[TreeView] Support node label (#17080)
Browse files Browse the repository at this point in the history
* [TreeView] Support node label

* Update docs/src/pages/components/tree-view/tree-view.md

Co-Authored-By: Matt <github@nospam.33m.co>

* Update docs/src/pages/components/tree-view/tree-view.md

Co-Authored-By: Matt <github@nospam.33m.co>

* Update docs/src/pages/components/tree-view/GmailTreeView.tsx
  • Loading branch information
oliviertassinari authored Aug 22, 2019
1 parent cd825b7 commit 4f10bf7
Show file tree
Hide file tree
Showing 7 changed files with 356 additions and 6 deletions.
1 change: 1 addition & 0 deletions docs/pages/api/tree-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Any other props supplied will be provided to the root element (native element).
| Rule name | Global class | Description |
|:-----|:-------------|:------------|
| <span class="prop-name">root</span> | <span class="prop-name">MuiTreeItem-root</span> | Styles applied to the root element.
| <span class="prop-name">expanded</span> | <span class="prop-name">Mui-expanded</span> | Pseudo-class applied to the root element when expanded.
| <span class="prop-name">group</span> | <span class="prop-name">MuiTreeItem-group</span> | Styles applied to the `role="group"` element.
| <span class="prop-name">content</span> | <span class="prop-name">MuiTreeItem-content</span> | Styles applied to the tree node content.
| <span class="prop-name">iconContainer</span> | <span class="prop-name">MuiTreeItem-iconContainer</span> | Styles applied to the tree node icon and collapse/expand icon.
Expand Down
159 changes: 159 additions & 0 deletions docs/src/pages/components/tree-view/GmailTreeView.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
import React from 'react';
import PropTypes from 'prop-types';
import { makeStyles } from '@material-ui/core/styles';
import TreeView from '@material-ui/lab/TreeView';
import TreeItem from '@material-ui/lab/TreeItem';
import Typography from '@material-ui/core/Typography';
import MailIcon from '@material-ui/icons/Mail';
import DeleteIcon from '@material-ui/icons/Delete';
import Label from '@material-ui/icons/Label';
import SupervisorAccountIcon from '@material-ui/icons/SupervisorAccount';
import InfoIcon from '@material-ui/icons/Info';
import ForumIcon from '@material-ui/icons/Forum';
import LocalOfferIcon from '@material-ui/icons/LocalOffer';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import ArrowRightIcon from '@material-ui/icons/ArrowRight';

const useTreeItemStyles = makeStyles(theme => ({
root: {
color: theme.palette.text.secondary,
'&:focus > $content': {
backgroundColor: `var(--tree-view-bg-color, ${theme.palette.grey[400]})`,
color: 'var(--tree-view-color)',
},
},
content: {
color: theme.palette.text.secondary,
borderTopRightRadius: theme.spacing(2),
borderBottomRightRadius: theme.spacing(2),
paddingRight: theme.spacing(1),
fontWeight: theme.typography.fontWeightMedium,
'$expanded > &': {
fontWeight: theme.typography.fontWeightRegular,
},
},
group: {
marginLeft: 0,
'& $content': {
paddingLeft: theme.spacing(2),
},
},
expanded: {},
label: {
fontWeight: 'inherit',
color: 'inherit',
},
labelRoot: {
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0.5, 0),
},
labelIcon: {
marginRight: theme.spacing(1),
},
labelText: {
fontWeight: 'inherit',
flexGrow: 1,
},
}));

function StyledTreeItem(props) {
const classes = useTreeItemStyles();
const { labelText, labelIcon: LabelIcon, labelInfo, color, bgColor, ...other } = props;

return (
<TreeItem
label={
<div className={classes.labelRoot}>
<LabelIcon color="inherit" className={classes.labelIcon} />
<Typography variant="body2" className={classes.labelText}>
{labelText}
</Typography>
<Typography variant="caption" color="inherit">
{labelInfo}
</Typography>
</div>
}
style={{
'--tree-view-color': color,
'--tree-view-bg-color': bgColor,
}}
classes={{
root: classes.root,
content: classes.content,
expanded: classes.expanded,
group: classes.group,
label: classes.label,
}}
{...other}
/>
);
}

StyledTreeItem.propTypes = {
bgColor: PropTypes.string,
color: PropTypes.string,
labelIcon: PropTypes.elementType.isRequired,
labelInfo: PropTypes.string,
labelText: PropTypes.string.isRequired,
};

const useStyles = makeStyles({
root: {
height: 264,
flexGrow: 1,
maxWidth: 400,
},
});

export default function GmailTreeView() {
const classes = useStyles();

return (
<TreeView
className={classes.root}
defaultExpanded={['3']}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<div style={{ width: 24 }} />}
>
<StyledTreeItem nodeId="1" labelText="All Mail" labelIcon={MailIcon} />
<StyledTreeItem nodeId="2" labelText="Trash" labelIcon={DeleteIcon} />
<StyledTreeItem nodeId="3" labelText="Categories" labelIcon={Label}>
<StyledTreeItem
nodeId="5"
labelText="Social"
labelIcon={SupervisorAccountIcon}
labelInfo="90"
color="#1a73e8"
bgColor="#e8f0fe"
/>
<StyledTreeItem
nodeId="6"
labelText="Updates"
labelIcon={InfoIcon}
labelInfo="2,294"
color="#e3742f"
bgColor="#fcefe3"
/>
<StyledTreeItem
nodeId="7"
labelText="Forums"
labelIcon={ForumIcon}
labelInfo="3,566"
color="#a250f5"
bgColor="#f3e8fd"
/>
<StyledTreeItem
nodeId="8"
labelText="Promotions"
labelIcon={LocalOfferIcon}
labelInfo="733"
color="#3c8039"
bgColor="#e6f4ea"
/>
</StyledTreeItem>
<StyledTreeItem nodeId="4" labelText="History" labelIcon={Label} />
</TreeView>
);
}
170 changes: 170 additions & 0 deletions docs/src/pages/components/tree-view/GmailTreeView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import React from 'react';
import { makeStyles, Theme, createStyles } from '@material-ui/core/styles';
import TreeView from '@material-ui/lab/TreeView';
import TreeItem, { TreeItemProps } from '@material-ui/lab/TreeItem';
import Typography from '@material-ui/core/Typography';
import MailIcon from '@material-ui/icons/Mail';
import DeleteIcon from '@material-ui/icons/Delete';
import Label from '@material-ui/icons/Label';
import SupervisorAccountIcon from '@material-ui/icons/SupervisorAccount';
import InfoIcon from '@material-ui/icons/Info';
import ForumIcon from '@material-ui/icons/Forum';
import LocalOfferIcon from '@material-ui/icons/LocalOffer';
import ArrowDropDownIcon from '@material-ui/icons/ArrowDropDown';
import ArrowRightIcon from '@material-ui/icons/ArrowRight';
import { SvgIconProps } from '@material-ui/core/SvgIcon';

declare module 'csstype' {
interface Properties {
'--tree-view-color'?: string;
'--tree-view-bg-color'?: string;
}
}

type StyledTreeItemProps = TreeItemProps & {
bgColor?: string;
color?: string;
labelIcon: React.ElementType<SvgIconProps>;
labelInfo?: string;
labelText: string;
};

const useTreeItemStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
color: theme.palette.text.secondary,
'&:focus > $content': {
backgroundColor: `var(--tree-view-bg-color, ${theme.palette.grey[400]})`,
color: 'var(--tree-view-color)',
},
},
content: {
color: theme.palette.text.secondary,
borderTopRightRadius: theme.spacing(2),
borderBottomRightRadius: theme.spacing(2),
paddingRight: theme.spacing(1),
fontWeight: theme.typography.fontWeightMedium,
'$expanded > &': {
fontWeight: theme.typography.fontWeightRegular,
},
},
group: {
marginLeft: 0,
'& $content': {
paddingLeft: theme.spacing(2),
},
},
expanded: {},
label: {
fontWeight: 'inherit',
color: 'inherit',
},
labelRoot: {
display: 'flex',
alignItems: 'center',
padding: theme.spacing(0.5, 0),
},
labelIcon: {
marginRight: theme.spacing(1),
},
labelText: {
fontWeight: 'inherit',
flexGrow: 1,
},
}),
);

function StyledTreeItem(props: StyledTreeItemProps) {
const classes = useTreeItemStyles();
const { labelText, labelIcon: LabelIcon, labelInfo, color, bgColor, ...other } = props;

return (
<TreeItem
label={
<div className={classes.labelRoot}>
<LabelIcon color="inherit" className={classes.labelIcon} />
<Typography variant="body2" className={classes.labelText}>
{labelText}
</Typography>
<Typography variant="caption" color="inherit">
{labelInfo}
</Typography>
</div>
}
style={{
'--tree-view-color': color,
'--tree-view-bg-color': bgColor,
}}
classes={{
root: classes.root,
content: classes.content,
expanded: classes.expanded,
group: classes.group,
label: classes.label,
}}
{...other}
/>
);
}

const useStyles = makeStyles(
createStyles({
root: {
height: 264,
flexGrow: 1,
maxWidth: 400,
},
}),
);

export default function GmailTreeView() {
const classes = useStyles();

return (
<TreeView
className={classes.root}
defaultExpanded={['3']}
defaultCollapseIcon={<ArrowDropDownIcon />}
defaultExpandIcon={<ArrowRightIcon />}
defaultEndIcon={<div style={{ width: 24 }} />}
>
<StyledTreeItem nodeId="1" labelText="All Mail" labelIcon={MailIcon} />
<StyledTreeItem nodeId="2" labelText="Trash" labelIcon={DeleteIcon} />
<StyledTreeItem nodeId="3" labelText="Categories" labelIcon={Label}>
<StyledTreeItem
nodeId="5"
labelText="Social"
labelIcon={SupervisorAccountIcon}
labelInfo="90"
color="#1a73e8"
bgColor="#e8f0fe"
/>
<StyledTreeItem
nodeId="6"
labelText="Updates"
labelIcon={InfoIcon}
labelInfo="2,294"
color="#e3742f"
bgColor="#fcefe3"
/>
<StyledTreeItem
nodeId="7"
labelText="Forums"
labelIcon={ForumIcon}
labelInfo="3,566"
color="#a250f5"
bgColor="#f3e8fd"
/>
<StyledTreeItem
nodeId="8"
labelText="Promotions"
labelIcon={LocalOfferIcon}
labelInfo="733"
color="#3c8039"
bgColor="#e6f4ea"
/>
</StyledTreeItem>
<StyledTreeItem nodeId="4" labelText="History" labelIcon={Label} />
</TreeView>
);
}
6 changes: 6 additions & 0 deletions docs/src/pages/components/tree-view/tree-view.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ Tree views can be used to represent a file system navigator displaying folders a

## Customized tree view

### Custom icons, border and animation

{{"demo": "pages/components/tree-view/CustomizedTreeView.js"}}

### Gmail clone

{{"demo": "pages/components/tree-view/GmailTreeView.js"}}
8 changes: 7 additions & 1 deletion packages/material-ui-lab/src/TreeItem/TreeItem.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ export interface TreeItemProps
TransitionComponent?: React.ComponentType<TransitionProps>;
}

export type TreeItemClassKey = 'root' | 'group' | 'content' | 'iconContainer' | 'label';
export type TreeItemClassKey =
| 'root'
| 'expanded'
| 'group'
| 'content'
| 'iconContainer'
| 'label';

declare const TreeItem: React.ComponentType<TreeItemProps>;

Expand Down
Loading

0 comments on commit 4f10bf7

Please sign in to comment.