@@ -72,9 +72,6 @@ interface StackedBarChartProps extends BarChartBaseProps {
7272
7373export type BarChartProps = SingleSeriesBarChartProps | StackedBarChartProps
7474
75- /** Surface gap between stacked segments, so adjacent fills never merge. */
76- const STACK_GAP = 1
77-
7875/**
7976 * Tick and tooltip text for a bucket's value, in the caller's unit. `exact` is for
8077 * the tooltip, where a figure is read in full rather than fitted to the axis gutter.
@@ -177,7 +174,7 @@ function BarChartComponent(props: BarChartProps) {
177174 cursor -= segmentHeight
178175 return [ { layer, y : cursor , height : segmentHeight } ]
179176 } )
180- return { x, top, point, segments }
177+ return { x, top, height : columnHeight , point, segments }
181178 } ) ,
182179 [
183180 buckets ,
@@ -323,26 +320,50 @@ function BarChartComponent(props: BarChartProps) {
323320 ) ) }
324321 </ g >
325322
326- < g style = { { mixBlendMode : isDark && ! isStacked ? 'screen' : 'normal' } } >
327- { columns . flatMap ( ( column , index ) =>
328- column . segments . map ( ( segment , segmentIndex ) => {
329- /** Every segment but the topmost gives up a sliver so neighbours stay distinct. */
330- const gap = segmentIndex < column . segments . length - 1 ? STACK_GAP : 0
331- return (
323+ { /**
324+ * Each column is one bar: its segments are square and clipped to a single
325+ * rounded outline, so only the bar's ends are rounded and a stack reads as one
326+ * shape split by color. A segment reaches half a pixel below its own bottom so
327+ * the one beneath never shows an anti-aliased seam through the join.
328+ */ }
329+ < defs >
330+ { columns . map ( ( column , index ) =>
331+ column . segments . length === 0 ? null : (
332+ < clipPath
333+ key = { `${ uniqueId } -column-${ column . point . timestamp } ` }
334+ id = { `${ uniqueId } -column-${ index } ` }
335+ >
332336 < rect
333- key = { `${ uniqueId } -bar-${ column . point . timestamp } -${ segment . layer . id } ` }
334337 x = { column . x }
335- y = { segment . y + gap }
338+ y = { column . top }
336339 width = { barWidth }
337- height = { Math . max ( 0 , segment . height - gap ) }
340+ height = { column . height }
338341 rx = '2'
342+ />
343+ </ clipPath >
344+ )
345+ ) }
346+ </ defs >
347+ < g style = { { mixBlendMode : isDark && ! isStacked ? 'screen' : 'normal' } } >
348+ { columns . map ( ( column , index ) => (
349+ < g
350+ key = { `${ uniqueId } -bar-${ column . point . timestamp } ` }
351+ clipPath = { `url(#${ uniqueId } -column-${ index } )` }
352+ >
353+ { column . segments . map ( ( segment ) => (
354+ < rect
355+ key = { segment . layer . id }
356+ x = { column . x }
357+ y = { segment . y }
358+ width = { barWidth }
359+ height = { segment . height + 0.5 }
339360 fill = { isStacked ? segment . layer . color : `url(#bar-${ uniqueId } )` }
340361 className = 'transition-opacity duration-150 motion-reduce:transition-none'
341362 opacity = { segmentOpacity ( segment . layer . id , index ) }
342363 />
343- )
344- } )
345- ) }
364+ ) ) }
365+ </ g >
366+ ) ) }
346367 </ g >
347368
348369 { tickIndices . map ( ( index ) => {
0 commit comments