[Panel] Extract styling duplication in new TitleItem component (#61625)

This commit is contained in:
Alexa V
2023-01-19 11:03:56 +00:00
committed by GitHub
parent f38e2856d8
commit 134ca6bb8f
7 changed files with 103 additions and 96 deletions
@@ -181,7 +181,7 @@ const ZoomOutTooltip = () => (
</>
);
const TimePickerTooltip = ({ timeRange, timeZone }: { timeRange: TimeRange; timeZone?: TimeZone }) => {
export const TimePickerTooltip = ({ timeRange, timeZone }: { timeRange: TimeRange; timeZone?: TimeZone }) => {
const styles = useStyles2(getLabelStyles);
return (
@@ -1,20 +1,17 @@
import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme2 } from '../../themes';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { Icon } from '../Icon/Icon';
import { Tooltip } from '../Tooltip';
import { TitleItem } from './TitleItem';
interface Props {
description: string | (() => string);
}
export function PanelDescription({ description }: Props) {
const theme = useTheme2();
const styles = getStyles(theme);
const styles = getStyles();
const getDescriptionContent = (): JSX.Element => {
// description
@@ -29,39 +26,16 @@ export function PanelDescription({ description }: Props) {
return description !== '' ? (
<Tooltip interactive content={getDescriptionContent}>
<span className={styles.description}>
<Icon name="info-circle" size="lg" aria-label="description" />
</span>
<TitleItem className={styles.description}>
<Icon name="info-circle" size="lg" title="description" />
</TitleItem>
</Tooltip>
) : null;
}
const getStyles = (theme: GrafanaTheme2) => {
const getStyles = () => {
return {
description: css({
color: `${theme.colors.text.secondary}`,
backgroundColor: `${theme.colors.background.primary}`,
cursor: 'auto',
border: 'none',
borderRadius: `${theme.shape.borderRadius()}`,
padding: `${theme.spacing(0, 1)}`,
height: ` ${theme.spacing(theme.components.height.md)}`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'&:focus, &:focus-visible': {
...getFocusStyles(theme),
zIndex: 1,
},
'&: focus:not(:focus-visible)': getMouseFocusStyles(theme),
'&:hover ': {
boxShadow: `${theme.shadows.z1}`,
color: `${theme.colors.text.primary}`,
background: `${theme.colors.background.secondary}`,
},
code: {
whiteSpace: 'normal',
wordWrap: 'break-word',
@@ -0,0 +1,75 @@
import { cx, css } from '@emotion/css';
import React, { forwardRef } from 'react';
import { GrafanaTheme2, LinkModel, LinkTarget } from '@grafana/data';
import { useStyles2 } from '../../themes';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
type TitleItemProps = {
className?: string;
children: React.ReactNode;
onClick?: LinkModel['onClick'];
href?: string;
target?: LinkTarget;
title?: string;
};
export const TitleItem = forwardRef<HTMLAnchorElement, TitleItemProps>(
({ className, children, href, onClick, target, title, ...rest }, ref) => {
const styles = useStyles2(getStyles);
if (href) {
return (
<a
ref={ref}
href={href}
onClick={onClick}
target={target}
title={title}
className={cx(styles.item, className)}
{...rest}
>
{children}
</a>
);
} else {
return (
<span ref={ref} className={cx(styles.item, className)} {...rest}>
{children}
</span>
);
}
}
);
TitleItem.displayName = 'TitleItem';
const getStyles = (theme: GrafanaTheme2) => {
return {
item: css({
color: `${theme.colors.text.secondary}`,
label: 'panel-header-item',
backgroundColor: `${theme.colors.background.primary}`,
cursor: 'auto',
border: 'none',
borderRadius: `${theme.shape.borderRadius()}`,
padding: `${theme.spacing(0, 1)}`,
height: `${theme.spacing(theme.components.height.md)}`,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
'&:focus, &:focus-visible': {
...getFocusStyles(theme),
zIndex: 1,
},
'&: focus:not(:focus-visible)': getMouseFocusStyles(theme),
'&:hover ': {
boxShadow: `${theme.shadows.z1}`,
background: `${theme.colors.background.secondary}`,
},
}),
};
};
@@ -3,6 +3,7 @@ import React from 'react';
import { ErrorIndicator } from './ErrorIndicator';
import { LoadingIndicator } from './LoadingIndicator';
import { PanelChrome as PanelChromeComponent, PanelChromeProps } from './PanelChrome';
import { TitleItem } from './TitleItem';
/**
* @internal
@@ -15,6 +16,7 @@ export type { PanelChromeProps, PanelPadding } from './PanelChrome';
export interface PanelChromeType extends React.FC<PanelChromeProps> {
LoadingIndicator: typeof LoadingIndicator;
ErrorIndicator: typeof ErrorIndicator;
TitleItem: typeof TitleItem;
}
/**
@@ -23,6 +25,7 @@ export interface PanelChromeType extends React.FC<PanelChromeProps> {
export const PanelChrome = PanelChromeComponent as PanelChromeType;
PanelChrome.LoadingIndicator = LoadingIndicator;
PanelChrome.ErrorIndicator = ErrorIndicator;
PanelChrome.TitleItem = TitleItem;
/**
* Exporting the components for extensibility and since it is a good practice
@@ -33,6 +33,7 @@ export { UnitPicker } from './UnitPicker/UnitPicker';
export { StatsPicker } from './StatsPicker/StatsPicker';
export { RefreshPicker, defaultIntervals } from './RefreshPicker/RefreshPicker';
export { TimeRangePicker, type TimeRangePickerProps } from './DateTimePickers/TimeRangePicker';
export { TimePickerTooltip } from './DateTimePickers/TimeRangePicker';
export { TimeOfDayPicker } from './DateTimePickers/TimeOfDayPicker';
export { TimeZonePicker } from './DateTimePickers/TimeZonePicker';
export { WeekStartPicker } from './DateTimePickers/WeekStartPicker';