Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
6228e29
feat(chart): enhance margin calculations for axes in line/bar chart c…
rmojica-godaddy Apr 22, 2026
83e90aa
test: update visual regression screenshots
github-actions[bot] Apr 22, 2026
f012658
feat(chart): replace useChartContainer with useScrollableXYChart in B…
rmojica-godaddy Apr 23, 2026
c17c7d7
refactor(chart): update useScrollableXYChart props and documentation …
rmojica-godaddy Apr 23, 2026
644d686
test(chart): enhance tests for margin calculations and element visibi…
rmojica-godaddy Apr 23, 2026
eaacf58
fix(chart): improve minimum width calculations for X-axis labels
rmojica-godaddy Apr 23, 2026
a7a0e63
Merge remote-tracking branch 'origin/main' into rmb/enhance-margin-ca…
rmojica-godaddy Apr 24, 2026
9d317d6
chore: update snapshots after merge main
rmojica-godaddy Apr 24, 2026
d8c46d1
fix(chart): improve margin calculations by measuring text rects for o…
rmojica-godaddy Apr 27, 2026
736343d
chore: update snapshots
rmojica-godaddy Apr 27, 2026
3e7d630
refactor(chart): add request animation frame for xy charts
rmojica-godaddy Apr 27, 2026
4efaa00
refactor(chart): replace effectiveMargin with margin and update margi…
rmojica-godaddy Apr 27, 2026
4dd8326
test: update visual regression screenshots
github-actions[bot] Apr 27, 2026
812d63b
Merge branch 'main' into rmb/enhance-margin-calculations
rmojica-godaddy Apr 28, 2026
da7c282
Update packages/@godaddy/antares/components/chart/bar-chart/src/index…
rmojica-godaddy Apr 28, 2026
7eea636
fix(chart): increase bar chart height to improve visibility of tick m…
rmojica-godaddy Apr 28, 2026
198f3ab
test: update visual regression screenshots
github-actions[bot] Apr 28, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,16 @@ export const Playground = {
width: undefined,
'aria-label': 'Playground bar chart',
desc: '',
className: ''
className: '',
rtl: false
},
argTypes: {
orientation: {
control: 'radio',
options: ['vertical', 'horizontal'],
description: 'Orientation of the bars'
},
rtl: { control: 'boolean', description: 'Render in right-to-left layout' },
numSeries: {
control: 'radio',
options: [1, 2, 3],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { BarChart, type BarChartProps } from '@godaddy/antares';
import { cityTemperature } from '@visx/mock-data';
import { RTLProvider } from '../../../../utils/rtl-locale-provider.tsx';

export interface PlaygroundExampleProps
extends Omit<BarChartProps, 'series' | 'xAccessor' | 'yAccessor' | 'xTickFormat' | 'yTickFormat'> {
/** Number of series to render (1 hides the legend by default). */
numSeries?: 1 | 2 | 3;
/** Render in right-to-left layout by wrapping the chart in {@link RTLProvider}. */
rtl?: boolean;
}

const CITIES = ['New York', 'San Francisco', 'Austin'] as const;
Expand All @@ -15,6 +18,7 @@ export function PlaygroundExample({
xAxisTitle = 'Date',
yAxisTitle = 'Temperature (°F)',
height = 500,
rtl = false,
...rest
}: PlaygroundExampleProps) {
const rows = cityTemperature.slice(0, 10);
Expand All @@ -29,7 +33,7 @@ export function PlaygroundExample({
};
});

return (
const chart = (
<BarChart
series={series}
orientation={orientation}
Expand All @@ -40,4 +44,6 @@ export function PlaygroundExample({
{...rest}
/>
);

return rtl ? <RTLProvider>{chart}</RTLProvider> : chart;
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export function BarChartFormattedTickMarksExample() {
]}
xAccessor={(d: { category: Date; value: number }) => d.category}
yAccessor={(d: { category: Date; value: number }) => d.value}
height={400}
height={600}
width={600}
xAxisTitle="Date"
yAxisTitle="Sales Amount"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,6 @@
display: block;
}

/* Vertical X labels */
.chart[data-x-labels-vertical="true"] .axisX text {
writing-mode: sideways-lr;
text-anchor: end;
}

.chart[data-x-labels-vertical="true"] .axisX text:dir(rtl) {
writing-mode: sideways-rl;
}

/* First gridline overlapping axis: hide when baseline shown */
.chart[data-x-baseline="true"] .area .columns line:first-of-type,
.chart[data-y-baseline="true"] .area .rows line:first-of-type {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import type {
SeriesConfig,
XLabelsOrientation
} from '../../types.ts';
import { resolveLegendPosition, xAccessor as defaultXAccessor, yAccessor as defaultYAccessor } from '../../utils.ts';
import {
getXLabelVerticalProps,
resolveLegendPosition,
xAccessor as defaultXAccessor,
yAccessor as defaultYAccessor
} from '../../utils.ts';
import { useNormalizedSeries } from '#components/chart/use-normalized-series';
import { useChartContainer } from '../../line-chart/src/use-chart-container.ts';
import { useScrollableXYChart } from '#components/chart/use-scrollable-xy-chart';
import { ChartColorProvider, useChartColor } from '#components/chart/use-chart-color';
import { AxisBottom, AxisLeft, AxisRight } from '@visx/axis';
import { AxisTitle } from '#components/chart/axis-title';
Expand Down Expand Up @@ -332,7 +337,7 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
const tickLength = 8;

const { parentRef, chartWidth, chartHeight, margin, scrollLeft, scrollTop, xAxisRef, yAxisRef, xLabelsVertical } =
useChartContainer({ xLabelsOrientation });
useScrollableXYChart({ xLabelsOrientation });

const series = useNormalizedSeries(seriesProp);

Expand All @@ -341,7 +346,6 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
isVertical,
barWidth,
barPadding,
effectiveMargin,
categoryValues,
numSeries,
totalBarWidth,
Expand Down Expand Up @@ -449,7 +453,7 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
>
{desc && <desc id="barchart-desc">{desc}</desc>}

<Group top={effectiveMargin.top} left={effectiveMargin.left}>
<Group top={margin.top} left={margin.left}>
{yGridlines && <GridRows scale={yScale} width={innerWidth} className={styles.rows} />}
{xGridlines && <GridColumns scale={xScale} height={innerHeight} className={styles.columns} />}

Expand All @@ -465,6 +469,7 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
tickLength={tickLength}
hideAxisLine={!xBaseline}
tickFormat={formatXTick}
tickLabelProps={xLabelsVertical ? getXLabelVerticalProps(rtl) : undefined}
/>
)}

Expand Down Expand Up @@ -526,11 +531,11 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
<rect
x={scrollLeft}
y={0}
width={effectiveMargin.left}
width={margin.left}
height={svgHeight}
className={styles.axisBackground}
/>
<g transform={`translate(${effectiveMargin.left + scrollLeft}, ${effectiveMargin.top})`}>
<g transform={`translate(${margin.left + scrollLeft}, ${margin.top})`}>
<AxisLeft
axisClassName={styles.axisY}
axisLineClassName={styles.baseline}
Expand All @@ -549,15 +554,13 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
{isVertical && (yBaseline || yTickMarks || yLabels) && rtl && (
<>
<rect
x={svgWidth - effectiveMargin.right + scrollLeft}
x={svgWidth - margin.right + scrollLeft}
y={0}
width={effectiveMargin.right}
width={margin.right}
height={svgHeight}
className={styles.axisBackground}
/>
<g
transform={`translate(${svgWidth - effectiveMargin.right + scrollLeft}, ${effectiveMargin.top})`}
>
<g transform={`translate(${svgWidth - margin.right + scrollLeft}, ${margin.top})`}>
<AxisRight
axisClassName={styles.axisY}
axisLineClassName={styles.baseline}
Expand All @@ -582,14 +585,12 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
<>
<rect
x={0}
y={scrollTop + chartHeight - effectiveMargin.bottom}
y={scrollTop + chartHeight - margin.bottom}
width={svgWidth}
height={effectiveMargin.bottom}
height={margin.bottom}
className={styles.axisBackground}
/>
<g
transform={`translate(${effectiveMargin.left}, ${scrollTop + chartHeight - effectiveMargin.bottom})`}
>
<g transform={`translate(${margin.left}, ${scrollTop + chartHeight - margin.bottom})`}>
<AxisBottom
axisClassName={styles.axisX}
axisLineClassName={styles.baseline}
Expand All @@ -599,6 +600,7 @@ export function BarChart<T extends object>(props: BarChartProps<T>) {
numTicks={xNumTicks}
tickLength={tickLength}
tickFormat={formatXTick}
tickLabelProps={xLabelsVertical ? getXLabelVerticalProps(rtl) : undefined}
/>
</g>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { scaleBand, scaleLinear } from '@visx/scale';
import { useTooltip } from '@visx/tooltip';
import type { Accessors, SeriesConfig } from '../../types.ts';
import {
getEffectiveMargin,
getCategoryValues,
computeChartDimensions,
computeBarGroupSpacing,
Expand Down Expand Up @@ -53,13 +52,6 @@ export function useBarChart<T extends object>({
const numSeries = series?.length || 0;
const totalBarWidth = numSeries * BAR_WIDTH + (numSeries - 1) * BAR_PADDING;

const effectiveMargin = useMemo(
function getMargin() {
return getEffectiveMargin(margin, rtl);
},
[margin, rtl]
);

const categoryValues = useMemo(
function getCategories() {
return getCategoryValues(series, isVertical, xAccessor, yAccessor as any);
Expand All @@ -75,14 +67,14 @@ export function useBarChart<T extends object>({
return computeChartDimensions({
chartWidth,
chartHeight,
effectiveMargin,
margin,
numGroups,
totalBarWidth,
minGapBetweenGroups: MIN_GAP_BETWEEN_GROUPS,
isVertical
});
},
[chartWidth, chartHeight, effectiveMargin, numGroups, totalBarWidth, isVertical]
[chartWidth, chartHeight, margin, numGroups, totalBarWidth, isVertical]
);

const { innerWidth, innerHeight } = dimensions;
Expand Down Expand Up @@ -176,7 +168,7 @@ export function useBarChart<T extends object>({
innerHeight,
innerWidth: dimensions.innerWidth,
totalBarWidth,
effectiveMargin,
margin,
svgWidth: dimensions.svgWidth,
svgRect,
tooltipArrowHeight: TOOLTIP_ARROW_HEIGHT,
Expand All @@ -198,7 +190,7 @@ export function useBarChart<T extends object>({
isVertical,
totalBarWidth,
valueScale,
effectiveMargin,
margin,
rtl,
dimensions
]
Expand All @@ -216,7 +208,7 @@ export function useBarChart<T extends object>({
isVertical,
barWidth: BAR_WIDTH,
barPadding: BAR_PADDING,
effectiveMargin,
margin,
categoryValues,
categoryDomain,
numSeries,
Expand Down
39 changes: 14 additions & 25 deletions packages/@godaddy/antares/components/chart/bar-chart/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,6 @@ export interface Margin {
right: number;
}

/**
* Swaps left and right margins when the chart is in RTL mode.
*
* @param margin - The original margin values
* @param rtl - Whether the chart is in right-to-left mode
* @returns The margin with left/right swapped when rtl is true
*/
export function getEffectiveMargin(margin: Margin, rtl: boolean): Margin {
return rtl ? { top: margin.top, right: margin.left, bottom: margin.bottom, left: margin.right } : margin;
}

/**
* Extracts the ordered list of unique category values across all series.
* In vertical orientation, categories come from xAccessor; in horizontal, from yAccessor.
Expand Down Expand Up @@ -62,7 +51,7 @@ export function getCategoryValues<T extends object>(
*
* @param chartWidth - Available container width in pixels
* @param chartHeight - Available container height in pixels
* @param effectiveMargin - Margin after applying RTL adjustments
* @param margin - Physical chart margin (already RTL-mapped by `useScrollableXYChart`)
* @param numGroups - Number of category groups (sets of bars)
* @param totalBarWidth - Combined pixel width of all bars in one group
* @param minGapBetweenGroups - Minimum pixel gap required between groups
Expand All @@ -72,27 +61,27 @@ export function getCategoryValues<T extends object>(
export function computeChartDimensions({
chartWidth,
chartHeight,
effectiveMargin,
margin,
numGroups,
totalBarWidth,
minGapBetweenGroups,
isVertical
}: {
chartWidth: number;
chartHeight: number;
effectiveMargin: Margin;
margin: Margin;
numGroups: number;
totalBarWidth: number;
minGapBetweenGroups: number;
isVertical: boolean;
}) {
const baseInnerWidth = Math.max(chartWidth - effectiveMargin.left - effectiveMargin.right, 0);
const baseInnerHeight = Math.max(chartHeight - effectiveMargin.top - effectiveMargin.bottom, 0);
const baseInnerWidth = Math.max(chartWidth - margin.left - margin.right, 0);
const baseInnerHeight = Math.max(chartHeight - margin.top - margin.bottom, 0);
const minSpacePerGroup = totalBarWidth + minGapBetweenGroups;
const innerWidth = isVertical ? Math.max(baseInnerWidth, numGroups * minSpacePerGroup) : baseInnerWidth;
const innerHeight = !isVertical ? Math.max(baseInnerHeight, numGroups * minSpacePerGroup) : baseInnerHeight;
const svgWidth = innerWidth + effectiveMargin.left + effectiveMargin.right;
const svgHeight = innerHeight + effectiveMargin.top + effectiveMargin.bottom;
const svgWidth = innerWidth + margin.left + margin.right;
const svgHeight = innerHeight + margin.top + margin.bottom;
return { innerWidth, innerHeight, svgWidth, svgHeight };
}

Expand Down Expand Up @@ -160,7 +149,7 @@ interface TooltipPositionOptions {
innerHeight: number;
innerWidth: number;
totalBarWidth: number;
effectiveMargin: Margin;
margin: Margin;
svgWidth: number;
svgRect: DOMRect;
tooltipArrowHeight: number;
Expand Down Expand Up @@ -190,7 +179,7 @@ export function computeTooltipPosition({
innerHeight,
innerWidth,
totalBarWidth,
effectiveMargin,
margin,
svgWidth,
svgRect,
tooltipArrowHeight,
Expand All @@ -214,11 +203,11 @@ export function computeTooltipPosition({
const groupOffset = (categoryScale.bandwidth() - totalBarWidth) / 2;
const barGroupCenter = groupCenter + groupOffset + totalBarWidth / 2;
const tooltipLeft = rtl
? svgRect.left + window.scrollX + svgWidth - effectiveMargin.right - barGroupCenter
: svgRect.left + window.scrollX + effectiveMargin.left + barGroupCenter;
? svgRect.left + window.scrollX + svgWidth - margin.right - barGroupCenter
: svgRect.left + window.scrollX + margin.left + barGroupCenter;
return {
tooltipLeft,
tooltipTop: svgRect.top + window.scrollY + effectiveMargin.top + minY - tooltipArrowHeight,
tooltipTop: svgRect.top + window.scrollY + margin.top + minY - tooltipArrowHeight,
tooltipData: { x: groupCenter, y: minY, datumByKey }
};
}
Expand All @@ -237,8 +226,8 @@ export function computeTooltipPosition({
const barGroupTop = yPos + groupOffset;
const tooltipXOffset = rtl ? (extremeX + innerWidth) / 2 : extremeX / 2;
return {
tooltipLeft: svgRect.left + window.scrollX + effectiveMargin.left + tooltipXOffset,
tooltipTop: svgRect.top + window.scrollY + effectiveMargin.top + barGroupTop - tooltipArrowHeight,
tooltipLeft: svgRect.left + window.scrollX + margin.left + tooltipXOffset,
tooltipTop: svgRect.top + window.scrollY + margin.top + barGroupTop - tooltipArrowHeight,
tooltipData: { x: catValue, datumByKey }
};
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Comment thread
rmojica-godaddy marked this conversation as resolved.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

exports[`@godaddy/antares > #BarChart > renders custom-domain example 1`] = `"<div dir="ltr" data-x-labels="true" data-y-labels="true" data-x-labels-vertical="true" data-y-gridlines="true" class="box chart" style="display:flex;flex-direction:row;--chart-width:600px;--chart-height:400px"><div role="group" aria-label="y axis title" dir="ltr" class="box axis yAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Value</div><div class="box wrapper" style="flex:1;display:flex;flex-direction:column"><div dir="ltr" class="box area"></div><div role="group" aria-label="x axis title" dir="ltr" class="box axis xAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Category</div></div></div>"`;

exports[`@godaddy/antares > #BarChart > renders formatted-tick-marks example 1`] = `"<div dir="ltr" data-x-labels="true" data-y-labels="true" data-x-labels-vertical="true" data-y-gridlines="true" class="box chart" style="display:flex;flex-direction:row;--chart-width:600px;--chart-height:400px"><div role="group" aria-label="y axis title" dir="ltr" class="box axis yAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Sales Amount</div><div class="box wrapper" style="flex:1;display:flex;flex-direction:column"><div dir="ltr" class="box area"></div><div role="group" aria-label="x axis title" dir="ltr" class="box axis xAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Date</div></div></div>"`;
exports[`@godaddy/antares > #BarChart > renders formatted-tick-marks example 1`] = `"<div dir="ltr" data-x-labels="true" data-y-labels="true" data-x-labels-vertical="true" data-y-gridlines="true" class="box chart" style="display:flex;flex-direction:row;--chart-width:600px;--chart-height:600px"><div role="group" aria-label="y axis title" dir="ltr" class="box axis yAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Sales Amount</div><div class="box wrapper" style="flex:1;display:flex;flex-direction:column"><div dir="ltr" class="box area"></div><div role="group" aria-label="x axis title" dir="ltr" class="box axis xAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Date</div></div></div>"`;

exports[`@godaddy/antares > #BarChart > renders horizontal-multi-series example 1`] = `"<div dir="ltr" data-legend-position="bottom" data-x-labels="true" data-y-labels="true" data-x-labels-vertical="true" data-x-baseline="true" data-y-baseline="true" data-x-tick-marks="true" data-y-tick-marks="true" data-x-gridlines="true" data-y-gridlines="true" class="box chart" style="display:flex;flex-direction:row"><div role="group" aria-label="y axis title" dir="ltr" class="box axis yAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Exoplanet</div><div class="box wrapper" style="flex:1;display:flex;flex-direction:column"><div dir="ltr" class="box area"></div><div role="group" aria-label="x axis title" dir="ltr" class="box axis xAxis" style="display:flex;flex-direction:row;justify-content:center;align-items:center">Radius (Rj)</div><div data-size="md" class="box root legend" style="align-self:center;display:inline-flex;flex-direction:column;align-items:flex-start;gap:var(--sp-sm, 4px)"><div role="list" aria-label="Chart legend" class="box" style="flex-shrink:0;display:flex;flex-direction:row;justify-content:center;align-items:flex-start;flex-wrap:wrap;gap:var(--sp-md, 8px)"><div role="listitem" class="box item" style="display:flex;flex-direction:row;align-items:center;gap:var(--sp-sm, 4px)"><div class="box swatch" style="border-radius:9999px;background-color:var(--ux-k4t5bc)"></div><span class="text">Survey A</span></div><div role="listitem" class="box item" style="display:flex;flex-direction:row;align-items:center;gap:var(--sp-sm, 4px)"><div class="box swatch" style="border-radius:9999px;background-color:var(--ux-k4t5bc)"></div><span class="text">Survey B</span></div><div role="listitem" class="box item" style="display:flex;flex-direction:row;align-items:center;gap:var(--sp-sm, 4px)"><div class="box swatch" style="border-radius:9999px;background-color:var(--ux-k4t5bc)"></div><span class="text">Survey C</span></div><div role="listitem" class="box item" style="display:flex;flex-direction:row;align-items:center;gap:var(--sp-sm, 4px)"><div class="box swatch" style="border-radius:9999px;background-color:var(--ux-k4t5bc)"></div><span class="text">Survey D</span></div></div></div></div></div>"`;

Expand Down
Loading
Loading