diff --git a/packages/grafana-ui/src/components/Tabs/Tab.tsx b/packages/grafana-ui/src/components/Tabs/Tab.tsx index db912795a56..00127d38261 100644 --- a/packages/grafana-ui/src/components/Tabs/Tab.tsx +++ b/packages/grafana-ui/src/components/Tabs/Tab.tsx @@ -11,31 +11,41 @@ import { Counter } from './Counter'; export interface TabProps extends HTMLProps { label: string; active?: boolean; + /** When provided, it is possible to use the tab as a hyperlink. Use in cases where the tabs update location. */ + href?: string; icon?: IconName; - onChangeTab: () => void; + onChangeTab: (event?: React.MouseEvent) => void; + /** A number rendered next to the text. Usually used to display the number of items in a tab's view. */ counter?: number; } export const Tab = React.forwardRef( - ({ label, active, icon, onChangeTab, counter, className, ...otherProps }, ref) => { + ({ label, active, icon, onChangeTab, counter, className, href, ...otherProps }, ref) => { const theme = useTheme(); const tabsStyles = getTabStyles(theme); + const content = () => ( + <> + {icon && } + {label} + {typeof counter === 'number' && } + + ); return (
  • { - if (!active) { - onChangeTab(); - } - }} + className={cx(!href && tabsStyles.padding, tabsStyles.tabItem, active && tabsStyles.activeStyle)} + onClick={onChangeTab} aria-label={otherProps['aria-label'] || selectors.components.Tab.title(label)} ref={ref} > - {icon && } - {label} - {typeof counter === 'number' && } + {href ? ( + + {content()} + + ) : ( + <>{content()} + )}
  • ); } @@ -47,7 +57,6 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => { return { tabItem: css` list-style: none; - padding: 11px 15px 9px; margin-right: ${theme.spacing.md}; position: relative; display: block; @@ -61,18 +70,24 @@ const getTabStyles = stylesFactory((theme: GrafanaTheme) => { margin-right: ${theme.spacing.sm}; } + a { + display: block; + height: 100%; + } &:hover, &:focus { color: ${colors.linkHover}; } `, + padding: css` + padding: 11px 15px 9px; + `, activeStyle: css` label: activeTabStyle; border-color: ${theme.palette.orange} ${colors.pageHeaderBorder} transparent; background: ${colors.bodyBg}; color: ${colors.link}; overflow: hidden; - cursor: default; &::before { display: block; diff --git a/packages/grafana-ui/src/components/Tabs/TabsBar.mdx b/packages/grafana-ui/src/components/Tabs/TabsBar.mdx index db304fed246..7679164f0fd 100644 --- a/packages/grafana-ui/src/components/Tabs/TabsBar.mdx +++ b/packages/grafana-ui/src/components/Tabs/TabsBar.mdx @@ -1,9 +1,12 @@ import { Props } from '@storybook/addon-docs/blocks'; -import { TabsBar } from './TabsBar' +import { TabsBar } from './TabsBar'; # TabBar -A composition component for rendering a TabBar with Tabs for navigation +A composition component for rendering a TabBar with Tabs for navigation. +It has two modes - navigation and onClick. Navigation renders it as a simple `` element. To enable it, use the `href` prop. The onClick mode uses an onClick handler instead. To enable it, use the `onChangeTab` prop. + +**Warning!** Using `href` and `onChangeTab` at the same time may have unintended consequences. diff --git a/public/app/core/components/PageHeader/PageHeader.tsx b/public/app/core/components/PageHeader/PageHeader.tsx index 8253d5c671f..7739fb5c6cc 100644 --- a/public/app/core/components/PageHeader/PageHeader.tsx +++ b/public/app/core/components/PageHeader/PageHeader.tsx @@ -79,6 +79,7 @@ const Navigation = ({ children }: { children: NavModelItem[] }) => { key={`${child.url}-${index}`} icon={child.icon as IconName} onChangeTab={() => goToUrl(index)} + href={child.url} /> ) );