From 615b000acd0ae301a159e24bdc6e32f870aaf974 Mon Sep 17 00:00:00 2001 From: Tobias Skarhed <1438972+tskarhed@users.noreply.github.com> Date: Wed, 24 Jun 2020 16:58:40 +0200 Subject: [PATCH] Tab: Make active tab clickable and add hyperlink functionality (#25546) * onChangeTab for active tab and pointer mouse * Add anchor element to tab * Make a strict 'anchor' mode * Add short docs * Apply suggestions from code review Co-authored-by: Dominik Prokop * Fix nits Co-authored-by: Dominik Prokop --- .../grafana-ui/src/components/Tabs/Tab.tsx | 41 +++++++++++++------ .../src/components/Tabs/TabsBar.mdx | 7 +++- .../core/components/PageHeader/PageHeader.tsx | 1 + 3 files changed, 34 insertions(+), 15 deletions(-) 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} /> ) );