Chart States
Loading skeletons, empty states and error states for every chart — one wrapper, six skeleton shapes, and a frame height that never shifts between them.
Every state, same frame height
Signup cohort retention
| Cohort | Users | Month 0 | Month 1 | Month 2 | Month 3 | Month 4 | Month 5 | Month 6 | Month 7 | Month 8 | Month 9 | Month 10 | Month 11 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Sep 2025 | 674 | 100.0% | 60.8% | 58.7% | 53.5% | 51.0% | 47.3% | 42.8% | 39.0% | 37.7% | 36.0% | 34.7% | 33.2% |
| Oct 2025 | 1150 | 100.0% | 62.7% | 61.1% | 56.6% | 54.1% | 50.9% | 48.0% | 45.2% | 42.7% | 41.9% | 38.5% | — |
| Nov 2025 | 764 | 100.0% | 55.6% | 54.3% | 52.6% | 51.0% | 47.8% | 46.9% | 45.5% | 43.5% | 42.6% | — | — |
| Dec 2025 | 855 | 100.0% | 63.7% | 63.2% | 62.9% | 59.0% | 58.3% | 54.4% | 53.9% | 52.1% | — | — | — |
| Jan 2026 | 1245 | 100.0% | 66.4% | 66.1% | 62.8% | 61.5% | 59.1% | 56.1% | 55.8% | — | — | — | — |
| Feb 2026 | 1566 | 100.0% | 64.5% | 63.3% | 62.9% | 62.2% | 59.6% | 57.8% | — | — | — | — | — |
| Mar 2026 | 1450 | 100.0% | 65.3% | 65.0% | 64.6% | 64.3% | 62.1% | — | — | — | — | — | — |
| Apr 2026 | 1021 | 100.0% | 63.7% | 63.3% | 63.0% | 62.1% | — | — | — | — | — | — | — |
| May 2026 | 1538 | 100.0% | 59.1% | 58.8% | 58.5% | — | — | — | — | — | — | — | — |
| Jun 2026 | 1207 | 100.0% | 58.0% | 57.7% | — | — | — | — | — | — | — | — | — |
| Jul 2026 | 1781 | 100.0% | 59.1% | — | — | — | — | — | — | — | — | — | — |
| Aug 2026 | 1290 | 100.0% | — | — | — | — | — | — | — | — | — | — | — |
Skeleton variants
variant="bars"
bar, candle, volume, histogram
variant="line"
line, area, price, depth
variant="grid"
calendar, cohort, heatmap
variant="rows"
order book, cohort, tables
variant="arc"
radial, progress
variant="cards"
stat cards, KPI tiles
Empty and error
empty
no data, nothing broken
No events in this range
Widen the date range, or send your first event to start populating this chart.
error
retry is part of the state
Could not load analytics
The metrics API returned a 503. This is usually transient.
Wrapping your own chart
ChartState
wrap anything
Nothing tracked yet
Install the SDK and your first session will show up here.
Manual installation
Prefer to copy by hand? Open the Code tab on any example above and switch to the file you need — every source file is there, not just the demo. Drop them in your project like this:
chart-engine.tsxcomponents/spectrumui/charts/chart-engine.tsxcohort-chart.tsxcomponents/spectrumui/charts/cohort-chart.tsxchart-states.tsxcomponents/spectrumui/charts/chart-states.tsx
There is nothing to install — this chart draws its own SVG and imports only @/lib/utils.
Usage
import { ChartStatusSwitcher } from '@/components/spectrumui/charts/chart-states';
<ChartStatusSwitcher />ChartStatewraps anything, not just Spectrum charts — give it a height and a skeleton variant.- The frame height is identical in all four states, so nothing shifts when data lands.