mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
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:
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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`
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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} />;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user