diff --git a/src/specBuilder/bar/barSpecBuilder.ts b/src/specBuilder/bar/barSpecBuilder.ts index ff2b6dc1b..f7adbf94a 100644 --- a/src/specBuilder/bar/barSpecBuilder.ts +++ b/src/specBuilder/bar/barSpecBuilder.ts @@ -53,6 +53,7 @@ export const addBar = produce { expect(horizontal?.cornerRadiusBottomRight).toEqual(vertical?.cornerRadiusTopRight); expect(horizontal?.cornerRadiusBottomLeft).toEqual(vertical?.cornerRadiusBottomRight); }); + test('corner radius should be 0 when the hasSquareCorners prop is true', () => { + const squareRadius = getCornerRadiusEncodings({ ...defaultBarProps, hasSquareCorners: true }); + + // Square radius should have values of 0 + expect(squareRadius).toEqual( + expect.objectContaining({ + cornerRadiusTopLeft: expect.arrayContaining([expect.objectContaining({ value: 0 })]), + cornerRadiusTopRight: expect.arrayContaining([expect.objectContaining({ value: 0 })]), + }) + ); + + const roundRadius = getCornerRadiusEncodings({ ...defaultBarProps }); + + // Round radius should have values of 6 + expect(roundRadius).toEqual( + expect.objectContaining({ + cornerRadiusTopLeft: expect.arrayContaining([expect.objectContaining({ value: CORNER_RADIUS })]), + cornerRadiusTopRight: expect.arrayContaining([expect.objectContaining({ value: CORNER_RADIUS })]), + }) + ); + }); }); describe('getStackedCorderRadiusEncodings()', () => { @@ -261,6 +282,28 @@ describe('barUtils', () => { { value: 0 }, ]); }); + + test('corner radius should be 0 when the hasSquareCorners prop is true', () => { + const squareRadius = getStackedCornerRadiusEncodings({ ...defaultBarProps, hasSquareCorners: true }); + + // Square radius should have values of 0 + expect(squareRadius).toEqual( + expect.objectContaining({ + cornerRadiusTopLeft: expect.arrayContaining([expect.objectContaining({ value: 0 })]), + cornerRadiusTopRight: expect.arrayContaining([expect.objectContaining({ value: 0 })]), + }) + ); + + const roundRadius = getStackedCornerRadiusEncodings({ ...defaultBarProps }); + + // Round radius should have values of 6 + expect(roundRadius).toEqual( + expect.objectContaining({ + cornerRadiusTopLeft: expect.arrayContaining([expect.objectContaining({ value: CORNER_RADIUS })]), + cornerRadiusTopRight: expect.arrayContaining([expect.objectContaining({ value: CORNER_RADIUS })]), + }) + ); + }); }); describe('getOrientationProperties()', () => { diff --git a/src/specBuilder/bar/barUtils.ts b/src/specBuilder/bar/barUtils.ts index 52fed1802..07b94f241 100644 --- a/src/specBuilder/bar/barUtils.ts +++ b/src/specBuilder/bar/barUtils.ts @@ -180,8 +180,8 @@ export const getStackedMetricEncodings = (props: BarSpecProps): RectEncodeEntry }; export const getCornerRadiusEncodings = (props: BarSpecProps): RectEncodeEntry => { - const { type, lineWidth, metric } = props; - const value = Math.max(1, CORNER_RADIUS - getLineWidthPixelsFromLineWidth(lineWidth) / 2); + const { type, lineWidth, metric, hasSquareCorners } = props; + const value = hasSquareCorners ? 0 : Math.max(1, CORNER_RADIUS - getLineWidthPixelsFromLineWidth(lineWidth) / 2); let rectEncodeEntry: RectEncodeEntry; @@ -199,10 +199,15 @@ export const getCornerRadiusEncodings = (props: BarSpecProps): RectEncodeEntry = return rotateRectClockwiseIfNeeded(rectEncodeEntry, props); }; -export const getStackedCornerRadiusEncodings = ({ name, metric, lineWidth }: BarSpecProps): RectEncodeEntry => { +export const getStackedCornerRadiusEncodings = ({ + name, + metric, + lineWidth, + hasSquareCorners, +}: BarSpecProps): RectEncodeEntry => { const topTestString = `datum.${metric}1 > 0 && data('${name}_stacks')[indexof(pluck(data('${name}_stacks'), '${STACK_ID}'), datum.${STACK_ID})].max_${metric}1 === datum.${metric}1`; const bottomTestString = `datum.${metric}1 < 0 && data('${name}_stacks')[indexof(pluck(data('${name}_stacks'), '${STACK_ID}'), datum.${STACK_ID})].min_${metric}1 === datum.${metric}1`; - const value = Math.max(1, CORNER_RADIUS - getLineWidthPixelsFromLineWidth(lineWidth) / 2); + const value = hasSquareCorners ? 0 : Math.max(1, CORNER_RADIUS - getLineWidthPixelsFromLineWidth(lineWidth) / 2); return { cornerRadiusTopLeft: [{ test: topTestString, value }, { value: 0 }], diff --git a/src/stories/components/Bar/Bar.story.tsx b/src/stories/components/Bar/Bar.story.tsx index c58b088a6..468aa1b49 100644 --- a/src/stories/components/Bar/Bar.story.tsx +++ b/src/stories/components/Bar/Bar.story.tsx @@ -78,4 +78,11 @@ WithAnnotation.args = { metric: 'downloads', }; -export { Basic, Horizontal, LineType, Opacity, PaddingRatio, WithAnnotation }; +const HasSquareCorners = bindWithProps(BarStory); +HasSquareCorners.args = { + dimension: 'browser', + metric: 'downloads', + hasSquareCorners: true, +}; + +export { Basic, Horizontal, LineType, Opacity, PaddingRatio, WithAnnotation, HasSquareCorners }; diff --git a/src/types/Chart.ts b/src/types/Chart.ts index 5c888875f..cd72d3a55 100644 --- a/src/types/Chart.ts +++ b/src/types/Chart.ts @@ -331,6 +331,8 @@ export interface BarProps extends Omit { dimension?: string; /** Sets the inner padding between bars in a group */ groupedPadding?: number; + /** Should the top-left and top-right corners of the bars be square? Round by default */ + hasSquareCorners?: boolean; /** Line type or key in the data that is used as the line type facet */ lineType?: LineTypeFacet | DualFacet; /** Border width of the bar */ diff --git a/src/types/specBuilderTypes.ts b/src/types/specBuilderTypes.ts index 35ee15f16..da8ef4ec0 100644 --- a/src/types/specBuilderTypes.ts +++ b/src/types/specBuilderTypes.ts @@ -89,6 +89,7 @@ export interface AxisAnnotationSpecProps type BarPropsWithDefaults = | 'color' | 'dimension' + | 'hasSquareCorners' | 'lineType' | 'lineWidth' | 'metric'