NodeGraph: Show gradient fields in legend (#34078)
* Add gradient fields to legend * Fix test * Remove unnecessary mapping * Add tests
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { GrafanaTheme, GrafanaThemeType } from '../types/theme';
|
||||
|
||||
/**
|
||||
* @deprecated use theme.vizColors.getByName
|
||||
* @deprecated use theme.visualization.getColorByName
|
||||
*/
|
||||
export function getColorForTheme(color: string, theme: GrafanaTheme): string {
|
||||
return theme.visualization.getColorByName(color);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { SeriesIcon } from './SeriesIcon';
|
||||
|
||||
describe('SeriesIcon', () => {
|
||||
it('renders gradient correctly', () => {
|
||||
const { container } = render(<SeriesIcon gradient={'continuous-GrYlRd'} />);
|
||||
const div = container.firstChild! as HTMLDivElement;
|
||||
// There is issue in JSDOM which means we cannot actually get the gradient value. I guess if it's empty at least
|
||||
// we know it is setting some gradient instead of a single color.
|
||||
// https://github.com/jsdom/jsdom/issues/2166
|
||||
expect(div.style.getPropertyValue('background')).toBe('');
|
||||
});
|
||||
|
||||
it('renders color correctly', () => {
|
||||
const { container } = render(<SeriesIcon color={'red'} />);
|
||||
const div = container.firstChild! as HTMLDivElement;
|
||||
expect(div.style.getPropertyValue('background')).toBe('red');
|
||||
});
|
||||
});
|
||||
@@ -1,20 +1,40 @@
|
||||
import React, { CSSProperties } from 'react';
|
||||
import { useTheme2 } from '../../themes';
|
||||
import { fieldColorModeRegistry } from '@grafana/data';
|
||||
|
||||
export interface Props extends React.HTMLAttributes<HTMLDivElement> {
|
||||
color: string;
|
||||
color?: string;
|
||||
gradient?: string;
|
||||
}
|
||||
|
||||
export const SeriesIcon = React.forwardRef<HTMLDivElement, Props>(({ color, className, ...restProps }, ref) => {
|
||||
const styles: CSSProperties = {
|
||||
backgroundColor: color,
|
||||
width: '14px',
|
||||
height: '4px',
|
||||
borderRadius: '1px',
|
||||
display: 'inline-block',
|
||||
marginRight: '8px',
|
||||
};
|
||||
export const SeriesIcon = React.forwardRef<HTMLDivElement, Props>(
|
||||
({ color, className, gradient, ...restProps }, ref) => {
|
||||
const theme = useTheme2();
|
||||
let cssColor: string;
|
||||
|
||||
return <div ref={ref} className={className} style={styles} {...restProps} />;
|
||||
});
|
||||
if (gradient) {
|
||||
const colors = fieldColorModeRegistry.get(gradient).getColors?.(theme);
|
||||
if (colors?.length) {
|
||||
cssColor = `linear-gradient(90deg, ${colors.join(', ')})`;
|
||||
} else {
|
||||
// Not sure what to default to, this will return gray, this should not happen though.
|
||||
cssColor = theme.visualization.getColorByName('');
|
||||
}
|
||||
} else {
|
||||
cssColor = color!;
|
||||
}
|
||||
|
||||
const styles: CSSProperties = {
|
||||
background: cssColor,
|
||||
width: '14px',
|
||||
height: '4px',
|
||||
borderRadius: '1px',
|
||||
display: 'inline-block',
|
||||
marginRight: '8px',
|
||||
};
|
||||
|
||||
return <div ref={ref} className={className} style={styles} {...restProps} />;
|
||||
}
|
||||
);
|
||||
|
||||
SeriesIcon.displayName = 'SeriesIcon';
|
||||
|
||||
@@ -59,7 +59,7 @@ export const VizLegendListItem = <T extends unknown = any>({
|
||||
className={cx(styles.itemWrapper, className)}
|
||||
aria-label={selectors.components.VizLegend.seriesName(item.label)}
|
||||
>
|
||||
<VizLegendSeriesIcon seriesName={item.label} color={item.color} />
|
||||
<VizLegendSeriesIcon seriesName={item.label} color={item.color} gradient={item.gradient} />
|
||||
<div
|
||||
onMouseEnter={onMouseEnter}
|
||||
onMouseOut={onMouseOut}
|
||||
|
||||
@@ -5,13 +5,14 @@ import { SeriesIcon } from './SeriesIcon';
|
||||
|
||||
interface Props {
|
||||
seriesName: string;
|
||||
color: string;
|
||||
color?: string;
|
||||
gradient?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName, color }) => {
|
||||
export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName, color, gradient }) => {
|
||||
const { onSeriesColorChange } = usePanelContext();
|
||||
const onChange = useCallback(
|
||||
(color: string) => {
|
||||
@@ -20,7 +21,7 @@ export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName
|
||||
[seriesName, onSeriesColorChange]
|
||||
);
|
||||
|
||||
if (seriesName && onSeriesColorChange) {
|
||||
if (seriesName && onSeriesColorChange && color) {
|
||||
return (
|
||||
<SeriesColorPicker color={color} onChange={onChange} enableNamedColors>
|
||||
{({ ref, showColorPicker, hideColorPicker }) => (
|
||||
@@ -35,7 +36,7 @@ export const VizLegendSeriesIcon: React.FunctionComponent<Props> = ({ seriesName
|
||||
</SeriesColorPicker>
|
||||
);
|
||||
}
|
||||
return <SeriesIcon color={color} />;
|
||||
return <SeriesIcon color={color} gradient={gradient} />;
|
||||
};
|
||||
|
||||
VizLegendSeriesIcon.displayName = 'VizLegendSeriesIcon';
|
||||
|
||||
@@ -31,7 +31,8 @@ export interface LegendProps<T = any> extends VizLegendBaseProps<T>, VizLegendTa
|
||||
export interface VizLegendItem<T = any> {
|
||||
getItemKey?: () => string;
|
||||
label: string;
|
||||
color: string;
|
||||
color?: string;
|
||||
gradient?: string;
|
||||
yAxis: number;
|
||||
disabled?: boolean;
|
||||
// displayValues?: DisplayValue[];
|
||||
|
||||
Reference in New Issue
Block a user