Migrate web charts from Recharts to Bklit - #171
Open
ZingerLittleBee wants to merge 25 commits into
Open
Conversation
Install the Bklit bar chart registry (BarChart, Bar, categorical axes) and add a StackedBarPlot wrapper matching the existing metric plot pattern: figure + legend list + screen-reader table. Local extensions on the vendored files: - `maxBarWidth` caps the auto-sized band (Recharts `maxBarSize`) - stacked vertical series scale to the column total instead of the largest single value, which used to overflow the plot area - horizontal stacked segments size to their own value; upstream subtracted the stack offset twice and rendered negative widths - categorical axes take a label formatter and fit their label count to the plot width BarValueAxis is repo-local: upstream ships no numeric axis for horizontal bars.
Move the dashboard traffic widget, security event timeline, server traffic card and server traffic tab off Recharts onto StackedBarPlot. The historical cycle comparison keeps its horizontal layout and now labels each cycle by its start date instead of truncating the full range. Daily and hourly charts gain a tooltip title: the Bklit crosshair hides the axis tick under the cursor, so the hovered bucket would otherwise be unlabelled.
MetricAreaPlot now takes a series list so a single wrapper can render stacked traffic trends alongside single-metric charts, and SparklinePlot covers the decorative inline case.
Ports the ping results chart, global traffic trend and metric card sparkline onto the Bklit wrappers, then removes the recharts dependency along with its lazy loader, chart shim and manual chunk.
Restores the dedicated chart chunk recharts used to have: visx, d3 and motion move out of index.js (1543 kB -> 1380 kB) so app releases stop invalidating them.
The server traffic tab has always called GET /api/traffic/{id}/daily,
but no such route existed, so the daily trend chart rendered its empty
state on every server. Adds the route over the existing daily breakdown
query with optional from/to dates.
Mobile used the persisted grid_h verbatim, so a layout saved below a widget type's minimum squashed the card until inner flex rows collapsed to zero height and the metric card sparkline disappeared.
The bklit registry install pulled in a loading skeleton and two mount animation hooks that nothing in the app imports.
The bklit theme block ships a five-step scale palette for chart types the app does not use; no component or utility class references them.
…it charts valueDomain skips the automatic 10% headroom so status strips can fill the plot height, and tooltip rows key by index because label+color is not unique (duplicate labels left stale rows on the previous point).
Replaces the hand-painted gradient track and its 90 tooltip triggers with a four-series stacked bar chart (one series per status) plus the shared chart tooltip, and adds the screen-reader table the other charts have. crispEdges keeps the 1-3px day columns from anti-aliasing unevenly.
The vendored chart modules import d3-shape and d3-array types, which only resolved locally through a stale node_modules tree; a frozen install in CI had no top-level @types entry and tsc fell back to implicit any.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces Recharts with Bklit chart primitives (visx + motion) across the web app, then removes the
rechartsdependency entirely. Every chart now goes through a small set of shared wrappers inapps/web/src/components/charts/, so tooltips, axis formatting, legends and screen-reader tables behave the same everywhere.Two bugs surfaced during verification and are fixed here as well: a per-server daily traffic endpoint the UI had always called but that never existed, and a single-column dashboard layout that ignored a widget type's minimum height.
Chart migration
MetricAreaPlot(multi-series areas),MetricLinePlot,StackedBarPlot(vertical + horizontal),SparklinePlot. Each renders<figure aria-label>+ anaria-hiddenchart + an optional legend + ansr-onlydata table sampled to 50 rows.shape-rendering: crispEdgespreserves the reason the old implementation existed: 1–3px day columns must not anti-alias unevenly.maxBarWidth, a stacked-aware axis maximum,formatLabelon the bar axes, a bottom numeric axis for horizontal bars,valueDomainfor full-height status strips, a horizontal stacked-segment width fix, and tooltip rows keyed by index (label+color is not unique, which left stale rows behind).recharts,components/ui/chart.tsxandcomponents/ui/recharts-lazy.tsxare gone; chart vendor deps live in their ownchartschunk so app releases do not invalidate them.Bundle, measured by rebuilding the pre-migration commit with the same tooling: raw 2896.7 kB → 2781.7 kB, gzip 863.2 kB → 854.2 kB. The 397 kB Recharts chunk disappears but Bklit + visx claim most of that back, so the gzip win is small.
Fixes
GET /api/traffic/{server_id}/dailynow exists (optionalfrom/to, defaults to the last 30 days, 400 on unparsable or inverted ranges, 404 on unknown servers). The server Traffic tab had always requested it and always fell back to its empty state.grid_hverbatim, so a layout saved below a widget type'sminHsquashed the card until inner flex rows collapsed to zero height and the metric-card sparkline vanished.Verification
cargo test --workspace --no-fail-fast— 3226 passed, 0 failedcargo clippy --workspace -- -D warnings— cleanbun run typecheck(ui + web + docs),bun x ultracite check src,bun run test(732 passed),bun run buildNotes
tests/performance.mdkeeps its measured widget-capacity numbers; they were taken with the previous chart engine and have not been re-measured.