Compare commits

...

1 Commits

Author SHA1 Message Date
Paul Marbach
ec42bbaba9 BigValue: Make height, width optional; remove graphMode 2026-01-09 13:07:41 -05:00
6 changed files with 100 additions and 43 deletions

View File

@@ -42,14 +42,7 @@ An example usage is in the [Stat panel](https://grafana.com/docs/grafana/latest/
```tsx
import { DisplayValue } from '@grafana/data';
import {
BigValue,
BigValueColorMode,
BigValueGraphMode,
BigValueJustifyMode,
BigValueTextMode,
useTheme,
} from '@grafana/ui';
import { BigValue, BigValueColorMode, BigValueJustifyMode, BigValueTextMode, useTheme } from '@grafana/ui';
const bigValue: DisplayValue = {
color: 'red',
@@ -62,7 +55,6 @@ return (
<BigValue
theme={useTheme()}
justifyMode={BigValueJustifyMode.Auto}
graphMode={BigValueGraphMode.Area}
colorMode={BigValueColorMode.Value}
textMode={BigValueTextMode.Auto}
value={bigValue}

View File

@@ -10,7 +10,7 @@ import {
BigValueGraphMode,
BigValueJustifyMode,
BigValueTextMode,
Props,
BigValueProps,
} from './BigValue';
import mdx from './BigValue.mdx';
@@ -58,7 +58,7 @@ const meta: Meta = {
},
};
interface StoryProps extends Props {
interface StoryProps extends BigValueProps {
numeric: number;
title: string;
color: string;
@@ -95,7 +95,6 @@ export const ApplyNoValue: StoryFn<StoryProps> = ({
width={width}
height={height}
colorMode={colorMode}
graphMode={graphMode}
textMode={textMode}
justifyMode={justifyMode}
value={{
@@ -109,6 +108,18 @@ export const ApplyNoValue: StoryFn<StoryProps> = ({
);
};
ApplyNoValue.args = {
valueText: '$5022',
title: 'Total Earnings',
colorMode: BigValueColorMode.Value,
graphMode: BigValueGraphMode.Area,
justifyMode: BigValueJustifyMode.Auto,
width: 400,
height: 300,
color: 'red',
textMode: BigValueTextMode.Auto,
};
export const Basic: StoryFn<StoryProps> = ({
valueText,
title,
@@ -137,7 +148,6 @@ export const Basic: StoryFn<StoryProps> = ({
width={width}
height={height}
colorMode={colorMode}
graphMode={graphMode}
textMode={textMode}
justifyMode={justifyMode}
value={{
@@ -163,14 +173,53 @@ Basic.args = {
textMode: BigValueTextMode.Auto,
};
ApplyNoValue.args = {
export const Flexible: StoryFn<StoryProps> = ({
valueText,
title,
colorMode,
graphMode,
height,
width,
color,
textMode,
justifyMode,
}) => {
const theme = useTheme2();
const sparkline: FieldSparkline = {
y: {
name: '',
values: [1, 2, 3, 4, 3],
type: FieldType.number,
state: { range: { min: 1, max: 4, delta: 3 } },
config: {},
},
};
return (
<BigValue
theme={theme}
colorMode={colorMode}
textMode={textMode}
justifyMode={justifyMode}
height={NaN}
width={NaN}
value={{
text: valueText,
numeric: 5022,
color: color,
title,
}}
sparkline={graphMode === BigValueGraphMode.None ? undefined : sparkline}
/>
);
};
Flexible.args = {
valueText: '$5022',
title: 'Total Earnings',
colorMode: BigValueColorMode.Value,
graphMode: BigValueGraphMode.Area,
justifyMode: BigValueJustifyMode.Auto,
width: 400,
height: 300,
color: 'red',
textMode: BigValueTextMode.Auto,
};

View File

@@ -2,7 +2,7 @@ import { render, screen } from '@testing-library/react';
import { createTheme } from '@grafana/data';
import { BigValue, BigValueColorMode, BigValueGraphMode, Props } from './BigValue';
import { BigValue, BigValueColorMode, BigValueProps } from './BigValue';
const valueObject = {
text: '25',
@@ -10,10 +10,9 @@ const valueObject = {
color: 'red',
};
function getProps(propOverrides?: Partial<Props>): Props {
const props: Props = {
function getProps(propOverrides?: Partial<BigValueProps>): BigValueProps {
const props: BigValueProps = {
colorMode: BigValueColorMode.Background,
graphMode: BigValueGraphMode.Line,
height: 300,
width: 300,
value: valueObject,

View File

@@ -1,5 +1,6 @@
import { cx } from '@emotion/css';
import { memo, type MouseEventHandler } from 'react';
import { useMeasure } from 'react-use';
import { DisplayValue, DisplayValueAlignmentFactors, FieldSparkline } from '@grafana/data';
import { PercentChangeColorMode, VizTextDisplayOptions } from '@grafana/schema';
@@ -18,6 +19,7 @@ export enum BigValueColorMode {
Value = 'value',
}
/** @deprecated use `sparkline` to configure the graph */
export enum BigValueGraphMode {
None = 'none',
Line = 'line',
@@ -40,11 +42,11 @@ export enum BigValueTextMode {
None = 'none',
}
export interface Props extends Themeable2 {
export interface BigValueProps extends Themeable2 {
/** Height of the component */
height: number;
height?: number;
/** Width of the component */
width: number;
width?: number;
/** Value displayed as Big Value */
value: DisplayValue;
/** Sparkline values for showing a graph under/behind the value */
@@ -55,8 +57,6 @@ export interface Props extends Themeable2 {
className?: string;
/** Color mode for coloring the value or the background */
colorMode: BigValueColorMode;
/** Show a graph behind/under the value */
graphMode: BigValueGraphMode;
/** Auto justify value and text or center it */
justifyMode?: BigValueJustifyMode;
/** Factors that should influence the positioning of the text */
@@ -80,6 +80,9 @@ export interface Props extends Themeable2 {
* Disable the wide layout for the BigValue
*/
disableWideLayout?: boolean;
/** @deprecated use `sparkline` to configure the graph */
graphMode?: BigValueGraphMode;
}
/**
@@ -87,10 +90,22 @@ export interface Props extends Themeable2 {
*
* https://developers.grafana.com/ui/latest/index.html?path=/docs/plugins-bigvalue--docs
*/
export const BigValue = memo<Props>((props) => {
const { onClick, className, hasLinks, theme, justifyMode = BigValueJustifyMode.Auto } = props;
export const BigValue = memo<BigValueProps>((props) => {
const {
onClick,
className,
hasLinks,
theme,
justifyMode = BigValueJustifyMode.Auto,
height: propsHeight,
width: propsWidth,
} = props;
const [wrapperRef, { width: calcWidth, height: calcHeight }] = useMeasure<HTMLDivElement>();
const layout = buildLayout({ ...props, justifyMode });
const height = propsHeight ?? calcHeight;
const width = propsWidth ?? calcWidth;
const layout = buildLayout({ ...props, justifyMode, height, width });
const panelStyles = layout.getPanelStyles();
const valueAndTitleContainerStyles = layout.getValueAndTitleContainerStyles();
const valueStyles = layout.getValueStyles();
@@ -105,7 +120,7 @@ export const BigValue = memo<Props>((props) => {
if (!onClick) {
return (
<div className={className} style={panelStyles} title={tooltip}>
<div ref={wrapperRef} className={className} style={panelStyles} title={tooltip}>
<div style={valueAndTitleContainerStyles}>
{textValues.title && <div style={titleStyles}>{textValues.title}</div>}
<FormattedValueDisplay value={textValues} style={valueStyles} />
@@ -129,7 +144,7 @@ export const BigValue = memo<Props>((props) => {
onClick={onClick}
title={tooltip}
>
<div style={valueAndTitleContainerStyles}>
<div ref={wrapperRef} style={valueAndTitleContainerStyles}>
{textValues.title && <div style={titleStyles}>{textValues.title}</div>}
<FormattedValueDisplay value={textValues} style={valueStyles} />
</div>

View File

@@ -3,19 +3,19 @@ import { CSSProperties } from 'react';
import { createTheme, FieldType } from '@grafana/data';
import { PercentChangeColorMode } from '@grafana/schema';
import { Props, BigValueColorMode, BigValueGraphMode, BigValueTextMode } from './BigValue';
import { BigValueProps, BigValueColorMode, BigValueTextMode } from './BigValue';
import {
buildLayout,
getPercentChangeColor,
StackedWithChartLayout,
StackedWithNoChartLayout,
WideWithChartLayout,
BigValuePropsWithHeightAndWidth,
} from './BigValueLayout';
function getProps(propOverrides?: Partial<Props>): Props {
const props: Props = {
function getProps(propOverrides?: Partial<BigValuePropsWithHeightAndWidth>): BigValuePropsWithHeightAndWidth {
const props: BigValuePropsWithHeightAndWidth = {
colorMode: BigValueColorMode.Background,
graphMode: BigValueGraphMode.Area,
height: 300,
width: 300,
value: {
@@ -105,7 +105,7 @@ describe('BigValueLayout', () => {
['wide layout', {}],
['non-wide layout', { disableWideLayout: true }],
])('should shrink the value if percent change is shown for %s', (_, propsOverride) => {
const baseProps: Partial<Props> = {
const baseProps: Partial<BigValueProps> = {
width: 300,
height: 100,
sparkline: undefined,

View File

@@ -9,13 +9,15 @@ import { getTextColorForAlphaBackground } from '../../utils/colors';
import { calculateFontSize } from '../../utils/measureText';
import { Sparkline } from '../Sparkline/Sparkline';
import { BigValueColorMode, Props, BigValueJustifyMode, BigValueTextMode } from './BigValue';
import { BigValueColorMode, BigValueProps, BigValueJustifyMode, BigValueTextMode } from './BigValue';
import { percentChangeString } from './PercentChange';
const LINE_HEIGHT = 1.2;
const MAX_TITLE_SIZE = 30;
const VALUE_FONT_WEIGHT = 500;
export type BigValuePropsWithHeightAndWidth = BigValueProps & Required<Pick<BigValueProps, 'width' | 'height'>>;
export abstract class BigValueLayout {
titleFontSize: number;
valueFontSize: number;
@@ -31,7 +33,7 @@ export abstract class BigValueLayout {
maxTextHeight: number;
textValues: BigValueTextValues;
constructor(private props: Props) {
constructor(private props: BigValuePropsWithHeightAndWidth) {
const { width, height, value, text } = props;
this.valueColor = value.color ?? 'gray';
@@ -288,7 +290,7 @@ export abstract class BigValueLayout {
}
export class WideNoChartLayout extends BigValueLayout {
constructor(props: Props) {
constructor(props: BigValuePropsWithHeightAndWidth) {
super(props);
const valueWidthPercent = this.titleToAlignTo?.length ? 0.3 : 1.0;
@@ -350,7 +352,7 @@ export class WideNoChartLayout extends BigValueLayout {
}
export class WideWithChartLayout extends BigValueLayout {
constructor(props: Props) {
constructor(props: BigValuePropsWithHeightAndWidth) {
super(props);
const { width, height } = props;
@@ -406,7 +408,7 @@ export class WideWithChartLayout extends BigValueLayout {
}
export class StackedWithChartLayout extends BigValueLayout {
constructor(props: Props) {
constructor(props: BigValuePropsWithHeightAndWidth) {
super(props);
const { width, height } = props;
@@ -464,7 +466,7 @@ export class StackedWithChartLayout extends BigValueLayout {
}
export class StackedWithNoChartLayout extends BigValueLayout {
constructor(props: Props) {
constructor(props: BigValuePropsWithHeightAndWidth) {
super(props);
const { height } = props;
@@ -523,7 +525,7 @@ export class StackedWithNoChartLayout extends BigValueLayout {
}
}
export function buildLayout(props: Props): BigValueLayout {
export function buildLayout(props: BigValuePropsWithHeightAndWidth): BigValueLayout {
const { width, height, sparkline } = props;
const useWideLayout = width / height > 2.5 && !props.disableWideLayout;
@@ -557,7 +559,7 @@ export interface BigValueTextValues extends DisplayValue {
tooltip?: string;
}
function getTextValues(props: Props): BigValueTextValues {
function getTextValues(props: BigValuePropsWithHeightAndWidth): BigValueTextValues {
const { value, alignmentFactors, count } = props;
let { textMode } = props;