56 lines
1.9 KiB
TypeScript
Raw Normal View History

import * as React from 'react';
import { Route, Switch, useRouteMatch, useLocation } from 'react-router-dom';
import { useHistory, Redirect } from 'react-router';
import { Tabs } from 'antd';
import { TabsProps } from 'antd/lib/tabs';
const { TabPane } = Tabs;
interface Props extends TabsProps {
defaultPath: string;
tabs: Array<{
name: string;
path: string;
content: React.ReactNode;
}>;
}
/**
* A tab view where each tab is associated with a route mounted on top of the current path.
* This permits direct navigation to a particular tab via URL.
*/
export const RoutedTabs = ({ defaultPath, tabs, ...props }: Props) => {
const { path, url } = useRouteMatch();
const { pathname } = useLocation();
const history = useHistory();
const subRoutes = tabs.map((tab) => tab.path.replace('/', ''));
const trimmedPathName = pathname.endsWith('/') ? pathname.slice(0, pathname.length - 1) : pathname;
const splitPathName = trimmedPathName.split('/');
const providedPath = splitPathName[splitPathName.length - 1];
const activePath = subRoutes.includes(providedPath) ? providedPath : defaultPath.replace('/', '');
return (
<div>
<Tabs
defaultActiveKey={activePath}
size="large"
onChange={(newPath) => history.push(`${url}/${newPath}`)}
{...props}
>
{tabs.map((tab) => (
<TabPane tab={tab.name} key={tab.path.replace('/', '')} />
))}
</Tabs>
<Switch>
<Route exact path={path}>
<Redirect to={`${pathname}${pathname.endsWith('/') ? '' : '/'}${defaultPath}`} />
</Route>
{tabs.map((tab) => (
<Route exact path={`${path}/${tab.path.replace('/', '')}`} render={() => tab.content} />
))}
</Switch>
</div>
);
};