Selkie.git | docs/api/ | Selkie--Widget--BarChart.md
NAME
====
Selkie::Widget::BarChart - Categorical bar chart, vertical or horizontal
SYNOPSIS
========
```raku
use Selkie::Widget::BarChart;
use Selkie::Sizing;
# Vertical bars (default)
my $bars = Selkie::Widget::BarChart.new(
data => [
{ label => 'apples', value => 12 },
{ label => 'pears', value => 7 },
{ label => 'cherries',value => 15 },
{ label => 'plums', value => 4 },
],
sizing => Sizing.flex,
);
# Horizontal bars
my $hbars = Selkie::Widget::BarChart.new(
data => @data,
orientation => 'horizontal',
sizing => Sizing.flex,
);
# Reactive — read from a store path
my $live = Selkie::Widget::BarChart.new(
store-path => <stats counts>,
sizing => Sizing.flex,
);
```
DESCRIPTION
===========
A categorical bar chart. Each entry is a labelled value; entries are laid out across the chart body with one bar per entry. The **orientation** determines the bar direction:
* **vertical** (default) — bars rise from the bottom; labels along the bottom edge; values along the left edge.
* **horizontal** — bars extend rightward from the left; labels along the left edge; values along the top edge.
Bar heights / widths use 1/8-cell precision via the Unicode block glyphs (`▁▂▃▄▅▆▇█` vertically, `▏▎▍▌▋▊▉█` horizontally) so a bar can be `3.625` cells tall, not just integer cells.
Construction modes
------------------
Same as [Selkie::Widget::Sparkline](Selkie--Widget--Sparkline.md):
* **Static** — pass `:data([...])` with one hash per bar (`label`, `value`, optional `color`).
* **Reactive** — pass `:store-path<a b c>` to read the data array from a store path; the widget re-renders when the value changes.
The two modes are mutually exclusive.
Coloring
--------
Each bar's color comes from one of three sources, in priority order:
* Per-bar override: `{ label =` 'foo', value => 12, color => 0xFF0000 }>
* The named palette specified by `:palette` (default `okabe-ito`) — colors cycle if there are more bars than palette entries
* `self.theme.graph-line` as a fallback for any bar without a color and no palette match
See [Selkie::Plot::Palette](Selkie--Plot--Palette.md) for the available palettes.
Range
-----
Y-range (vertical) / X-range (horizontal) auto-derives from the data: the lower bound is `0` (or the data minimum if negative), the upper bound is the data maximum padded outward by Heckbert's nice-number choice (so the top tick lands on a round number).
Pass `:min` and `:max` to fix the range.
EXAMPLES
========
Simple categorical comparison
-----------------------------
```raku
my $chart = Selkie::Widget::BarChart.new(
data => [
{ label => 'Q1', value => 1230 },
{ label => 'Q2', value => 1875 },
{ label => 'Q3', value => 2042 },
{ label => 'Q4', value => 1611 },
],
sizing => Sizing.flex,
);
```
Multi-color with a palette override
-----------------------------------
```raku
my $chart = Selkie::Widget::BarChart.new(
data => @data,
palette => 'tol-bright',
sizing => Sizing.flex,
);
```
Per-bar color (status indicator)
--------------------------------
```raku
my @data = $tasks.map: -> $t {
{
label => $t.name,
value => $t.duration-ms,
color => $t.status eq 'failed' ?? 0xCC4444 !! 0x44AA44,
}
};
my $chart = Selkie::Widget::BarChart.new(:@data, sizing => Sizing.flex);
```
SEE ALSO
========
* [Selkie::Widget::Histogram](Selkie--Widget--Histogram.md) — bins a numeric series and feeds it into BarChart
* [Selkie::Widget::Sparkline](Selkie--Widget--Sparkline.md) — for a single inline trend bar
* [Selkie::Plot::Palette](Selkie--Plot--Palette.md) — series colors
### has Positional @.data
List of bar entries. Each entry is a hash with `label` (Str), `value` (Real), and optional `color` (UInt RGB).
### has Positional[Str] @.store-path
Reactive store path. Mutually exclusive with `data`.
### has Str $.orientation
`vertical` (bars rise from the bottom) or `horizontal` (bars extend right from the left).
### has Str $.palette
Named series palette for bar colors. See [Selkie::Plot::Palette](Selkie--Plot--Palette.md).
### has Bool $.show-axis
Whether to draw the value axis (left for vertical, top for horizontal). Disable when the chart is composed in a layout that supplies its own axis.
### has Bool $.show-labels
Whether to draw category labels (bottom for vertical, left for horizontal).
### has Real $.min
Optional explicit lower bound. When unset, derived from the data (`min(0, min-data)`).
### has Real $.max
Optional explicit upper bound. When unset, derived from the data (`max-data`, padded by Heckbert).
### has UInt $.tick-count
Approximate tick count for the value axis.
### has Str $.empty-message
Message rendered when there are no bars. The default is the expected startup state for monitoring dashboards. Set to the empty string to suppress.
### method on-store-attached
```raku
method on-store-attached(
$store
) returns Mu
```
Hook called when the widget is attached to a store. Wires up a subscription against the chart's `:store-path` so it re-renders whenever the underlying state changes. No-op in `:data` mode.
### method set-data
```raku
method set-data(
@new
) returns Mu
```
Replace the chart's data with a new array of bars / grouped bars. Throws when the chart was constructed in `:store-path` mode — pick one feed source up front (data array vs. store path) and stick with it for the lifetime of the widget.