Sorting And Types
This demo shows how chart components handle common x value shapes: continuous numeric values, ordered category labels, and boolean categories. In each case, y values must be finite numbers.
Boilerplate
First, we create the import aliases for TinyBase and React modules we'll need:
<script type="importmap">
{
"imports": {
"tinybase": "https://esm.sh/tinybase@8.5.0-beta.2",
"tinybase/ui-react": "https://esm.sh/tinybase@8.5.0-beta.2/ui-react",
"tinybase/ui-react-dom-charts": "https://esm.sh/tinybase@8.5.0-beta.2/ui-react-dom-charts",
"react": "https://esm.sh/react@^19.2.7",
"react/jsx-runtime": "https://esm.sh/react@^19.2.7/jsx-runtime",
"react-dom/client": "https://esm.sh/react-dom@^19.2.7/client"
}
}
</script>
We need a Store, a Provider, and the chart components:
import React from 'react';
import {createRoot} from 'react-dom/client';
import {createStore} from 'tinybase';
import {Provider, useCreateStore} from 'tinybase/ui-react';
import {
BarChart,
BarSeries,
CartesianChart,
LineChart,
} from 'tinybase/ui-react-dom-charts';
The App
The Store contains three small Tables so each chart can focus on one data binding behavior:
const App = () => {
const store = useCreateStore(() =>
createStore()
.setTable('measurements', {
third: {x: 3, score: 17},
first: {x: 1, score: 8},
fifth: {x: 5, score: 27},
second: {x: 2, score: 13},
fourth: {x: 4, score: 22},
})
.setTable('channels', {
organic: {channel: 'Organic', rank: 1, visits: 39},
referral: {channel: 'Referral', rank: 3, visits: 24},
paid: {channel: 'Paid', rank: 2, visits: 31},
direct: {channel: 'Direct', rank: 4, visits: 18},
})
.setTable('flags', {
active: {enabled: true, order: 1, accounts: 28},
inactive: {enabled: false, order: 2, accounts: 11},
}),
);
return (
<Provider store={store}>
<Body />
</Provider>
);
};
addEventListener('load', () => createRoot(document.body).render(<App />));
The Chart Gallery
When the x values are all numbers, a LineChart component uses a continuous x axis. String and boolean x values are categories, and can be ordered with sortCellId:
const Body = () => (
<main>
<section>
<LineChart
className="chart chart-numbers"
tableId="measurements"
xCellId="x"
yCellId="score"
/>
</section>
<section>
<BarChart
className="chart chart-categories"
tableId="channels"
xCellId="channel"
yCellId="visits"
sortCellId="rank"
/>
</section>
<section>
<CartesianChart className="chart chart-booleans" tableId="flags">
<BarSeries
className="series-accounts"
label="Accounts"
sortCellId="order"
xCellId="enabled"
yCellId="accounts"
/>
</CartesianChart>
</section>
</main>
);
Styling
The same CSS structure works across all three examples:
@font-face {
font-family: Inter;
src: url(https://tinybase.org/fonts/inter.woff2) format('woff2');
}
* {
box-sizing: border-box;
}
body {
font-family: Inter, sans-serif;
margin: 0;
}
main {
display: grid;
gap: 1rem;
grid-template-columns: repeat(3, minmax(0, 1fr));
margin: 2rem auto;
max-width: 72rem;
padding: 0 2rem;
section {
min-width: 0;
}
}
.chart {
display: block;
font-size: 12px;
height: 14rem;
width: 100%;
.grid {
color: #d8e1eb;
stroke-dasharray: 4 6;
}
.axes {
color: #677489;
.title {
fill: #1f2937;
font-weight: 700;
}
}
.area {
fill: #2b8c67;
fill-opacity: 0.12;
}
.line {
fill: none;
stroke: #2b8c67;
stroke-linecap: round;
stroke-linejoin: round;
stroke-width: 3;
}
.points {
fill: white;
stroke: #2b8c67;
stroke-width: 2;
}
.bar {
fill: #5367c9;
}
&-booleans {
.bar {
fill: #d16b3f;
}
}
}
@media (max-width: 52rem) {
main {
grid-template-columns: 1fr;
}
}
Numbers become a continuous x scale for line charts. Strings and booleans become ordered categories, with boolean labels rendered as true and false.