diff --git a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axes-tick-label-rotation-visually-looks-correct-1-snap.png b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axes-tick-label-rotation-visually-looks-correct-1-snap.png index 12fd22f78c..cf29b75c42 100644 Binary files a/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axes-tick-label-rotation-visually-looks-correct-1-snap.png and b/integration/tests/__image_snapshots__/all-test-ts-baseline-visual-tests-for-all-stories-axes-tick-label-rotation-visually-looks-correct-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png index 12fd22f78c..cf29b75c42 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-bottom-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png index 12fd22f78c..cf29b75c42 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-left-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png index 12fd22f78c..cf29b75c42 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-right-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png index 12fd22f78c..cf29b75c42 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-hide-top-axis-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-0-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-0-1-snap.png new file mode 100644 index 0000000000..cf29b75c42 Binary files /dev/null and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-0-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-1-snap.png index 01fb3a1683..0cbe6796eb 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-180-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-180-1-snap.png new file mode 100644 index 0000000000..afd5fc2f39 Binary files /dev/null and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-180-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-90-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-90-1-snap.png new file mode 100644 index 0000000000..80e4cea3c7 Binary files /dev/null and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-90-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-negative-90-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-negative-90-1-snap.png new file mode 100644 index 0000000000..6b1fd88b10 Binary files /dev/null and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-correctly-rotated-ticks-negative-90-1-snap.png differ diff --git a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png index 12fd22f78c..cf29b75c42 100644 Binary files a/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png and b/integration/tests/__image_snapshots__/axis-stories-test-ts-axis-stories-should-render-ticks-with-varied-rotations-1-snap.png differ diff --git a/integration/tests/axis_stories.test.ts b/integration/tests/axis_stories.test.ts index f587283501..fc2395cfc6 100644 --- a/integration/tests/axis_stories.test.ts +++ b/integration/tests/axis_stories.test.ts @@ -17,6 +17,7 @@ * under the License. */ +import { Rotation } from '../../src'; import { common } from '../page_objects'; describe('Axis stories', () => { @@ -76,4 +77,15 @@ describe('Axis stories', () => { 'http://localhost:9001/?path=/story/axes--tick-label-rotation&knob-debug_general=true&knob-disable%20axis%20overrides_general=false&knob-Tick%20label%20rotation_bottom=47&knob-Tick%20label%20rotation_left=-54&knob-Tick%20label%20rotation_top=69&knob-Tick%20label%20rotation_right=48&knob-Tick%20label%20rotation_shared=30', ); }); + + it.each<[string, Rotation]>([ + ['0', 0], + ['90', 90], + ['180', 180], + ['negative 90', -90], + ])('should render correctly rotated ticks - %s', async (_, rotation) => { + await common.expectChartAtUrlToMatchScreenshot( + `http://localhost:9001/?path=/story/axes--tick-label-rotation&knob-disable axis overrides_general=true&knob-Tick label rotation_shared=${rotation}`, + ); + }); }); diff --git a/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts b/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts index b855ac8418..e5d54535a8 100644 --- a/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts +++ b/src/chart_types/xy_chart/renderer/canvas/axes/tick_label.ts @@ -41,6 +41,7 @@ export function renderTickLabel(ctx: CanvasRenderingContext2D, tick: AxisTick, s axisStyle, tick.position, position, + tickLabelRotation, size, axisTicksDimensions, showTicks, diff --git a/src/chart_types/xy_chart/utils/axis_utils.test.ts b/src/chart_types/xy_chart/utils/axis_utils.test.ts index 54c3d69dc4..7c696799ed 100644 --- a/src/chart_types/xy_chart/utils/axis_utils.test.ts +++ b/src/chart_types/xy_chart/utils/axis_utils.test.ts @@ -728,6 +728,7 @@ describe('Axis computational utils', () => { getCustomStyle(0, 5), tickPosition, Position.Left, + 0, axisPosition, axisDimensions, true, @@ -749,6 +750,7 @@ describe('Axis computational utils', () => { getCustomStyle(90), tickPosition, Position.Left, + 90, axisPosition, axisDimensions, true, @@ -774,6 +776,7 @@ describe('Axis computational utils', () => { getCustomStyle(90), tickPosition, Position.Right, + 90, axisPosition, axisDimensions, true, @@ -799,6 +802,7 @@ describe('Axis computational utils', () => { getCustomStyle(), tickPosition, Position.Right, + 0, axisPosition, axisDimensions, true, @@ -829,6 +833,7 @@ describe('Axis computational utils', () => { getCustomStyle(0, 5), tickPosition, Position.Top, + 0, axisPosition, axisDimensions, true, @@ -854,6 +859,7 @@ describe('Axis computational utils', () => { getCustomStyle(90), tickPosition, Position.Top, + 90, axisPosition, axisDimensions, true, @@ -863,11 +869,11 @@ describe('Axis computational utils', () => { expect(rotatedLabelProps).toEqual({ offsetX: 0, offsetY: -50, - textOffsetX: 0, + textOffsetX: 50, textOffsetY: 0, x: 0, y: -10, - align: 'center', + align: 'right', verticalAlign: 'middle', }); @@ -875,6 +881,7 @@ describe('Axis computational utils', () => { getCustomStyle(90), tickPosition, Position.Bottom, + 90, axisPosition, axisDimensions, true, @@ -884,11 +891,11 @@ describe('Axis computational utils', () => { expect(bottomRotatedLabelProps).toEqual({ offsetX: 0, offsetY: 50, - textOffsetX: 0, + textOffsetX: -50, textOffsetY: 0, x: 0, y: 20, - align: 'center', + align: 'left', verticalAlign: 'middle', }); @@ -896,6 +903,7 @@ describe('Axis computational utils', () => { getCustomStyle(90), tickPosition, Position.Bottom, + 90, axisPosition, axisDimensions, true, diff --git a/src/chart_types/xy_chart/utils/axis_utils.ts b/src/chart_types/xy_chart/utils/axis_utils.ts index 9b2ef1192c..c3b1f1a732 100644 --- a/src/chart_types/xy_chart/utils/axis_utils.ts +++ b/src/chart_types/xy_chart/utils/axis_utils.ts @@ -309,6 +309,7 @@ function getVerticalTextOffset( function getHorizontalAlign( position: Position, + rotation: number, alignment: HorizontalAlignment = HorizontalAlignment.Near, ): Exclude { if ( @@ -319,6 +320,22 @@ function getHorizontalAlign( return alignment; } + if ([-90, 90].includes(rotation)) { + if (position === Position.Left || position === Position.Right) { + return HorizontalAlignment.Center; + } + + if (position === Position.Top) { + return rotation === 90 ? HorizontalAlignment.Right : HorizontalAlignment.Left; + } + + return rotation === -90 ? HorizontalAlignment.Right : HorizontalAlignment.Left; + } + + if ([0, 180].includes(rotation) && (position === Position.Bottom || position === Position.Top)) { + return HorizontalAlignment.Center; + } + if (position === Position.Left) { return alignment === HorizontalAlignment.Near ? HorizontalAlignment.Right : HorizontalAlignment.Left; } @@ -328,11 +345,12 @@ function getHorizontalAlign( } // fallback for near/far on top/bottom axis - return 'center'; + return HorizontalAlignment.Center; } function getVerticalAlign( position: Position, + rotation: number, alignment: VerticalAlignment = VerticalAlignment.Middle, ): Exclude { if ( @@ -343,6 +361,18 @@ function getVerticalAlign( return alignment; } + if ([0, 180].includes(rotation)) { + if (position === Position.Bottom || position === Position.Top) { + return VerticalAlignment.Middle; + } + + if (position === Position.Left) { + return rotation === 0 ? VerticalAlignment.Bottom : VerticalAlignment.Top; + } + + return rotation === 180 ? VerticalAlignment.Bottom : VerticalAlignment.Top; + } + if (position === Position.Top) { return alignment === VerticalAlignment.Near ? VerticalAlignment.Bottom : VerticalAlignment.Top; } @@ -371,6 +401,7 @@ export function getTickLabelProps( { tickLine, tickLabel }: AxisStyle, tickPosition: number, position: Position, + rotation: number, axisSize: Size, tickDimensions: AxisTicksDimensions, showTicks: boolean, @@ -382,8 +413,8 @@ export function getTickLabelProps( const labelPadding = getSimplePadding(tickLabel.padding); const isLeftAxis = position === Position.Left; const isAxisTop = position === Position.Top; - const align = getHorizontalAlign(position, textAlignment?.horizontal); - const verticalAlign = getVerticalAlign(position, textAlignment?.vertical); + const align = getHorizontalAlign(position, rotation, textAlignment?.horizontal); + const verticalAlign = getVerticalAlign(position, rotation, textAlignment?.vertical); const userOffsets = getUserTextOffsets(tickDimensions, textOffset); const textOffsetX = getHorizontalTextOffset(maxLabelTextWidth, align) + userOffsets.local.x; @@ -862,8 +893,8 @@ export const isDuplicateAxis = ( tickMap: Map, specs: AxisSpec[], ): boolean => { - const firstTickLabel = tickLabels[0]; - const lastTickLabel = tickLabels.slice(-1)[0]; + const [firstTickLabel] = tickLabels; + const [lastTickLabel] = tickLabels.slice(-1); let hasDuplicate = false; tickMap.forEach(({ tickLabels: axisTickLabels }, axisId) => { diff --git a/stories/axes/2_tick_label_rotation.tsx b/stories/axes/2_tick_label_rotation.tsx index e747631487..e708bcc74d 100644 --- a/stories/axes/2_tick_label_rotation.tsx +++ b/stories/axes/2_tick_label_rotation.tsx @@ -173,7 +173,6 @@ export const Example = () => { } : undefined } - tickFormat={(d) => Number(d).toFixed(2)} /> { } : undefined } - tickFormat={(d) => Number(d).toFixed(2)} /> { } : undefined } - tickFormat={(d) => Number(d).toFixed(2)} - domain={{ min: 0, max: 10 }} + domain={{ min: 0, max: 100 }} /> { xAccessor="x" yAccessors={['y']} data={[ - { x: 0, y: 2 }, - { x: 1, y: 7 }, - { x: 2, y: 3 }, - { x: 3, y: 6 }, + { x: 0, y: 20 }, + { x: 1, y: 70 }, + { x: 2, y: 30 }, + { x: 3, y: 60 }, ]} />