rename component for list-item-text-icon
[arvados-workbench2.git] / src / components / side-panel / side-panel.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import * as React from 'react';
6 import { ReactElement } from 'react';
7 import { StyleRulesCallback, WithStyles, withStyles } from '@material-ui/core/styles';
8 import { ArvadosTheme } from '../../common/custom-theme';
9 import { List, ListItem, ListItemText, ListItemIcon, Collapse, Typography } from "@material-ui/core";
10 import { SidePanelRightArrowIcon, IconType } from '../icon/icon';
11 import * as classnames from "classnames";
12 import ListItemTextIcon from '../list-item-text-icon/list-item-text-icon';
13
14 export interface SidePanelItem {
15     id: string;
16     name: string;
17     icon: IconType;
18     active?: boolean;
19     open?: boolean;
20     margin?: boolean;
21     openAble?: boolean;
22 }
23
24 interface SidePanelProps {
25     toggleOpen: (id: string) => void;
26     toggleActive: (id: string) => void;
27     sidePanelItems: SidePanelItem[];
28     onContextMenu: (event: React.MouseEvent<HTMLElement>, item: SidePanelItem) => void;
29 }
30
31 class SidePanel extends React.Component<SidePanelProps & WithStyles<CssRules>> {
32     render(): ReactElement<any> {
33         const { classes, toggleOpen, toggleActive, sidePanelItems, children } = this.props;
34         const { root, row, list, toggableIconContainer } = classes;
35         return (
36             <div className={root}>
37                 <List>
38                     {sidePanelItems.map(it => (
39                         <span key={it.name}>
40                             <ListItem button className={list} onClick={() => toggleActive(it.id)} onContextMenu={this.handleRowContextMenu(it)}>
41                                 <span className={row}>
42                                     {it.openAble ? (
43                                         <i onClick={() => toggleOpen(it.id)} className={toggableIconContainer}>
44                                             <ListItemIcon className={this.getToggableIconClassNames(it.open, it.active)}>
45                                                 < SidePanelRightArrowIcon />
46                                             </ListItemIcon>
47                                         </i>
48                                     ) : null}
49                                     <ListItemTextIcon icon={it.icon} name={it.name} isActive={it.active} hasMargin={it.margin} />
50                                 </span>
51                             </ListItem>
52                             {it.openAble ? (
53                                 <Collapse in={it.open} timeout="auto" unmountOnExit>
54                                     {children}
55                                 </Collapse>
56                             ) : null}
57                         </span>
58                     ))}
59                 </List>
60             </div>
61         );
62     }
63
64     getToggableIconClassNames = (isOpen?: boolean, isActive ?: boolean) => {
65         const { classes } = this.props;
66         return classnames(classes.toggableIcon, {
67             [classes.iconOpen]: isOpen,
68             [classes.iconClose]: !isOpen,
69             [classes.active]: isActive
70         });
71     }
72
73     handleRowContextMenu = (item: SidePanelItem) =>
74         (event: React.MouseEvent<HTMLElement>) =>
75             item.openAble ? this.props.onContextMenu(event, item) : null
76
77 }
78
79 type CssRules = 'active' | 'row' | 'root' | 'list' | 'iconClose' | 'iconOpen' | 'toggableIconContainer' | 'toggableIcon';
80
81 const styles: StyleRulesCallback<CssRules> = (theme: ArvadosTheme) => ({
82     root: {
83         overflowY: 'auto',
84         minWidth: '240px',
85         whiteSpace: 'nowrap',
86         marginTop: '52px',
87         display: 'flex',
88         flexGrow: 1,
89     },
90     list: {
91         padding: '5px 0px 5px 14px',
92         minWidth: '240px',
93     },
94     row: {
95         display: 'flex',
96         alignItems: 'center',
97     },
98     toggableIconContainer: {
99         color: theme.palette.grey["700"],
100         height: '14px',
101         position: 'absolute'
102     },
103     toggableIcon: {
104         fontSize: '14px'
105     },
106     active: {
107         color: theme.palette.primary.main,
108     },
109     iconClose: {
110         transition: 'all 0.1s ease',
111     },
112     iconOpen: {
113         transition: 'all 0.1s ease',
114         transform: 'rotate(90deg)',
115     }
116 });
117
118 export default withStyles(styles)(SidePanel);