Merge branch '21572-user-packages'
[arvados.git] / services / workbench2 / src / components / conditional-tabs / conditional-tabs.tsx
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 import React, { ReactElement, useEffect, useState } from "react";
6 import { Tabs, Tab } from "@material-ui/core";
7 import { TabsProps } from "@material-ui/core/Tabs";
8
9 interface ComponentWithHidden {
10     hidden: boolean;
11 };
12
13 export type TabData = {
14     show: boolean;
15     label: string;
16     content: ReactElement<ComponentWithHidden>;
17 };
18
19 type ConditionalTabsProps = {
20     tabs: TabData[];
21 };
22
23 export const ConditionalTabs = ({ tabs: tabData, ...props }: Omit<TabsProps, 'value' | 'onChange'> & ConditionalTabsProps) => {
24     const [tabState, setTabState] = useState(0);
25     const visibleTabs = tabData.filter(tab => tab.show);
26     const visibleTabNames = visibleTabs.map(tab => tab.label).join();
27
28     const handleTabChange = (event: React.MouseEvent<HTMLElement>, value: number) => {
29         setTabState(value);
30     };
31
32     // Reset tab to 0 when tab visibility changes
33     // (or if tab set change causes visible set to change)
34     useEffect(() => {
35         setTabState(0);
36     }, [visibleTabNames]);
37
38     return <>
39         <Tabs
40             {...props}
41             value={tabState}
42             onChange={handleTabChange} >
43             {visibleTabs.map(tab => <Tab key={tab.label} label={tab.label} />)}
44         </Tabs>
45
46         {visibleTabs.map((tab, i) => (
47             React.cloneElement(tab.content, {key: i, hidden: i !== tabState})
48         ))}
49     </>;
50 };