Chore: Further reduce usage of v1 theme (#53423)

This commit is contained in:
kay delaney
2022-08-09 14:58:32 +01:00
committed by GitHub
parent f4a5e034b3
commit 96403236cb
30 changed files with 291 additions and 291 deletions

View File

@@ -1,25 +1,24 @@
import { css } from '@emotion/css';
import React, { memo, PropsWithChildren } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme, stylesFactory } from '../../../themes';
import { useStyles2 } from '../../../themes';
const getStyle = stylesFactory((theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
text: css`
font-size: ${theme.typography.size.md};
font-weight: ${theme.typography.weight.semibold};
color: ${theme.colors.formLabel};
font-weight: ${theme.typography.fontWeightMedium};
color: ${theme.colors.text.primary};
margin: 0;
display: flex;
`,
};
});
};
export const TimePickerTitle = memo<PropsWithChildren<{}>>(({ children }) => {
const theme = useTheme();
const styles = getStyle(theme);
const styles = useStyles2(getStyles);
return <h3 className={styles.text}>{children}</h3>;
});

View File

@@ -1,17 +1,16 @@
import { css } from '@emotion/css';
import React, { PropsWithChildren, useMemo } from 'react';
import { GrafanaTheme, TimeZoneInfo } from '@grafana/data';
import { GrafanaTheme2, TimeZoneInfo } from '@grafana/data';
import { useTheme, stylesFactory } from '../../../themes';
import { useStyles2 } from '../../../themes';
interface Props {
info?: TimeZoneInfo;
}
export const TimeZoneDescription: React.FC<PropsWithChildren<Props>> = ({ info }) => {
const theme = useTheme();
const styles = getStyles(theme);
const styles = useStyles2(getStyles);
const description = useDescription(info);
if (!info) {
@@ -42,14 +41,14 @@ const useDescription = (info?: TimeZoneInfo): string => {
}, [info]);
};
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
description: css`
font-weight: normal;
font-size: ${theme.typography.size.sm};
color: ${theme.colors.textWeak};
color: ${theme.colors.text.secondary};
white-space: normal;
text-overflow: ellipsis;
`,
};
});
};

View File

@@ -1,9 +1,9 @@
import { css } from '@emotion/css';
import React, { PropsWithChildren } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme, stylesFactory } from '../../../themes';
import { useStyles2 } from '../../../themes';
interface Props {
label: string | undefined;
@@ -12,9 +12,8 @@ interface Props {
const stopPropagation = (event: React.MouseEvent) => event.stopPropagation();
export const TimeZoneGroup: React.FC<PropsWithChildren<Props>> = (props) => {
const theme = useTheme();
const { children, label } = props;
const styles = getStyles(theme);
const styles = useStyles2(getStyles);
if (!label) {
return <div onClick={stopPropagation}>{children}</div>;
@@ -30,18 +29,18 @@ export const TimeZoneGroup: React.FC<PropsWithChildren<Props>> = (props) => {
);
};
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
header: css`
padding: 7px 10px;
width: 100%;
border-top: 1px solid ${theme.colors.border1};
border-top: 1px solid ${theme.colors.border.weak};
text-transform: capitalize;
`,
label: css`
font-size: ${theme.typography.size.sm};
color: ${theme.colors.textWeak};
font-weight: ${theme.typography.weight.semibold};
color: ${theme.colors.text.secondary};
font-weight: ${theme.typography.fontWeightMedium};
`,
};
});
};

View File

@@ -2,9 +2,9 @@ import { css, cx } from '@emotion/css';
import { isString } from 'lodash';
import React, { PropsWithChildren } from 'react';
import { GrafanaTheme, TimeZone, dateTimeFormat } from '@grafana/data';
import { GrafanaTheme2, TimeZone, dateTimeFormat } from '@grafana/data';
import { useTheme, stylesFactory } from '../../../themes';
import { useStyles2 } from '../../../themes';
interface Props {
timestamp: number;
@@ -13,9 +13,8 @@ interface Props {
}
export const TimeZoneOffset: React.FC<PropsWithChildren<Props>> = (props) => {
const theme = useTheme();
const { timestamp, timeZone, className } = props;
const styles = getStyles(theme);
const styles = useStyles2(getStyles);
if (!isString(timeZone)) {
return null;
@@ -40,22 +39,22 @@ export const formatUtcOffset = (timestamp: number, timeZone: TimeZone): string =
return `UTC${offset}`;
};
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
const textBase = css`
font-weight: normal;
font-size: ${theme.typography.size.sm};
color: ${theme.colors.textWeak};
color: ${theme.colors.text.secondary};
white-space: normal;
`;
return {
offset: css`
${textBase};
color: ${theme.colors.text};
background: ${theme.colors.bg2};
color: ${theme.colors.text.primary};
background: ${theme.colors.background.secondary};
padding: 2px 5px;
border-radius: 2px;
margin-left: 4px;
`,
};
});
};

View File

@@ -1,17 +1,16 @@
import { css } from '@emotion/css';
import React, { ReactNode } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme, stylesFactory } from '../../../themes';
import { useStyles2 } from '../../../themes';
interface Props {
title: string | ReactNode;
}
export const TimeZoneTitle: React.FC<Props> = ({ title }) => {
const theme = useTheme();
const styles = getStyles(theme);
const styles = useStyles2(getStyles);
if (!title) {
return null;
@@ -20,11 +19,11 @@ export const TimeZoneTitle: React.FC<Props> = ({ title }) => {
return <span className={styles.title}>{title}</span>;
};
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
title: css`
font-weight: ${theme.typography.weight.regular};
font-weight: ${theme.typography.fontWeightRegular};
text-overflow: ellipsis;
`,
};
});
};

View File

@@ -1,16 +1,16 @@
import { css, cx } from '@emotion/css';
import React, { FC, HTMLProps, ReactNode } from 'react';
import React, { HTMLProps, ReactNode } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles } from '../../themes';
import { useStyles2 } from '../../themes';
export interface Props extends Omit<HTMLProps<HTMLDivElement>, 'css'> {
children: ReactNode | ReactNode[];
}
export const InlineFieldRow: FC<Props> = ({ children, className, ...htmlProps }) => {
const styles = useStyles(getStyles);
export const InlineFieldRow = ({ children, className, ...htmlProps }: Props) => {
const styles = useStyles2(getStyles);
return (
<div className={cx(styles.container, className)} {...htmlProps}>
{children}
@@ -18,7 +18,7 @@ export const InlineFieldRow: FC<Props> = ({ children, className, ...htmlProps })
);
};
const getStyles = (theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
container: css`
label: InlineFieldRow;
@@ -26,7 +26,7 @@ const getStyles = (theme: GrafanaTheme) => {
flex-direction: row;
flex-wrap: wrap;
align-content: flex-start;
row-gap: ${theme.spacing.xs};
row-gap: ${theme.spacing(0.5)};
`,
};
};

View File

@@ -1,9 +1,9 @@
import { css, cx } from '@emotion/css';
import React, { FunctionComponent } from 'react';
import React, { FunctionComponent, useCallback } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme } from '../../themes';
import { useStyles2 } from '../../themes';
import { Icon } from '../Icon/Icon';
import { PopoverContent, Tooltip } from '../Tooltip';
@@ -34,8 +34,10 @@ export const InlineLabel: FunctionComponent<Props> = ({
as: Component = 'label',
...rest
}) => {
const theme = useTheme();
const styles = getInlineLabelStyles(theme, transparent, width);
const styles = useStyles2(
useCallback((theme) => getInlineLabelStyles(theme, transparent, width), [transparent, width])
);
return (
<Component className={cx(styles.label, className)} {...rest}>
{children}
@@ -48,31 +50,31 @@ export const InlineLabel: FunctionComponent<Props> = ({
);
};
export const getInlineLabelStyles = (theme: GrafanaTheme, transparent = false, width?: number | 'auto') => {
export const getInlineLabelStyles = (theme: GrafanaTheme2, transparent = false, width?: number | 'auto') => {
return {
label: css`
display: flex;
align-items: center;
justify-content: space-between;
flex-shrink: 0;
padding: 0 ${theme.spacing.sm};
font-weight: ${theme.typography.weight.semibold};
padding: 0 ${theme.spacing(1)};
font-weight: ${theme.typography.fontWeightMedium};
font-size: ${theme.typography.size.sm};
background-color: ${transparent ? 'transparent' : theme.colors.bg2};
height: ${theme.height.md}px;
line-height: ${theme.height.md}px;
margin-right: ${theme.spacing.xs};
border-radius: ${theme.border.radius.md};
background-color: ${transparent ? 'transparent' : theme.colors.background.secondary};
height: ${theme.spacing(theme.components.height.md)};
line-height: ${theme.spacing(theme.components.height.md)};
margin-right: ${theme.spacing(0.5)};
border-radius: ${theme.shape.borderRadius(2)};
border: none;
width: ${width ? (width !== 'auto' ? `${8 * width}px` : width) : '100%'};
color: ${theme.colors.textHeading};
color: ${theme.colors.text.primary};
`,
icon: css`
color: ${theme.colors.textWeak};
color: ${theme.colors.text.secondary};
margin-left: 10px;
:hover {
color: ${theme.colors.text};
color: ${theme.colors.text.primary};
}
`,
};

View File

@@ -1,9 +1,9 @@
import { cx, css } from '@emotion/css';
import React, { FC } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme } from '../../themes';
import { useStyles2 } from '../../themes';
export interface Props {
grow?: boolean;
@@ -12,8 +12,7 @@ export interface Props {
/** @beta */
export const InlineSegmentGroup: FC<Props> = ({ children, className, grow, ...htmlProps }) => {
const theme = useTheme();
const styles = getStyles(theme, grow);
const styles = useStyles2((theme) => getStyles(theme, grow));
return (
<div className={cx(styles.container, className)} {...htmlProps}>
@@ -24,7 +23,7 @@ export const InlineSegmentGroup: FC<Props> = ({ children, className, grow, ...ht
InlineSegmentGroup.displayName = 'InlineSegmentGroup';
const getStyles = (theme: GrafanaTheme, grow?: boolean) => {
const getStyles = (theme: GrafanaTheme2, grow?: boolean) => {
return {
container: css`
display: flex;
@@ -33,7 +32,7 @@ const getStyles = (theme: GrafanaTheme, grow?: boolean) => {
text-align: left;
position: relative;
flex: ${grow ? 1 : 0} 0 auto;
margin-bottom: ${theme.spacing.xs};
margin-bottom: ${theme.spacing(0.5)};
`,
};
};

View File

@@ -1,28 +1,27 @@
import { css, cx } from '@emotion/css';
import React, { ReactNode } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme, stylesFactory } from '../../themes';
import { useStyles2 } from '../../themes';
export interface LabelProps extends React.HTMLAttributes<HTMLLegendElement> {
children: string | ReactNode;
description?: string;
}
export const getLegendStyles = stylesFactory((theme: GrafanaTheme) => {
export const getLegendStyles = (theme: GrafanaTheme2) => {
return {
legend: css`
font-size: ${theme.typography.heading.h3};
font-weight: ${theme.typography.weight.regular};
margin: 0 0 ${theme.spacing.md} 0;
font-size: ${theme.typography.h3.fontSize};
font-weight: ${theme.typography.fontWeightRegular};
margin: 0 0 ${theme.spacing(2)} 0;
`,
};
});
};
export const Legend: React.FC<LabelProps> = ({ children, className, ...legendProps }) => {
const theme = useTheme();
const styles = getLegendStyles(theme);
const styles = useStyles2(getLegendStyles);
return (
<legend className={cx(styles.legend, className)} {...legendProps}>

View File

@@ -8,9 +8,10 @@ import {
dateTimeFormat,
TimeZone,
FormattedValue,
GrafanaTheme2,
} from '@grafana/data';
import { useTheme } from '../../themes';
import { useStyles2 } from '../../themes';
import { ContextMenu, ContextMenuProps } from '../ContextMenu/ContextMenu';
import { FormattedValueDisplay } from '../FormattedValueDisplay/FormattedValueDisplay';
import { HorizontalGroup } from '../Layout/Layout';
@@ -113,31 +114,32 @@ export const GraphContextMenuHeader = ({
displayName: string;
displayValue: FormattedValue;
}) => {
const theme = useTheme();
const styles = useStyles2(getStyles);
return (
<div
className={css`
padding: ${theme.spacing.xs} ${theme.spacing.sm};
font-size: ${theme.typography.size.sm};
z-index: ${theme.zIndex.tooltip};
`}
>
<div className={styles.wrapper}>
<strong>{timestamp}</strong>
<HorizontalGroup>
<div>
<SeriesIcon color={seriesColor} />
<span
className={css`
white-space: nowrap;
padding-left: ${theme.spacing.xs};
`}
>
{displayName}
</span>
<span className={styles.displayName}>{displayName}</span>
</div>
{displayValue && <FormattedValueDisplay value={displayValue} />}
</HorizontalGroup>
</div>
);
};
function getStyles(theme: GrafanaTheme2) {
return {
wrapper: css`
padding: ${theme.spacing(0.5)} ${theme.spacing(1)};
font-size: ${theme.typography.size.sm};
z-index: ${theme.zIndex.tooltip};
`,
displayName: css`
white-space: nowrap;
padding-left: ${theme.spacing(0.5)};
`,
};
}

View File

@@ -4,7 +4,7 @@ import React, { ChangeEvent, useState } from 'react';
import { Input, Field, Icon } from '@grafana/ui';
import { useTheme } from '../../themes';
import { useTheme2 } from '../../themes';
import { getAvailableIcons, IconName } from '../../types';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
@@ -25,8 +25,8 @@ const meta: ComponentMeta<typeof Icon> = {
};
const IconWrapper = ({ name }: { name: IconName }) => {
const theme = useTheme();
const borderColor = theme.colors.border2;
const theme = useTheme2();
const borderColor = theme.colors.border.medium;
return (
<div
@@ -46,7 +46,7 @@ const IconWrapper = ({ name }: { name: IconName }) => {
className={css`
padding-top: 16px;
word-break: break-all;
font-family: ${theme.typography.fontFamily.monospace};
font-family: ${theme.typography.fontFamilyMonospace};
font-size: ${theme.typography.size.xs};
`}
>

View File

@@ -2,10 +2,9 @@ import { css, cx } from '@emotion/css';
import React from 'react';
import SVG from 'react-inlinesvg';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useTheme } from '../../themes/ThemeContext';
import { stylesFactory } from '../../themes/stylesFactory';
import { useStyles2 } from '../../themes/ThemeContext';
import { IconName, IconType, IconSize } from '../../types/icon';
import { cacheInitialized, initIconCache, iconRoot } from './iconBundle';
@@ -18,7 +17,7 @@ export interface IconProps extends React.HTMLAttributes<HTMLDivElement> {
title?: string;
}
const getIconStyles = stylesFactory((theme: GrafanaTheme) => {
const getIconStyles = (theme: GrafanaTheme2) => {
return {
// line-height: 0; is needed for correct icon alignment in Safari
container: css`
@@ -32,14 +31,14 @@ const getIconStyles = stylesFactory((theme: GrafanaTheme) => {
fill: currentColor;
`,
orange: css`
fill: ${theme.palette.orange};
fill: ${theme.v1.palette.orange};
`,
};
});
};
export const Icon = React.forwardRef<HTMLDivElement, IconProps>(
({ size = 'md', type = 'default', name, className, style, title = '', ...divElementProps }, ref) => {
const theme = useTheme();
const styles = useStyles2(getIconStyles);
/* Temporary solution to display also font awesome icons */
if (name?.startsWith('fa fa-')) {
@@ -54,7 +53,6 @@ export const Icon = React.forwardRef<HTMLDivElement, IconProps>(
initIconCache();
}
const styles = getIconStyles(theme);
const svgSize = getSvgSize(size);
const svgHgt = svgSize;
const svgWid = name?.startsWith('gf-bar-align') ? 16 : name?.startsWith('gf-interp') ? 30 : svgSize;

View File

@@ -1,9 +1,9 @@
import { css } from '@emotion/css';
import React from 'react';
import { FeatureState, GrafanaTheme } from '@grafana/data';
import { FeatureState, GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useStyles } from '../../themes';
import { useStyles2 } from '../../themes';
import { Badge, BadgeProps } from '../Badge/Badge';
import { InfoBox, InfoBoxProps } from './InfoBox';
@@ -16,7 +16,7 @@ export interface FeatureInfoBoxProps extends Omit<InfoBoxProps, 'title' | 'urlTi
/** @deprecated use Alert with severity info */
export const FeatureInfoBox = React.memo(
React.forwardRef<HTMLDivElement, FeatureInfoBoxProps>(({ title, featureState, ...otherProps }, ref) => {
const styles = useStyles(getFeatureInfoBoxStyles);
const styles = useStyles2(getFeatureInfoBoxStyles);
const titleEl = featureState ? (
<>
@@ -34,13 +34,13 @@ export const FeatureInfoBox = React.memo(
FeatureInfoBox.displayName = 'FeatureInfoBox';
const getFeatureInfoBoxStyles = stylesFactory((theme: GrafanaTheme) => {
const getFeatureInfoBoxStyles = (theme: GrafanaTheme2) => {
return {
badge: css`
margin-bottom: ${theme.spacing.sm};
margin-bottom: ${theme.spacing(1)};
`,
};
});
};
interface FeatureBadgeProps {
featureState: FeatureState;

View File

@@ -1,9 +1,9 @@
import { css, cx } from '@emotion/css';
import React, { HTMLProps } from 'react';
import React, { HTMLProps, useCallback } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme } from '../../themes';
import { useStyles2 } from '../../themes';
enum Orientation {
Horizontal,
@@ -41,8 +41,13 @@ export const Layout: React.FC<LayoutProps> = ({
height = '100%',
...rest
}) => {
const theme = useTheme();
const styles = getStyles(theme, orientation, spacing, justify, align, wrap);
const styles = useStyles2(
useCallback(
(theme) => getStyles(theme, orientation, spacing, justify, align, wrap),
[align, justify, orientation, spacing, wrap]
)
);
return (
<div className={styles.layout} style={{ width, height }} {...rest}>
{React.Children.toArray(children)
@@ -100,8 +105,8 @@ export const VerticalGroup: React.FC<Omit<LayoutProps, 'orientation' | 'wrap'>>
);
export const Container: React.FC<ContainerProps> = ({ children, padding, margin, grow, shrink }) => {
const theme = useTheme();
const styles = getContainerStyles(theme, padding, margin);
const styles = useStyles2(useCallback((theme) => getContainerStyles(theme, padding, margin), [padding, margin]));
return (
<div
className={cx(
@@ -121,49 +126,61 @@ export const Container: React.FC<ContainerProps> = ({ children, padding, margin,
);
};
const getStyles = stylesFactory(
(theme: GrafanaTheme, orientation: Orientation, spacing: Spacing, justify: Justify, align, wrap) => {
const finalSpacing = spacing !== 'none' ? theme.spacing[spacing] : 0;
// compensate for last row margin when wrapped, horizontal layout
const marginCompensation =
(orientation === Orientation.Horizontal && !wrap) || orientation === Orientation.Vertical
? 0
: `-${finalSpacing}`;
const getStyles = (
theme: GrafanaTheme2,
orientation: Orientation,
spacing: Spacing,
justify: Justify,
align: Align,
wrap: boolean
) => {
const finalSpacing = spacing !== 'none' ? theme.spacing(spacingToNumber[spacing]) : 0;
const label = orientation === Orientation.Vertical ? 'vertical-group' : 'horizontal-group';
// compensate for last row margin when wrapped, horizontal layout
const marginCompensation =
(orientation === Orientation.Horizontal && !wrap) || orientation === Orientation.Vertical ? 0 : `-${finalSpacing}`;
return {
layout: css`
label: ${label};
display: flex;
flex-direction: ${orientation === Orientation.Vertical ? 'column' : 'row'};
flex-wrap: ${wrap ? 'wrap' : 'nowrap'};
justify-content: ${justify};
align-items: ${align};
height: 100%;
max-width: 100%;
// compensate for last row margin when wrapped, horizontal layout
margin-bottom: ${marginCompensation};
`,
childWrapper: css`
label: layoutChildrenWrapper;
margin-bottom: ${orientation === Orientation.Horizontal && !wrap ? 0 : finalSpacing};
margin-right: ${orientation === Orientation.Horizontal ? finalSpacing : 0};
display: flex;
align-items: ${align};
const label = orientation === Orientation.Vertical ? 'vertical-group' : 'horizontal-group';
&:last-child {
margin-bottom: ${orientation === Orientation.Vertical && 0};
margin-right: ${orientation === Orientation.Horizontal && 0};
}
`,
};
}
);
return {
layout: css`
label: ${label};
display: flex;
flex-direction: ${orientation === Orientation.Vertical ? 'column' : 'row'};
flex-wrap: ${wrap ? 'wrap' : 'nowrap'};
justify-content: ${justify};
align-items: ${align};
height: 100%;
max-width: 100%;
// compensate for last row margin when wrapped, horizontal layout
margin-bottom: ${marginCompensation};
`,
childWrapper: css`
label: layoutChildrenWrapper;
margin-bottom: ${orientation === Orientation.Horizontal && !wrap ? 0 : finalSpacing};
margin-right: ${orientation === Orientation.Horizontal ? finalSpacing : 0};
display: flex;
align-items: ${align};
const getContainerStyles = stylesFactory((theme: GrafanaTheme, padding?: Spacing, margin?: Spacing) => {
const paddingSize = (padding && padding !== 'none' && theme.spacing[padding]) || 0;
const marginSize = (margin && margin !== 'none' && theme.spacing[margin]) || 0;
&:last-child {
margin-bottom: ${orientation === Orientation.Vertical && 0};
margin-right: ${orientation === Orientation.Horizontal && 0};
}
`,
};
};
const spacingToNumber: Record<Spacing, number> = {
none: 0,
xs: 0.5,
sm: 1,
md: 2,
lg: 3,
};
const getContainerStyles = (theme: GrafanaTheme2, padding?: Spacing, margin?: Spacing) => {
const paddingSize = (padding && padding !== 'none' && theme.spacing(spacingToNumber[padding])) || 0;
const marginSize = (margin && margin !== 'none' && theme.spacing(spacingToNumber[margin])) || 0;
return {
wrapper: css`
label: container;
@@ -171,4 +188,4 @@ const getContainerStyles = stylesFactory((theme: GrafanaTheme, padding?: Spacing
padding: ${paddingSize};
`,
};
});
};

View File

@@ -1,9 +1,9 @@
import { css, cx } from '@emotion/css';
import React, { HTMLAttributes, SFC } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles } from '../../themes';
import { useStyles2 } from '../../themes';
import { Spinner } from '../Spinner/Spinner';
/**
@@ -17,7 +17,7 @@ export interface LoadingPlaceholderProps extends HTMLAttributes<HTMLDivElement>
* @public
*/
export const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text, className, ...rest }) => {
const styles = useStyles(getStyles);
const styles = useStyles2(getStyles);
return (
<div className={cx(styles.container, className)} {...rest}>
{text} <Spinner inline={true} />
@@ -25,10 +25,10 @@ export const LoadingPlaceholder: SFC<LoadingPlaceholderProps> = ({ text, classNa
);
};
const getStyles = (theme: GrafanaTheme) => {
const getStyles = (theme: GrafanaTheme2) => {
return {
container: css`
margin-bottom: ${theme.spacing.xl};
margin-bottom: ${theme.spacing(4)};
`,
};
};

View File

@@ -1,36 +1,36 @@
import { css } from '@emotion/css';
import React, { PureComponent } from 'react';
import { LogLabelStatsModel, GrafanaTheme } from '@grafana/data';
import { LogLabelStatsModel, GrafanaTheme2 } from '@grafana/data';
import { stylesFactory } from '../../themes';
import { withTheme } from '../../themes/index';
import { Themeable } from '../../types/theme';
import { withTheme2 } from '../../themes/index';
import { Themeable2 } from '../../types/theme';
//Components
import { LogLabelStatsRow } from './LogLabelStatsRow';
const STATS_ROW_LIMIT = 5;
const getStyles = stylesFactory((theme: GrafanaTheme) => {
const getStyles = stylesFactory((theme: GrafanaTheme2) => {
return {
logsStats: css`
label: logs-stats;
background: inherit;
color: ${theme.colors.text};
color: ${theme.colors.text.primary};
word-break: break-all;
width: fit-content;
max-width: 100%;
`,
logsStatsHeader: css`
label: logs-stats__header;
border-bottom: 1px solid ${theme.colors.border2};
border-bottom: 1px solid ${theme.colors.border.medium};
display: flex;
`,
logsStatsTitle: css`
label: logs-stats__title;
font-weight: ${theme.typography.weight.semibold};
padding-right: ${theme.spacing.d};
font-weight: ${theme.typography.fontWeightMedium};
padding-right: ${theme.spacing(2)};
display: inline-block;
white-space: nowrap;
text-overflow: ellipsis;
@@ -47,7 +47,7 @@ const getStyles = stylesFactory((theme: GrafanaTheme) => {
};
});
interface Props extends Themeable {
interface Props extends Themeable2 {
stats: LogLabelStatsModel[];
label: string;
value: string;
@@ -96,5 +96,5 @@ class UnThemedLogLabelStats extends PureComponent<Props> {
}
}
export const LogLabelStats = withTheme(UnThemedLogLabelStats);
export const LogLabelStats = withTheme2(UnThemedLogLabelStats);
LogLabelStats.displayName = 'LogLabelStats';

View File

@@ -1,18 +1,18 @@
import { css, cx } from '@emotion/css';
import React, { FunctionComponent } from 'react';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { useStyles } from '../../themes/ThemeContext';
import { useStyles2 } from '../../themes/ThemeContext';
const getStyles = (theme: GrafanaTheme) => ({
const getStyles = (theme: GrafanaTheme2) => ({
logsStatsRow: css`
label: logs-stats-row;
margin: ${parseInt(theme.spacing.d, 10) / 1.75}px 0;
margin: ${parseInt(theme.spacing(2), 10) / 1.75}px 0;
`,
logsStatsRowActive: css`
label: logs-stats-row--active;
color: ${theme.colors.textBlue};
color: ${theme.colors.primary.text};
position: relative;
`,
logsStatsRowLabel: css`
@@ -41,13 +41,13 @@ const getStyles = (theme: GrafanaTheme) => ({
label: logs-stats-row__bar;
height: 4px;
overflow: hidden;
background: ${theme.colors.textFaint};
background: ${theme.colors.text.disabled};
`,
logsStatsRowInnerBar: css`
label: logs-stats-row__innerbar;
height: 4px;
overflow: hidden;
background: ${theme.colors.bgBlue1};
background: ${theme.colors.primary.main};
`,
});
@@ -59,7 +59,7 @@ export interface Props {
}
export const LogLabelStatsRow: FunctionComponent<Props> = ({ active, count, proportion, value }) => {
const style = useStyles(getStyles);
const style = useStyles2(getStyles);
const percent = `${Math.round(proportion * 100)}%`;
const barStyle = { width: percent };
const className = active ? cx([style.logsStatsRow, style.logsStatsRowActive]) : cx([style.logsStatsRow]);

View File

@@ -1,28 +1,26 @@
import { render, screen } from '@testing-library/react';
import React from 'react';
import { getTheme } from '../../themes';
import { UnThemedLogLabels as LogLabels } from './LogLabels';
import { LogLabels } from './LogLabels';
describe('<LogLabels />', () => {
it('renders notice when no labels are found', () => {
render(<LogLabels labels={{}} theme={getTheme()} />);
render(<LogLabels labels={{}} />);
expect(screen.queryByText('(no unique labels)')).toBeInTheDocument();
});
it('renders labels', () => {
render(<LogLabels labels={{ foo: 'bar', baz: '42' }} theme={getTheme()} />);
render(<LogLabels labels={{ foo: 'bar', baz: '42' }} />);
expect(screen.queryByText('bar')).toBeInTheDocument();
expect(screen.queryByText('42')).toBeInTheDocument();
});
it('excludes labels with certain names or labels starting with underscore', () => {
render(<LogLabels labels={{ foo: 'bar', level: '42', _private: '13' }} theme={getTheme()} />);
render(<LogLabels labels={{ foo: 'bar', level: '42', _private: '13' }} />);
expect(screen.queryByText('bar')).toBeInTheDocument();
expect(screen.queryByText('42')).not.toBeInTheDocument();
expect(screen.queryByText('13')).not.toBeInTheDocument();
});
it('excludes labels with empty string values', () => {
render(<LogLabels labels={{ foo: 'bar', baz: '' }} theme={getTheme()} />);
render(<LogLabels labels={{ foo: 'bar', baz: '' }} />);
expect(screen.queryByText('bar')).toBeInTheDocument();
expect(screen.queryByText('baz')).not.toBeInTheDocument();
});

View File

@@ -1,49 +1,19 @@
import { css, cx } from '@emotion/css';
import React, { FunctionComponent } from 'react';
import { GrafanaTheme, Labels } from '@grafana/data';
import { GrafanaTheme2, Labels } from '@grafana/data';
import { stylesFactory } from '../../themes';
import { withTheme } from '../../themes/ThemeContext';
import { Themeable } from '../../types/theme';
import { useStyles2 } from '../../themes/ThemeContext';
// Levels are already encoded in color, filename is a Loki-ism
const HIDDEN_LABELS = ['level', 'lvl', 'filename'];
const getStyles = stylesFactory((theme: GrafanaTheme) => {
return {
logsLabels: css`
display: flex;
flex-wrap: wrap;
font-size: ${theme.typography.size.xs};
`,
logsLabel: css`
label: logs-label;
display: flex;
padding: 0 2px;
background-color: ${theme.colors.bg2};
border-radius: ${theme.border.radius};
margin: 1px 4px 0 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
`,
logsLabelValue: css`
label: logs-label__value;
display: inline-block;
max-width: 20em;
text-overflow: ellipsis;
overflow: hidden;
`,
};
});
interface Props extends Themeable {
interface Props {
labels: Labels;
}
export const UnThemedLogLabels: FunctionComponent<Props> = ({ labels, theme }) => {
const styles = getStyles(theme);
export const LogLabels: FunctionComponent<Props> = ({ labels }) => {
const styles = useStyles2(getStyles);
const displayLabels = Object.keys(labels).filter((label) => !label.startsWith('_') && !HIDDEN_LABELS.includes(label));
if (displayLabels.length === 0) {
@@ -74,5 +44,30 @@ export const UnThemedLogLabels: FunctionComponent<Props> = ({ labels, theme }) =
);
};
export const LogLabels = withTheme(UnThemedLogLabels);
LogLabels.displayName = 'LogLabels';
const getStyles = (theme: GrafanaTheme2) => {
return {
logsLabels: css`
display: flex;
flex-wrap: wrap;
font-size: ${theme.typography.size.xs};
`,
logsLabel: css`
label: logs-label;
display: flex;
padding: 0 2px;
background-color: ${theme.colors.background.secondary};
border-radius: ${theme.shape.borderRadius(1)};
margin: 1px 4px 0 0;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
`,
logsLabelValue: css`
label: logs-label__value;
display: inline-block;
max-width: 20em;
text-overflow: ellipsis;
overflow: hidden;
`,
};
};

View File

@@ -1,9 +1,9 @@
import { css, cx } from '@emotion/css';
import React, { useRef, useState, useLayoutEffect, useEffect } from 'react';
import { GrafanaTheme, DataQueryError, LogRowModel, textUtil } from '@grafana/data';
import { GrafanaTheme2, DataQueryError, LogRowModel, textUtil } from '@grafana/data';
import { useStyles, useTheme } from '../../themes/ThemeContext';
import { useStyles2 } from '../../themes/ThemeContext';
import { Alert } from '../Alert/Alert';
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
import { CustomScrollbar } from '../CustomScrollbar/CustomScrollbar';
@@ -22,7 +22,7 @@ interface LogRowContextProps {
onLoadMoreContext: () => void;
}
const getLogRowContextStyles = (theme: GrafanaTheme, wrapLogMessage?: boolean) => {
const getLogRowContextStyles = (theme: GrafanaTheme2, wrapLogMessage?: boolean) => {
/**
* This is workaround for displaying uncropped context when we have unwrapping log messages.
* We are using margins to correctly position context. Because non-wrapped logs have always 1 line of log
@@ -53,10 +53,10 @@ const getLogRowContextStyles = (theme: GrafanaTheme, wrapLogMessage?: boolean) =
height: 250px;
z-index: ${theme.zIndex.dropdown};
overflow: hidden;
background: ${theme.colors.bg1};
box-shadow: 0 0 10px ${theme.colors.dropdownShadow};
border: 1px solid ${theme.colors.bg2};
border-radius: ${theme.border.radius.md};
background: ${theme.colors.background.primary};
box-shadow: 0 0 10px ${theme.v1.palette.black};
border: 1px solid ${theme.colors.background.secondary};
border-radius: ${theme.shape.borderRadius(2)};
width: 100%;
`,
header: css`
@@ -64,7 +64,7 @@ const getLogRowContextStyles = (theme: GrafanaTheme, wrapLogMessage?: boolean) =
padding: 0 10px;
display: flex;
align-items: center;
background: ${theme.colors.bg2};
background: ${theme.colors.background.secondary};
`,
logs: css`
height: 220px;
@@ -94,7 +94,7 @@ const LogRowContextGroupHeader: React.FunctionComponent<LogRowContextGroupHeader
onLoadMoreContext,
canLoadMoreRows,
}) => {
const { header } = useStyles(getLogRowContextStyles);
const { header } = useStyles2(getLogRowContextStyles);
return (
<div className={header}>
@@ -132,7 +132,7 @@ export const LogRowContextGroup: React.FunctionComponent<LogRowContextGroupProps
canLoadMoreRows,
onLoadMoreContext,
}) => {
const { commonStyles, logs } = useStyles(getLogRowContextStyles);
const { commonStyles, logs } = useStyles2(getLogRowContextStyles);
const [scrollTop, setScrollTop] = useState(0);
const listContainerRef = useRef<HTMLDivElement>() as React.RefObject<HTMLDivElement>;
@@ -204,8 +204,7 @@ export const LogRowContext: React.FunctionComponent<LogRowContextProps> = ({
document.removeEventListener('keydown', handleEscKeyDown, false);
};
}, [onOutsideClick]);
const theme = useTheme();
const { afterContext, beforeContext } = getLogRowContextStyles(theme, wrapLogMessage);
const { afterContext, beforeContext } = useStyles2((theme) => getLogRowContextStyles(theme, wrapLogMessage));
return (
<ClickOutsideWrapper onClick={onOutsideClick}>

View File

@@ -3,12 +3,12 @@ import React, { PureComponent } from 'react';
import { LogRowModel, Field, LinkModel } from '@grafana/data';
import { withTheme } from '../../themes/index';
import { Themeable } from '../../types/theme';
import { withTheme2 } from '../../themes/index';
import { Themeable2 } from '../../types/theme';
import { getAllFields } from './logParser';
export interface Props extends Themeable {
export interface Props extends Themeable2 {
row: LogRowModel;
showDetectedFields: string[];
wrapLogMessage: boolean;
@@ -45,5 +45,5 @@ class UnThemedLogRowMessageDetectedFields extends PureComponent<Props> {
}
}
export const LogRowMessageDetectedFields = withTheme(UnThemedLogRowMessageDetectedFields);
export const LogRowMessageDetectedFields = withTheme2(UnThemedLogRowMessageDetectedFields);
LogRowMessageDetectedFields.displayName = 'LogRowMessageDetectedFields';

View File

@@ -2,9 +2,9 @@ import { css } from '@emotion/css';
import { GrafanaTheme2, LogLevel } from '@grafana/data';
import { styleMixins, stylesFactory } from '../../themes';
import { styleMixins } from '../../themes';
export const getLogRowStyles = stylesFactory((theme: GrafanaTheme2, logLevel?: LogLevel) => {
export const getLogRowStyles = (theme: GrafanaTheme2, logLevel?: LogLevel) => {
let logColor = theme.isLight ? theme.v1.palette.gray5 : theme.v1.palette.gray2;
const hoverBgColor = styleMixins.hoverColor(theme.colors.background.secondary, theme);
@@ -77,8 +77,8 @@ export const getLogRowStyles = stylesFactory((theme: GrafanaTheme2, logLevel?: L
> td {
position: relative;
padding-right: ${theme.spacing(1)};
border-top: ${theme.v1.border.width.sm} solid transparent;
border-bottom: ${theme.v1.border.width.sm} solid transparent;
border-top: 1px solid transparent;
border-bottom: 1px solid transparent;
height: 100%;
}
@@ -182,4 +182,4 @@ export const getLogRowStyles = stylesFactory((theme: GrafanaTheme2, logLevel?: L
}
`,
};
});
};

View File

@@ -5,7 +5,6 @@ import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Link } from '..';
import { styleMixins } from '../../themes';
import { useStyles2 } from '../../themes/ThemeContext';
import { getFocusStyles } from '../../themes/mixins';
import { IconName } from '../../types';
@@ -173,7 +172,7 @@ const getStyles = (theme: GrafanaTheme2) => {
`,
pageIcon: css`
display: none;
@media ${styleMixins.mediaUp(theme.v1.breakpoints.md)} {
${theme.breakpoints.up('md')} {
display: flex;
padding-right: ${theme.spacing(1)};
align-items: center;
@@ -221,7 +220,7 @@ const getStyles = (theme: GrafanaTheme2) => {
`,
parentLink: css`
display: none;
@media ${styleMixins.mediaUp(theme.v1.breakpoints.md)} {
${theme.breakpoints.up('md')} {
display: unset;
}
`,
@@ -230,7 +229,7 @@ const getStyles = (theme: GrafanaTheme2) => {
`,
leftActionItem: css`
display: none;
@media ${styleMixins.mediaUp(theme.v1.breakpoints.md)} {
${theme.breakpoints.up('md')} {
align-items: center;
display: flex;
padding-left: ${spacing(0.5)};

View File

@@ -1,9 +1,8 @@
import { css, cx } from '@emotion/css';
import React from 'react';
import { GrafanaTheme } from '@grafana/data';
import { useStyles } from '../../themes';
import { useStyles2 } from '../../themes';
import { commonColorsPalette } from '../../themes/default';
import { Icon } from '../Icon/Icon';
import { Tooltip } from '../Tooltip/Tooltip';
@@ -19,7 +18,7 @@ export type ErrorIndicatorProps = {
* @internal
*/
export const ErrorIndicator: React.FC<ErrorIndicatorProps> = ({ error, onClick }) => {
const styles = useStyles(getStyles);
const styles = useStyles2(getStyles);
if (!error) {
return null;
@@ -37,13 +36,13 @@ export const ErrorIndicator: React.FC<ErrorIndicatorProps> = ({ error, onClick }
);
};
const getStyles = (theme: GrafanaTheme) => {
const getStyles = () => {
return {
clickable: css`
cursor: pointer;
`,
icon: css`
color: ${theme.palette.red88};
color: ${commonColorsPalette.red88};
`,
};
};

View File

@@ -3,7 +3,7 @@ import React from 'react';
import { selectors } from '@grafana/e2e-selectors';
import { useStyles } from '../../themes';
import { useStyles2 } from '../../themes';
import { Icon } from '../Icon/Icon';
import { Tooltip } from '../Tooltip/Tooltip';
@@ -19,7 +19,7 @@ export type LoadingIndicatorProps = {
* @internal
*/
export const LoadingIndicator: React.FC<LoadingIndicatorProps> = ({ onCancel, loading }) => {
const styles = useStyles(getStyles);
const styles = useStyles2(getStyles);
if (!loading) {
return null;

View File

@@ -3,8 +3,8 @@ import { merge } from 'lodash';
import React, { CSSProperties, useState } from 'react';
import { useInterval } from 'react-use';
import { GrafanaTheme } from '@grafana/data';
import { PanelChrome, useTheme, PanelChromeProps } from '@grafana/ui';
import { GrafanaTheme2 } from '@grafana/data';
import { PanelChrome, useTheme2, PanelChromeProps } from '@grafana/ui';
import { withCenteredStory } from '../../utils/storybook/withCenteredStory';
import { HorizontalGroup, VerticalGroup } from '../Layout/Layout';
@@ -18,7 +18,7 @@ const meta: ComponentMeta<typeof PanelChrome> = {
},
};
function renderPanel(name: string, overrides: Partial<PanelChromeProps>, theme: GrafanaTheme) {
function renderPanel(name: string, overrides: Partial<PanelChromeProps>, theme: GrafanaTheme2) {
const props: PanelChromeProps = {
width: 400,
height: 130,
@@ -29,7 +29,7 @@ function renderPanel(name: string, overrides: Partial<PanelChromeProps>, theme:
merge(props, overrides);
const contentStyle: CSSProperties = {
background: theme.colors.bg2,
background: theme.colors.background.secondary,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
@@ -45,13 +45,13 @@ function renderPanel(name: string, overrides: Partial<PanelChromeProps>, theme:
}
export const Examples = () => {
const theme = useTheme();
const theme = useTheme2();
const [loading, setLoading] = useState(true);
useInterval(() => setLoading(true), 5000);
return (
<div style={{ background: theme.colors.dashboardBg, padding: 100 }}>
<div style={{ background: theme.colors.background.canvas, padding: 100 }}>
<HorizontalGroup spacing="md">
<VerticalGroup spacing="md">
{renderPanel('Default panel', {}, theme)}
@@ -66,7 +66,7 @@ export const Examples = () => {
)}
</VerticalGroup>
</HorizontalGroup>
<div style={{ marginTop: theme.spacing.md }} />
<div style={{ marginTop: theme.spacing(2) }} />
<HorizontalGroup spacing="md">
<VerticalGroup spacing="md">
{renderPanel(

View File

@@ -1,20 +1,17 @@
import { css } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes';
import { useStyles2 } from '../../themes';
interface InputGroupProps {}
export const InputGroup: React.FC<InputGroupProps> = ({ children }) => {
const theme = useTheme2();
const styles = useStyles(theme);
const styles = useStyles2(getStyles);
return <div className={styles.root}>{children}</div>;
};
const useStyles = stylesFactory((theme: GrafanaTheme2) => ({
const getStyles = () => ({
root: css({
display: 'flex',
@@ -51,4 +48,4 @@ const useStyles = stylesFactory((theme: GrafanaTheme2) => ({
},
},
}),
}));
});

View File

@@ -1,9 +1,9 @@
import { css } from '@emotion/css';
import React, { CSSProperties } from 'react';
import React, { CSSProperties, useCallback } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, useTheme2 } from '../../themes';
import { useStyles2 } from '../../themes';
interface StackProps {
direction?: CSSProperties['flexDirection'];
@@ -13,13 +13,12 @@ interface StackProps {
}
export const Stack: React.FC<StackProps> = ({ children, ...props }) => {
const theme = useTheme2();
const styles = useStyles(theme, props);
const styles = useStyles2(useCallback((theme) => getStyles(theme, props), [props]));
return <div className={styles.root}>{children}</div>;
};
const useStyles = stylesFactory((theme: GrafanaTheme2, props: StackProps) => ({
const getStyles = (theme: GrafanaTheme2, props: StackProps) => ({
root: css({
display: 'flex',
flexDirection: props.direction ?? 'row',
@@ -27,4 +26,4 @@ const useStyles = stylesFactory((theme: GrafanaTheme2, props: StackProps) => ({
alignItems: props.alignItems,
gap: theme.spacing(props.gap ?? 2),
}),
}));
});

View File

@@ -1,8 +1,10 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data';
export const getSegmentStyles = (theme: GrafanaTheme | GrafanaTheme2) => {
const palette = 'v1' in theme ? theme.v1.palette : theme.palette;
export const getSegmentStyles = (theme: GrafanaTheme2) => {
return {
segment: css`
cursor: pointer;
@@ -10,7 +12,7 @@ export const getSegmentStyles = (theme: GrafanaTheme2) => {
`,
queryPlaceholder: css`
color: ${theme.v1.palette.gray2};
color: ${palette.gray2};
`,
disabled: css`

View File

@@ -2,13 +2,13 @@ import { css } from '@emotion/css';
import React, { PureComponent } from 'react';
import { GroupProps } from 'react-select';
import { GrafanaTheme } from '@grafana/data';
import { GrafanaTheme2 } from '@grafana/data';
import { stylesFactory, withTheme } from '../../themes';
import { Themeable } from '../../types';
import { stylesFactory, withTheme2 } from '../../themes';
import { Themeable2 } from '../../types';
import { Icon } from '../Icon/Icon';
interface ExtendedGroupProps extends Omit<GroupProps<any, any>, 'theme'>, Themeable {
interface ExtendedGroupProps extends Omit<GroupProps<any, any>, 'theme'>, Themeable2 {
data: {
label: string;
expanded: boolean;
@@ -20,7 +20,7 @@ interface State {
expanded: boolean;
}
const getSelectOptionGroupStyles = stylesFactory((theme: GrafanaTheme) => {
const getSelectOptionGroupStyles = stylesFactory((theme: GrafanaTheme2) => {
return {
header: css`
display: flex;
@@ -30,10 +30,10 @@ const getSelectOptionGroupStyles = stylesFactory((theme: GrafanaTheme) => {
cursor: pointer;
padding: 7px 10px;
width: 100%;
border-bottom: 1px solid ${theme.colors.bg2};
border-bottom: 1px solid ${theme.colors.background.secondary};
&:hover {
color: ${theme.colors.textStrong};
color: ${theme.colors.text.maxContrast};
}
`,
label: css`
@@ -91,4 +91,4 @@ class UnthemedSelectOptionGroup extends PureComponent<ExtendedGroupProps, State>
}
}
export const SelectOptionGroup = withTheme(UnthemedSelectOptionGroup);
export const SelectOptionGroup = withTheme2(UnthemedSelectOptionGroup);