# `PhoenixKitWeb.Components.Core.Chart`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.13.11/lib/phoenix_kit_web/components/core/chart.ex#L1)

Server-rendered SVG chart primitives — no JavaScript, no external
libraries. Charts re-render whenever LiveView assigns change, so they
are live by construction. (They snap rather than tween: SVG geometry
attributes are not CSS-transitionable.)

All charts draw in `currentColor`: set a text colour on the component
(`class="text-primary"`) and stroke, fill and gradient all follow it in
light and dark themes.

## Sizing

Each chart fills its container. The SVG uses `preserveAspectRatio="none"`,
so it stretches to whatever box you give it while strokes stay crisp via
`vector-effect="non-scaling-stroke"`. **Give the wrapper a height** —
otherwise you inherit the viewBox's intrinsic ratio, which is rarely what
you want:

    <div class="h-48 w-full">
      <.line_chart id="p" data={@points} class="text-primary" />
    </div>

Heavy stretching still distorts anything measured in user space: dash
patterns and the bars' rounded corners. Strokes are protected; those are
not.

## Data

Values are plain numbers — callers map their domain (time, money, watts)
to x/y first, which is what keeps these primitives generic: a price
curve, a CPU graph and a signup funnel are all just `{x, y}` pairs.

Points may be `{x, y}` tuples or `%{x: x, y: y}` maps, and `Decimal`
values are converted automatically (money and metrics arrive that way
from Ecto). Points that aren't numeric are dropped rather than crashing
the page; if nothing usable is left, the `:empty` slot renders.

Series are sorted by x, so out-of-order data plots correctly instead of
zigzagging.

Origin: extracted from NordSwitch's live price charts; also intended as
the drawing layer for `phoenix_kit_dashboards` widgets.

# `bar_chart`

A vertical bar chart, measured from a zero baseline.

## Examples

    <.bar_chart
      id="daily-kwh"
      data={Enum.map(@days, &%{label: &1.date, value: &1.kwh})}
      aria_label="Daily consumption"
      class="text-secondary"
    />

Bars carry a native `<title>`, so hovering one shows its label and value
with no JS. Negative values hang below the baseline instead of
disappearing. A datum may set `class:` to colour one bar differently
(`%{label: "Fri", value: 22, class: "text-error"}`).

## Attributes

* `id` (`:string`) (required) - Unique id (applied to the SVG element).
* `data` (`:list`) (required) - List of %{label: term, value: number, class: optional_string}.
* `width` (`:integer`) - Defaults to `960`.
* `height` (`:integer`) - Defaults to `200`.
* `show_labels` (`:boolean`) - Render labels beneath the bars. Defaults to `false`.
* `baseline` (`:boolean`) - Draw the zero line when any value is negative (its position is not otherwise implied). Defaults to `true`.
* `class` (`:any`) - Classes for the wrapper (set text-* for colour). Defaults to `nil`.
* `aria_label` (`:string`) - Accessible name for the chart. Defaults to `nil`.
* `value_format` (`:any`) - 1-arity fun formatting a value for its tooltip. No generic chart can infer units or locale, so pass your own. It receives the NUMBER, not your original struct — non-numeric values are dropped before this runs — so write `&"$#{&1}"`, not `&Money.to_string/1`. Defaults to a compact numeric rendering. Defaults to `nil`.
* Global attributes are accepted. Extra attributes for the wrapper.
## Slots

* `empty` - Rendered instead of the SVG when there is no usable data.

# `line_chart`

A line chart for a numeric series, optionally filled.

## Examples

    <%!-- a day of prices: x = minute of day, y = EUR/MWh --%>
    <.line_chart
      id="price-day"
      data={Enum.map(@slots, &{minute_of_day(&1.starts_at), &1.eur_mwh})}
      x_domain={{0, 1440}}
      step
      marker_x={minute_of_day(@now)}
      aria_label="Electricity price today"
      class="text-primary"
    />

    <%!-- a bare line, auto domains --%>
    <.line_chart id="signups" data={@signups} area={false} />

With `step` each point holds its y until the next x (right-open steps —
the correct reading for slot/interval data like prices). `marker_x`
draws a dashed vertical "now" line. Domains default to the data's
min/max, y padded by 10%; a reversed domain is normalised.

## Attributes

* `id` (`:string`) (required) - Unique id (namespaces the SVG gradient defs).
* `data` (`:list`) (required) - Points as {x, y} tuples or %{x: _, y: _} maps. Non-numeric points are dropped.
* `step` (`:boolean`) - Step interpolation (interval data). Defaults to `false`.
* `area` (`:boolean`) - Fill a gradient area under the line. Defaults to `true`.
* `x_domain` (`:any`) - {min, max} for x, or nil to fit data. Defaults to `nil`.
* `y_domain` (`:any`) - {min, max} for y, or nil to fit data (10% padded). Defaults to `nil`.
* `marker_x` (`:any`) - x position for a dashed vertical marker, or nil. Defaults to `nil`.
* `width` (`:integer`) - viewBox width (the SVG scales to its container). Defaults to `960`.
* `height` (`:integer`) - viewBox height. Defaults to `240`.
* `gridlines` (`:integer`) - Number of horizontal gridlines (0 disables). Defaults to `3`.
* `class` (`:any`) - Classes for the wrapper (set text-* for colour). Defaults to `nil`.
* `aria_label` (`:string`) - Accessible name. `role="img"` without one is an unlabelled graphic to a screen reader; pass what the chart shows. Unlabelled charts are marked decorative. Defaults to `nil`.
* Global attributes are accepted. Extra attributes for the wrapper.
## Slots

* `empty` - Rendered instead of the SVG when there is no usable data.

# `sparkline`

A minimal inline sparkline for a list of values.

## Examples

    <.sparkline values={Enum.map(@upcoming, & &1.eur_mwh)} class="w-full h-12 text-info" />

A single value draws a flat line rather than nothing — one sample is a
real state, and an empty box reads as a rendering bug.

## Attributes

* `values` (`:list`) (required) - Numbers, in order. Non-numeric values are dropped.
* `width` (`:integer`) - viewBox width. Defaults to `200`.
* `height` (`:integer`) - viewBox height. Defaults to `48`.
* `class` (`:any`) - Classes for the wrapper (set text-* for colour). Defaults to `nil`.
* `aria_label` (`:string`) - Accessible name. Left unset the sparkline is marked decorative. Defaults to `nil`.
* Global attributes are accepted. Extra attributes for the wrapper.
## Slots

* `empty` - Rendered instead of the SVG when there is no usable data.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
