Barchart docs and styling fix (#41362)

* Barchart docs and styling fix

* Fix name of max length

* rename valueRotation -> xTickLabelRotation

also limits slider padding on sliders without marks
This commit is contained in:
Oscar Kilhed
2021-11-12 15:03:19 +01:00
committed by GitHub
parent d72e389d3d
commit 6fe29dda33
10 changed files with 42 additions and 33 deletions

View File

@@ -42,6 +42,14 @@ Use these options to refine your visualization.
- **Horizontal** - Will make the X axis the category axis. - **Horizontal** - Will make the X axis the category axis.
- **Vertical** - Will make the Y axis the category axis. - **Vertical** - Will make the Y axis the category axis.
### Rotate bar labels
When the graph is in vertical orientation you can use this setting to rotate the labels under the bars. Useful if the labels are long and overlap.
### Bar label max length
Sets the max length of the bar label. Labels longer than the max length will be truncated and `...` will be appended to the end.
### Show values ### Show values
This controls whether values are shown on top or to the left of bars. This controls whether values are shown on top or to the left of bars.

View File

@@ -26,7 +26,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
}) => { }) => {
const isHorizontal = orientation === 'horizontal'; const isHorizontal = orientation === 'horizontal';
const theme = useTheme2(); const theme = useTheme2();
const styles = getStyles(theme, isHorizontal); const styles = getStyles(theme, isHorizontal, Boolean(marks));
const SliderWithTooltip = SliderComponent; const SliderWithTooltip = SliderComponent;
const [sliderValue, setSliderValue] = useState<number>(value ?? min); const [sliderValue, setSliderValue] = useState<number>(value ?? min);

View File

@@ -3,7 +3,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { css as cssCore } from '@emotion/react'; import { css as cssCore } from '@emotion/react';
import { css } from '@emotion/css'; import { css } from '@emotion/css';
export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: boolean) => { export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: boolean, hasMarks = false) => {
const { spacing } = theme; const { spacing } = theme;
const railColor = theme.colors.border.strong; const railColor = theme.colors.border.strong;
const trackColor = theme.colors.primary.main; const trackColor = theme.colors.primary.main;
@@ -14,7 +14,8 @@ export const getStyles = stylesFactory((theme: GrafanaTheme2, isHorizontal: bool
return { return {
container: css` container: css`
width: 100%; width: 100%;
margin: ${isHorizontal ? 'none' : `${spacing(1, 3, 1, 1)}`}; margin: ${isHorizontal ? 'inherit' : `${spacing(1, 3, 1, 1)}`};
padding-bottom: ${isHorizontal && hasMarks ? theme.spacing(1) : 'inherit'};
height: ${isHorizontal ? 'auto' : '100%'}; height: ${isHorizontal ? 'auto' : '100%'};
`, `,
slider: css` slider: css`

View File

@@ -12,7 +12,7 @@ export interface AxisProps {
show?: boolean; show?: boolean;
size?: number | null; size?: number | null;
gap?: number; gap?: number;
valueRotation?: number; tickLabelRotation?: number;
placement?: AxisPlacement; placement?: AxisPlacement;
grid?: Axis.Grid; grid?: Axis.Grid;
ticks?: Axis.Ticks; ticks?: Axis.Ticks;
@@ -98,7 +98,7 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
isTime, isTime,
timeZone, timeZone,
theme, theme,
valueRotation, tickLabelRotation,
size, size,
} = this.props; } = this.props;
@@ -121,7 +121,7 @@ export class UPlotAxisBuilder extends PlotConfigBuilder<AxisProps, Axis> {
((self, values, axisIdx) => { ((self, values, axisIdx) => {
return this.calculateAxisSize(self, values, axisIdx); return this.calculateAxisSize(self, values, axisIdx);
}), }),
rotate: valueRotation, rotate: tickLabelRotation,
gap, gap,
labelGap: 0, labelGap: 0,

View File

@@ -17,8 +17,8 @@ export interface BarChartProps
const propsToDiff: Array<string | PropDiffFn> = [ const propsToDiff: Array<string | PropDiffFn> = [
'orientation', 'orientation',
'barWidth', 'barWidth',
'valueRotation', 'xTickLabelRotation',
'valueMaxLength', 'xTickLabelMaxLength',
'groupWidth', 'groupWidth',
'stacking', 'stacking',
'showValue', 'showValue',
@@ -64,8 +64,8 @@ export const BarChart: React.FC<BarChartProps> = (props) => {
legend, legend,
tooltip, tooltip,
text, text,
valueRotation, xTickLabelRotation,
valueMaxLength, xTickLabelMaxLength,
} = props; } = props;
return preparePlotConfigBuilder({ return preparePlotConfigBuilder({
@@ -78,8 +78,8 @@ export const BarChart: React.FC<BarChartProps> = (props) => {
barWidth, barWidth,
showValue, showValue,
groupWidth, groupWidth,
valueRotation, xTickLabelRotation,
valueMaxLength, xTickLabelMaxLength,
stacking, stacking,
legend, legend,
tooltip, tooltip,

View File

@@ -23,10 +23,10 @@ export const BarChartPanel: React.FunctionComponent<Props> = ({ data, options, w
return options.orientation; return options.orientation;
}, [width, height, options.orientation]); }, [width, height, options.orientation]);
const valueMaxLength = useMemo(() => { const xTickLabelMaxLength = useMemo(() => {
// If no max length is set, limit the number of characters to a length where it will use a maximum of half of the height of the viz. // If no max length is set, limit the number of characters to a length where it will use a maximum of half of the height of the viz.
if (!options.valueMaxLength) { if (!options.xTickLabelMaxLength) {
const rotationAngle = options.valueRotation; const rotationAngle = options.xTickLabelRotation;
const textSize = measureText('M', UPLOT_AXIS_FONT_SIZE).width; // M is usually the widest character so let's use that as an aproximation. const textSize = measureText('M', UPLOT_AXIS_FONT_SIZE).width; // M is usually the widest character so let's use that as an aproximation.
const maxHeightForValues = height / 2; const maxHeightForValues = height / 2;
@@ -36,9 +36,9 @@ export const BarChartPanel: React.FunctionComponent<Props> = ({ data, options, w
3 //Subtract 3 for the "..." added to the end. 3 //Subtract 3 for the "..." added to the end.
); );
} else { } else {
return options.valueMaxLength; return options.xTickLabelMaxLength;
} }
}, [height, options.valueRotation, options.valueMaxLength]); }, [height, options.xTickLabelRotation, options.xTickLabelMaxLength]);
// Force 'multi' tooltip setting or stacking mode // Force 'multi' tooltip setting or stacking mode
const tooltip = useMemo(() => { const tooltip = useMemo(() => {
@@ -66,7 +66,7 @@ export const BarChartPanel: React.FunctionComponent<Props> = ({ data, options, w
height={height} height={height}
{...options} {...options}
orientation={orientation} orientation={orientation}
valueMaxLength={valueMaxLength} xTickLabelMaxLength={xTickLabelMaxLength}
> >
{(config, alignedFrame) => { {(config, alignedFrame) => {
return <TooltipPlugin data={alignedFrame} config={config} mode={tooltip.mode} timeZone={timeZone} />; return <TooltipPlugin data={alignedFrame} config={config} mode={tooltip.mode} timeZone={timeZone} />;

View File

@@ -77,8 +77,8 @@ export const plugin = new PanelPlugin<BarChartOptions, BarChartFieldConfig>(BarC
defaultValue: VizOrientation.Auto, defaultValue: VizOrientation.Auto,
}) })
.addSliderInput({ .addSliderInput({
path: 'valueRotation', path: 'xTickLabelRotation',
name: 'Rotate values', name: 'Rotate bar labels',
defaultValue: 0, defaultValue: 0,
settings: { settings: {
min: -90, min: -90,
@@ -92,9 +92,9 @@ export const plugin = new PanelPlugin<BarChartOptions, BarChartFieldConfig>(BarC
}, },
}) })
.addNumberInput({ .addNumberInput({
path: 'valueMaxLength', path: 'xTickLabelMaxLength',
name: 'Value max length', name: 'Bar label max length',
description: 'Axis value labels will be truncated to the length provided', description: 'Bar labels will be truncated to the length provided',
settings: { settings: {
placeholder: 'Auto', placeholder: 'Auto',
min: 0, min: 0,

View File

@@ -19,8 +19,8 @@ export interface BarChartOptions extends OptionsWithLegend, OptionsWithTooltip,
showValue: VisibilityMode; showValue: VisibilityMode;
barWidth: number; barWidth: number;
groupWidth: number; groupWidth: number;
valueRotation: number; xTickLabelRotation: number;
valueMaxLength: number; xTickLabelMaxLength: number;
rawValue: (seriesIdx: number, valueIdx: number) => number; rawValue: (seriesIdx: number, valueIdx: number) => number;
} }

View File

@@ -87,8 +87,8 @@ describe('BarChart utils', () => {
placement: 'bottom', placement: 'bottom',
calcs: [], calcs: [],
}, },
valueRotation: 0, xTickLabelRotation: 0,
valueMaxLength: 20, xTickLabelMaxLength: 20,
stacking: StackingMode.None, stacking: StackingMode.None,
tooltip: { tooltip: {
mode: TooltipDisplayMode.None, mode: TooltipDisplayMode.None,

View File

@@ -56,13 +56,13 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
text, text,
rawValue, rawValue,
allFrames, allFrames,
valueRotation, xTickLabelRotation,
valueMaxLength, xTickLabelMaxLength,
legend, legend,
}) => { }) => {
const builder = new UPlotConfigBuilder(); const builder = new UPlotConfigBuilder();
const defaultValueFormatter = (seriesIdx: number, value: any) => { const defaultValueFormatter = (seriesIdx: number, value: any) => {
return shortenValue(formattedValueToString(frame.fields[seriesIdx].display!(value)), valueMaxLength); return shortenValue(formattedValueToString(frame.fields[seriesIdx].display!(value)), xTickLabelMaxLength);
}; };
// bar orientation -> x scale orientation & direction // bar orientation -> x scale orientation & direction
@@ -99,8 +99,8 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
builder.setTooltipInterpolator(config.interpolateTooltip); builder.setTooltipInterpolator(config.interpolateTooltip);
if (vizOrientation.xOri === ScaleOrientation.Horizontal && valueRotation !== 0) { if (vizOrientation.xOri === ScaleOrientation.Horizontal && xTickLabelRotation !== 0) {
builder.setPadding(getRotationPadding(frame, valueRotation, valueMaxLength)); builder.setPadding(getRotationPadding(frame, xTickLabelRotation, xTickLabelMaxLength));
} }
builder.setPrepData(config.prepData); builder.setPrepData(config.prepData);
@@ -123,7 +123,7 @@ export const preparePlotConfigBuilder: UPlotConfigPrepFn<BarChartOptions> = ({
grid: { show: false }, grid: { show: false },
ticks: { show: false }, ticks: { show: false },
gap: 15, gap: 15,
valueRotation: valueRotation * -1, tickLabelRotation: xTickLabelRotation * -1,
theme, theme,
}); });