Appearance
Architecture
@ringover/ringo-charts is a pure presentation library. It exports visualization components that accept display props (titles, formatted values, data tables, loading / error states) and render HTML / Canvas / SVG.
The library does not know about POST /statistics, WidgetConfig, saved views, the catalog of widget types, or the metrics + projection + periods + where contract. It wraps Chart.js, D3 and Leaflet into reusable Vue 3 components that any Ringover app (dashboard, monitoring, webapp) can consume without coupling to the stats API.
All business intelligence — API fetching, data mapping, view configuration — lives in the platform / app (Ringover Views), not in the library.
Two levels of components
The library exposes two levels: reusable visualization primitives and business widgets that compose those primitives with header / footer / objective / alert chrome.
Level 1 — Visualization primitives
Low-level components, no Widget suffix. An app can consume them directly to build its own views. See Chart primitives.
Level 2 — Business widgets
High-level components that wrap a primitive and add a header, objective footer, loading state and drill-down. The Widget suffix makes the role explicit. These are Organisms in Atomic Design terms. They are props-driven skeletons: no fetch, no store — layout is delivered through slots and props. See Business widgets.
Their props are display props — title, value, label, trend, rows, loading, error — not a WidgetConfig object.
Atomic Design layers
Every Vue file lives in exactly one of these directories under packages/ringo-charts/src/components/:
components/
├─ atoms/ # smallest UI units (badges, dots, inline bars, menus)
│ ├─ badges/ # chip / badge / pill primitives
│ └─ widgets/ # widget chrome atoms (RoWidgetMenu)
├─ molecules/
│ ├─ charts/ # chart-adjacent molecules (RoChartFrame, RoChartTooltipCard, …)
│ └─ widgets/ # widget chrome molecules (RoWidgetCard, RoWidgetHeader, …)
└─ organisms/
├─ charts/ # chart primitives (RoBarChart, RoLineChart, RoSankey, …)
├─ states/ # loading / empty / error skeletons
└─ widgets/ # business widgets — one folder per master patternThe …Widget suffix is reserved for business widgets in organisms/widgets/. Chart and state organisms never use it. There are no pattern-a..f folders and no legacy templates/ layer.
Allowed cross-layer imports
- Atoms depend on nothing except
vue,@ringover/ringo-uiand utils. - Molecules depend on atoms.
- Chart organisms depend on atoms +
chart.js/d3-*/vue-chartjs. - Widget chrome molecules (incl.
RoWidgetCard) depend on atoms + state organisms. - State organisms depend on atoms only.
- Widget organisms compose everything below them.
Data flow: from a saved view to a component
The full path between a saved view and the rendered screen shows the library / app split:
Saved View JSON (read from S3)
|
WidgetConfig (type + settings + filters) <- app
|
StatsRequest POST /statistics <- app
|
StatsResponse (meta + data pivoted by period) <- backend
|
App adapter (maps data -> display props) <- app (COMPONENT_BY_TYPE)
|
<RoKPIWidget title="..." value="..." trend="..." /> <- ringo-charts renders- Saved View JSON — the view is read from S3; it lists widgets with their
type,settingsandfilters. - WidgetConfig — the app parses the JSON into a
WidgetConfigper widget. This type is defined in the platform, not in ringo-charts. - StatsRequest — the app builds the API request (
POST /statistics): timezone,periods[], aprojectiondiscriminated bytype, and awhere[]derived from global + per-widget filters. The library is not involved here. - StatsResponse — the backend returns resolved period ranges and metrics pivoted by period (with an automatic
deltaon relative periods). - App adapter — the platform's
COMPONENT_BY_TYPEregistry maps the catalogtypeto a ringo-charts component and transformsStatsResponseinto display props (title,value,trend,rows,loading,error, …). This adapter lives in the app, not in the library. - Render — the component receives its props and renders. It does not know where the data came from.
Why a private library
- Visual consistency — every chart shares the same
ringo-uicolor tokens, padding, animations and fonts. - Pure presentation — components accept display props and render visuals; zero business logic, zero API calls.
- Centralized maintenance — a breaking Chart.js change is fixed in one place.
- Cross-project reuse — dashboard, monitoring and webapp all install the same package.
- Tree-shakeable — a project that only needs KPIs does not ship the Sankey.
Chart.js, vue-chartjs, D3 and Leaflet are encapsulated inside ringo-charts and are not installed directly by consuming apps (except the documented peers in Getting started).