21842: stickied the tabs
[arvados.git] / services / workbench2 / src / components / tabbedList / tabbed-list.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React from 'react';
6 import { Tabs, Tab, List, ListItem, StyleRulesCallback, withStyles } from '@material-ui/core';
7 import { WithStyles } from '@material-ui/core';
8 import classNames from 'classnames';
9 import { ArvadosTheme } from 'common/custom-theme';
10
11 type TabbedListClasses = 'root' | 'tabs' | 'list';
12
13 const tabbedListStyles: StyleRulesCallback<TabbedListClasses> = (theme: ArvadosTheme) => ({
14     root: {
15       overflowY: 'auto',
16     },
17     tabs: {
18         backgroundColor: theme.palette.background.paper,
19         position: 'sticky',
20         top: 0,
21         zIndex: 1,
22         borderBotton: '1px solid lightgrey'
23     },
24     list: {
25         overflowY: 'scroll',
26     },
27 });
28
29 type SingleTabProps = {
30     label: string;
31     items: any[];
32 };
33
34 type TabbedListProps = {
35     tabbedListContents: SingleTabProps[];
36     renderListItem?: (item: any) => React.ReactNode;
37     injectedStyles?: string;
38 };
39
40 type TabPanelProps = {
41     children: React.ReactNode;
42     value: number;
43     index: number;
44 };
45
46 const TabPanel = ({ children, value, index }: TabPanelProps) => {
47     return <div hidden={value !== index}>{value === index && children}</div>;
48 };
49
50 export const TabbedList = withStyles(tabbedListStyles)(({ tabbedListContents, renderListItem, injectedStyles, classes }: TabbedListProps & WithStyles<TabbedListClasses>) => {
51     const [tabNr, setTabNr] = React.useState(0);
52
53     const handleChange = (event: React.SyntheticEvent, newValue: number) => {
54         event.preventDefault();
55         setTabNr(newValue);
56     };
57
58     return (
59         <div className={classNames(classes.root, injectedStyles)}>
60             <div className={classes.tabs}>
61                 <Tabs
62                     value={tabNr}
63                     onChange={handleChange}
64                     fullWidth
65                 >
66                     {tabbedListContents.map((tab) => (
67                         <Tab label={tab.label} />
68                     ))}
69                 </Tabs>
70             </div>
71             <TabPanel
72                 value={tabNr}
73                 index={tabNr}
74             >
75                 <List className={classes.list}>{tabbedListContents[tabNr].items.map((item) => (renderListItem ? renderListItem(item) : <ListItem>{item}</ListItem>))}</List>
76             </TabPanel>
77         </div>
78     );
79 });