Skip to content

Commit

Permalink
Rounded Bars improvements (BarChart, etc) (#280)
Browse files Browse the repository at this point in the history
* feat(Bar): Add `none` rounded option

* feat(Bar): Support `rounded="edge"` for value and orientation aware single edge rounding

* feat(BarChart): Use new `rounded="edge"` for better default rounding, especially with `seriesLayout="stack"`

* docs(BarChart): Remove explicit series "rounded" as default `edge` handles these cases

* fix(Bar): Handle stack (array) values when determined value for rounded edge

* fix(BarChart): Improve handling of diverging stack series and negative values

* docs: Remove radius from most horizontal and vertical Bars examples

* fix(Bar): Re-add `none` rounded option

* fix(BarChart): Resolve svelte-check type error
  • Loading branch information
techniq authored Nov 11, 2024
1 parent 6b0c644 commit 450ef9d
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 119 deletions.
5 changes: 5 additions & 0 deletions .changeset/poor-waves-protect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': minor
---

feat(Bar): Add `none` rounded option
5 changes: 5 additions & 0 deletions .changeset/tough-mangos-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': minor
---

feat(Bar): Support `rounded="edge"` for value and orientation aware single edge rounding
5 changes: 5 additions & 0 deletions .changeset/yellow-maps-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'layerchart': minor
---

feat(BarChart): Use new `rounded="edge"` for better default rounding, especially with `seriesLayout="stack"`
37 changes: 29 additions & 8 deletions packages/layerchart/src/lib/components/Bar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import Rect from './Rect.svelte';
import Spline from './Spline.svelte';
import { createDimensionGetter } from '$lib/utils/rect.js';
import type { Accessor } from '../utils/common.js';
import { createDimensionGetter } from '../utils/rect.js';
import { isScaleBand } from '../utils/scales.js';
import { accessor, type Accessor } from '../utils/common.js';
import { greatestAbs } from '@layerstack/utils/array';
const { x: xContext, y: yContext } = chartContext();
const { x: xContext, y: yContext, xScale } = chartContext();
export let bar: Object;
Expand Down Expand Up @@ -40,6 +42,8 @@
/** Control which corners are rounded with radius. Uses <path> instead of <rect> when not set to `all` */
export let rounded:
| 'all'
| 'none'
| 'edge'
| 'top'
| 'bottom'
| 'left'
Expand All @@ -65,10 +69,27 @@
});
$: dimensions = $getDimensions(bar) ?? { x: 0, y: 0, width: 0, height: 0 };
$: topLeft = ['all', 'top', 'left', 'top-left'].includes(rounded);
$: topRight = ['all', 'top', 'right', 'top-right'].includes(rounded);
$: bottomLeft = ['all', 'bottom', 'left', 'bottom-left'].includes(rounded);
$: bottomRight = ['all', 'bottom', 'right', 'bottom-right'].includes(rounded);
$: isVertical = isScaleBand($xScale);
$: valueAccessor = accessor(isVertical ? y : x);
$: value = valueAccessor(bar);
$: resolvedValue = Array.isArray(value) ? greatestAbs(value) : value;
// Resolved `rounded="edge"` based on orientation and value
$: _rounded =
rounded === 'edge'
? isVertical
? resolvedValue >= 0
? 'top'
: 'bottom'
: resolvedValue >= 0
? 'right'
: 'left'
: rounded;
$: topLeft = ['all', 'top', 'left', 'top-left'].includes(_rounded);
$: topRight = ['all', 'top', 'right', 'top-right'].includes(_rounded);
$: bottomLeft = ['all', 'bottom', 'left', 'bottom-left'].includes(_rounded);
$: bottomRight = ['all', 'bottom', 'right', 'bottom-right'].includes(_rounded);
$: width = dimensions.width;
$: height = dimensions.height;
Expand All @@ -87,7 +108,7 @@
.join('');
</script>

{#if rounded === 'all'}
{#if _rounded === 'all' || radius === 0}
<Rect
{fill}
{spring}
Expand Down
8 changes: 5 additions & 3 deletions packages/layerchart/src/lib/components/Bars.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,20 @@
export let spring: ComponentProps<Rect>['spring'] = undefined;
export let tweened: ComponentProps<Rect>['tweened'] = undefined;
$: _data = chartDataArray(data ?? $contextData);
</script>

<g class="Bars">
<slot>
{#each chartDataArray(data ?? $contextData) as item}
{#each _data as d, i}
<Bar
bar={item}
bar={d}
{x}
{y}
{x1}
{y1}
fill={fill ?? ($config.c ? $cGet(item) : null)}
fill={fill ?? ($config.c ? $cGet(d) : null)}
{stroke}
{strokeWidth}
{radius}
Expand Down
16 changes: 6 additions & 10 deletions packages/layerchart/src/lib/components/charts/BarChart.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,16 @@
}
function getBarsProps(s: (typeof series)[number], i: number) {
const valueAccesor = stackSeries
? (d: any) => d.stackData[i]
: (s.value ?? (s.data ? undefined : s.key));
const barsProps: ComponentProps<Bars> = {
data: s.data,
x: !isVertical
? stackSeries
? (d) => d.stackData[i]
: (s.value ?? (s.data ? undefined : s.key))
: undefined,
y: isVertical
? stackSeries
? (d) => d.stackData[i]
: (s.value ?? (s.data ? undefined : s.key))
: undefined,
x: !isVertical ? valueAccesor : undefined,
y: isVertical ? valueAccesor : undefined,
x1: isVertical && groupSeries ? (d) => s.value ?? s.key : undefined,
y1: !isVertical && groupSeries ? (d) => s.value ?? s.key : undefined,
rounded: seriesLayout.startsWith('stack') && i !== series.length - 1 ? 'none' : 'edge',
radius: 4,
strokeWidth: 1,
fill: s.color,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -229,13 +229,11 @@
{
key: 'value',
color: 'hsl(var(--color-primary))',
props: { rounded: 'top' },
},
{
key: 'baseline',
value: (d) => -d.baseline,
color: 'hsl(var(--color-secondary))',
props: { rounded: 'bottom' },
},
]}
/>
Expand All @@ -261,12 +259,10 @@
key: 'male',
value: (d) => -d.male,
color: 'hsl(var(--color-primary))',
props: { rounded: 'left' },
},
{
key: 'female',
color: 'hsl(var(--color-secondary))',
props: { rounded: 'right' },
},
]}
>
Expand Down Expand Up @@ -316,13 +312,11 @@
key: 'male',
value: (d) => -d.male / totalPopulation,
color: 'hsl(var(--color-primary))',
props: { rounded: 'left' },
},
{
key: 'female',
value: (d) => d.female / totalPopulation,
color: 'hsl(var(--color-secondary))',
props: { rounded: 'right' },
},
]}
>
Expand Down Expand Up @@ -549,7 +543,12 @@
data={wideData}
x="year"
series={[
{ key: 'apples', value: (d) => -d.apples, color: 'hsl(var(--color-danger))' },
{
key: 'apples',
value: (d) => -d.apples,
color: 'hsl(var(--color-danger))',
props: { rounded: 'bottom' },
},
{
key: 'bananas',
color: 'hsl(var(--color-warning))',
Expand Down Expand Up @@ -797,7 +796,7 @@
axis="x"
bandPadding={0.1}
props={{
bars: { radius: 4, strokeWidth: 0 },
bars: { radius: 4, strokeWidth: 0, rounded: 'all' },
highlight: { bar: { radius: 4, class: 'stroke-current stroke-2 fill-none' } },
xAxis: { ticks: (scale) => scaleTime(scale.domain(), scale.range()).ticks() },
rule: { y: false },
Expand Down
Loading

0 comments on commit 450ef9d

Please sign in to comment.