Exposing Material-UI extension point from tab components on HeaderTabs so additional information can be added to them

Signed-off-by: Jussi Hallila <jussi@hallila.com>
This commit is contained in:
Jussi Hallila
2021-02-19 09:47:00 +01:00
parent 3b2d4d421a
commit d8cc7e67a3
6 changed files with 54 additions and 4 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/core': patch
---
Exposing Material UI extension point for tabs to be able to add additional information to them
@@ -48,7 +48,12 @@ export const RoutedTabs = ({ routes }: { routes: SubRoute[] }) => {
const navigate = useNavigate();
const { index, route, element } = useSelectedSubRoute(routes);
const headerTabs = useMemo(
() => routes.map(t => ({ id: t.path, label: t.title })),
() =>
routes.map(t => ({
id: t.path,
label: t.title,
tabProps: t.tabProps,
})),
[routes],
);
@@ -23,11 +23,13 @@ import React, {
ReactNode,
} from 'react';
import { RoutedTabs } from './RoutedTabs';
import { TabProps } from '@material-ui/core';
type SubRoute = {
path: string;
title: string;
children: JSX.Element;
tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;
};
const Route: (props: SubRoute) => null = () => null;
@@ -60,8 +62,8 @@ export function createSubRoutesFromChildren(
throw new Error('Child of TabbedLayout must be an TabbedLayout.Route');
}
const { path, title, children } = child.props;
return [{ path, title, children }];
const { path, title, children, tabProps } = child.props;
return [{ path, title, children, tabProps }];
});
}
@@ -14,8 +14,12 @@
* limitations under the License.
*/
import { TabProps } from '@material-ui/core';
import * as React from 'react';
export type SubRoute = {
path: string;
title: string;
children: JSX.Element;
tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;
};
@@ -17,6 +17,7 @@
import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
import { HeaderTabs } from './';
import { Badge, makeStyles } from '@material-ui/core';
const mockTabs = [
{ id: 'overview', label: 'Overview' },
@@ -46,4 +47,35 @@ describe('<HeaderTabs />', () => {
'true',
);
});
it('should render extension component to tab if one present', async () => {
const useStyles = makeStyles(() => ({
badge: {
margin: '20px 20px 0 0',
},
}));
const TextualBadge = React.forwardRef<HTMLSpanElement>((props, ref) => (
<Badge
classes={useStyles()}
color="secondary"
badgeContent="three new alarms"
>
<span ref={ref} {...props}>
{props.children}
</span>
</Badge>
));
const iconTab = [
{
id: 'icon-tab',
label: 'Alarms',
tabProps: { component: TextualBadge },
},
];
const rendered = await renderInTestApp(<HeaderTabs tabs={iconTab} />);
expect(rendered.getByText('Alarms')).toBeInTheDocument();
expect(rendered.getByText('three new alarms')).toBeInTheDocument();
});
});
@@ -18,7 +18,7 @@
// This is just a temporary solution to implementing tabs for now
import React, { useState, useEffect } from 'react';
import { makeStyles, Tabs, Tab as TabUI } from '@material-ui/core';
import { makeStyles, Tabs, Tab as TabUI, TabProps } from '@material-ui/core';
const useStyles = makeStyles(theme => ({
tabsWrapper: {
@@ -41,6 +41,7 @@ const useStyles = makeStyles(theme => ({
export type Tab = {
id: string;
label: string;
tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;
};
type HeaderTabsProps = {
@@ -82,6 +83,7 @@ export const HeaderTabs = ({
>
{tabs.map((tab, index) => (
<TabUI
{...tab.tabProps}
label={tab.label}
key={tab.id}
value={index}