Tab: Only make `Tab` an anchor if a `href` is passed (#78540)

* initial work

* only make the tab an anchor if it has a href

* move things around for smaller diff

* use content()

* eslint-disable the type assertions

* extract props into common object and add missing return statement
pull/78544/head
Ashley Harrison 2 years ago committed by GitHub
parent 778841cabe
commit 5355131aed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 58
      packages/grafana-ui/src/components/Tabs/Tab.tsx
  2. 2
      packages/grafana-ui/src/components/index.ts
  3. 2
      public/app/features/alerting/unified/PanelAlertTab.tsx

@ -7,26 +7,29 @@ import { selectors } from '@grafana/e2e-selectors';
import { useStyles2 } from '../../themes';
import { getFocusStyles } from '../../themes/mixins';
import { IconName } from '../../types';
import { clearButtonStyles } from '../Button';
import { Icon } from '../Icon/Icon';
import { Counter } from './Counter';
export interface TabProps extends HTMLProps<HTMLAnchorElement> {
export interface TabProps extends HTMLProps<HTMLElement> {
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?: (event?: React.MouseEvent<HTMLAnchorElement>) => void;
onChangeTab?: (event: React.MouseEvent<HTMLElement>) => void;
/** A number rendered next to the text. Usually used to display the number of items in a tab's view. */
counter?: number | null;
/** Extra content, displayed after the tab label and counter */
suffix?: NavModelItem['tabSuffix'];
}
export const Tab = React.forwardRef<HTMLAnchorElement, TabProps>(
export const Tab = React.forwardRef<HTMLElement, TabProps>(
({ label, active, icon, onChangeTab, counter, suffix: Suffix, className, href, ...otherProps }, ref) => {
const tabsStyles = useStyles2(getStyles);
const clearStyles = useStyles2(clearButtonStyles);
const content = () => (
<>
{icon && <Icon name={icon} />}
@ -36,23 +39,44 @@ export const Tab = React.forwardRef<HTMLAnchorElement, TabProps>(
</>
);
const linkClass = cx(tabsStyles.link, active ? tabsStyles.activeStyle : tabsStyles.notActive);
const linkClass = cx(clearStyles, tabsStyles.link, active ? tabsStyles.activeStyle : tabsStyles.notActive);
const commonProps = {
className: linkClass,
...otherProps,
onClick: onChangeTab,
'aria-label': otherProps['aria-label'] || selectors.components.Tab.title(label),
role: 'tab',
'aria-selected': active,
};
if (href) {
return (
<div className={tabsStyles.item}>
<a
{...commonProps}
href={href}
// don't think we can avoid the type assertion here :(
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
ref={ref as React.ForwardedRef<HTMLAnchorElement>}
>
{content()}
</a>
</div>
);
}
return (
<div className={tabsStyles.item}>
<a
// in case there is no href '#' is set in order to maintain a11y
href={href ? href : '#'}
className={linkClass}
{...otherProps}
onClick={onChangeTab}
aria-label={otherProps['aria-label'] || selectors.components.Tab.title(label)}
role="tab"
aria-selected={active}
ref={ref}
<button
{...commonProps}
type="button"
// don't think we can avoid the type assertion here :(
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
ref={ref as React.ForwardedRef<HTMLButtonElement>}
>
{content()}
</a>
</button>
</div>
);
}
@ -108,10 +132,6 @@ const getStyles = (theme: GrafanaTheme2) => {
color: theme.colors.text.primary,
overflow: 'hidden',
a: {
color: theme.colors.text.primary,
},
'&::before': {
backgroundImage: theme.colors.gradients.brandHorizontal,
},

@ -100,7 +100,7 @@ export {
} from './Table/types';
export { TableInputCSV } from './TableInputCSV/TableInputCSV';
export { TabsBar } from './Tabs/TabsBar';
export { Tab } from './Tabs/Tab';
export { Tab, type TabProps } from './Tabs/Tab';
export { VerticalTab } from './Tabs/VerticalTab';
export { TabContent } from './Tabs/TabContent';
export { Counter } from './Tabs/Counter';

@ -1,6 +1,6 @@
import React from 'react';
import { Tab, TabProps } from '@grafana/ui/src/components/Tabs/Tab';
import { Tab, TabProps } from '@grafana/ui';
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
import { usePanelCombinedRules } from './hooks/usePanelCombinedRules';

Loading…
Cancel
Save