forge-charts
Pure-Rust + SVG interactive charts for Leptos
(CSR). No JS, no canvas, no Tailwind — just leptos, chrono, and
web-sys. The public API is project-agnostic: consumers pass
accessor closures over their own data type.
What you get
AreaChart— multi-series filled area with axes, legend, hover crosshair, per-series hover dots, and a consumer-rendered tooltip card.- Modern visuals out of the box: gradient fills, soft axes, translucent rounded tooltip, light + dark mode via CSS variables.
- Clickable legend dots — native
<input type="color">lets the user re-theme any series at runtime. - Animations on mount (
scaleYrise from baseline, staggered per series). Respectsprefers-reduced-motion.
Install
[]
= "0.2"
= { = "0.8", = ["csr"] }
Or as a git dep during pre-publish:
[]
= { = "https://github.com/dandush03/forge" }
You also need the bundled stylesheet served alongside your bundle.
With Trunk, add to index.html:
…where vendor/forge-charts/charts.css is a copy (or symlink)
of crates/charts/src/charts.css. Alternatively, the CSS is exposed
as a &'static str via the CHART_CSS constant for runtime
injection through leptos_meta::Stylesheet:
use Stylesheet;
use CHART_CSS;
view!
Quick start
use *;
use ;
Custom tooltip
The chart hands the hovered data-point index back to a closure you provide; render whatever you want inside the tooltip card.
use Arc;
use *;
use IntoAny;
use ;
API surface
| Prop | Type | Description |
|---|---|---|
data |
Signal<Vec<T>> |
Data points. Order = X-axis order; no internal sorting. |
x_label |
Fn(&T) -> String |
Per-point X-axis label. |
y_values |
Fn(&T) -> Vec<f64> |
Y values per point, one per declared series (positional). |
series |
Vec<Series> |
Declares each plotted series + its CSS color hook. |
height |
u32 (default 320) |
Outer container height in CSS pixels. |
legend |
bool (default true) |
Show the legend chip strip above the chart. |
tooltip |
Option<TooltipSlot> |
Arc<dyn Fn(usize) -> AnyView + Send + Sync>. When None, the crosshair still tracks the cursor but no tooltip card draws. |
class |
String |
Extra classes on the outer .charts-root container. |
Series::area(name, color_class) builds an area series. name is
the legend + tooltip label. color_class is the CSS-class suffix
the chart uses for its color hooks (.charts-series-<color_class>).
Theming
The bundled stylesheet exposes a small set of CSS variables you can
override per consumer. Set them on :root, on any parent of
.charts-root, or via inline style= on the chart itself.
| Variable | Default (light) | Purpose |
|---|---|---|
--charts-fg |
rgb(17 24 39) |
Default text color inside the chart. |
--charts-fg-muted |
rgb(107 114 128) |
Axis labels. |
--charts-fg-faint |
rgb(156 163 175) |
Crosshair color. |
--charts-grid-color |
rgba(229, 231, 235, 0.7) |
Gridline color. |
--charts-series-<color_class> |
(none — set per series) | Solid color for series stroke + tooltip dot. |
--charts-series-<color_class>-soft |
(none — set per series) | Soft variant (≤ 0.5 alpha) for the gradient fill. |
Default palette ships with --charts-series-opened (blue) and
--charts-series-closed (green). Add more pairs for every
color_class you use:
}
Dark mode is automatic via @media (prefers-color-scheme: dark).
Runtime color override
Each legend dot is a clickable color picker (<input type="color">)
backed by an internal RwSignal<HashMap<String, String>>. Picking a
new color writes inline CSS variables on .charts-root so the chart
re-themes immediately. Choices are per-instance and not persisted
to disk — wire your own persistence by reading the override map from
your app's state if needed.
License
Dual-licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option. Contributions intentionally submitted for inclusion in this crate shall be dual-licensed as above, without any additional terms or conditions.