-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
/
RouterBreadcrumbs.tsx
134 lines (119 loc) · 4.01 KB
/
RouterBreadcrumbs.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* eslint-disable no-nested-ternary */
import React from 'react';
import PropTypes from 'prop-types';
import { Theme, createStyles, makeStyles } from '@material-ui/core/styles';
import List from '@material-ui/core/List';
import Link, { LinkProps } from '@material-ui/core/Link';
import NoSsr from '@material-ui/core/NoSsr';
import ListItem from '@material-ui/core/ListItem';
import Collapse from '@material-ui/core/Collapse';
import ListItemText from '@material-ui/core/ListItemText';
import Typography from '@material-ui/core/Typography';
import ExpandLess from '@material-ui/icons/ExpandLess';
import ExpandMore from '@material-ui/icons/ExpandMore';
import Breadcrumbs from '@material-ui/core/Breadcrumbs';
import { Route, MemoryRouter } from 'react-router';
import { Link as RouterLink } from 'react-router-dom';
import { Omit } from '@material-ui/core';
interface ListItemLinkProps extends LinkProps {
to: string;
open?: boolean;
}
const breadcrumbNameMap: { [key: string]: string } = {
'/inbox': 'Inbox',
'/inbox/important': 'Important',
'/trash': 'Trash',
'/spam': 'Spam',
'/drafts': 'Drafts',
};
function ListItemLink(props: Omit<ListItemLinkProps, 'ref'>) {
const { to, open, ...other } = props;
const primary = breadcrumbNameMap[to];
return (
<li>
<ListItem button component={RouterLink} to={to} {...other}>
<ListItemText primary={primary} />
{open != null ? open ? <ExpandLess /> : <ExpandMore /> : null}
</ListItem>
</li>
);
}
ListItemLink.propTypes = {
open: PropTypes.bool,
to: PropTypes.string.isRequired,
};
const useStyles = makeStyles((theme: Theme) =>
createStyles({
root: {
display: 'flex',
flexDirection: 'column',
width: 360,
},
lists: {
backgroundColor: theme.palette.background.paper,
marginTop: theme.spacing(1),
},
nested: {
paddingLeft: theme.spacing(4),
},
}),
);
interface LinkRouterProps extends LinkProps {
to: string;
replace?: boolean;
}
const LinkRouter = (props: LinkRouterProps) => <Link {...props} component={RouterLink as any} />;
function RouterBreadcrumbs() {
const classes = useStyles();
const [open, setOpen] = React.useState(true);
function handleClick() {
setOpen(prevOpen => !prevOpen);
}
// Use NoSsr to avoid SEO issues with the documentation website.
return (
<NoSsr>
<MemoryRouter initialEntries={['/inbox']} initialIndex={0}>
<div className={classes.root}>
<Route>
{({ location }) => {
const pathnames = location.pathname.split('/').filter(x => x);
return (
<Breadcrumbs aria-label="Breadcrumb">
<LinkRouter color="inherit" to="/">
Home
</LinkRouter>
{pathnames.map((value, index) => {
const last = index === pathnames.length - 1;
const to = `/${pathnames.slice(0, index + 1).join('/')}`;
return last ? (
<Typography color="textPrimary" key={to}>
{breadcrumbNameMap[to]}
</Typography>
) : (
<LinkRouter color="inherit" to={to} key={to}>
{breadcrumbNameMap[to]}
</LinkRouter>
);
})}
</Breadcrumbs>
);
}}
</Route>
<div className={classes.lists}>
<List component="nav">
<ListItemLink to="/inbox" open={open} onClick={handleClick} />
<Collapse in={open} timeout="auto" unmountOnExit>
<List component="div" disablePadding>
<ListItemLink to="/inbox/important" className={classes.nested} />
</List>
</Collapse>
<ListItemLink to="/trash" />
<ListItemLink to="/spam" />
</List>
</div>
</div>
</MemoryRouter>
</NoSsr>
);
}
export default RouterBreadcrumbs;