Time series, trends, anything continuous: this is the chart for it. Datasets can be filled to make an area chart, stacked, or mixed with bar datasets in the same component, and they all take their styling from the active daisyUI theme. The live feed example below redraws as new points arrive.
Basic Line Chart
<c-lb.chart.line legend="bottom" data='{
"labels": ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
"datasets": [
{ "label": "Users", "data": [120, 180, 95, 210, 170, 230, 160] },
{ "label": "Sessions", "data": [200, 310, 150, 390, 280, 420, 290] }
]
}' />
Multiple Datasets
<c-lb.chart.line legend="bottom" data='{
"labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
"datasets": [
{ "label": "2023", "data": [42, 38, 51, 47, 62, 58, 71, 68, 54, 49, 63, 75] },
{ "label": "2024", "data": [48, 44, 57, 52, 69, 65, 78, 74, 61, 55, 70, 82] }
]
}' />
Filled Area
<c-lb.chart.line legend="bottom" data='{
"labels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug"],
"datasets": [
{
"label": "Revenue",
"data": [4200, 3800, 5100, 4700, 6200, 5800, 6900, 7200],
"backgroundColor": "primary-light",
"borderColor": "primary",
"fill": true,
"tension": 0.4
},
{
"label": "Expenses",
"data": [2100, 2400, 2800, 2200, 3100, 2700, 3400, 3100],
"backgroundColor": "secondary-light",
"borderColor": "secondary",
"fill": true,
"tension": 0.4
},
{
"label": "Profit",
"data": [2100, 1400, 2300, 2500, 3100, 3100, 3500, 4100],
"backgroundColor": "accent-light",
"borderColor": "accent",
"fill": true,
"tension": 0.4
}
]
}' />
Reactive
<script>
const lineWeek = {
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [
{ label: 'Users', data: [120, 180, 95, 210, 170, 230, 160] },
{ label: 'Sessions', data: [200, 310, 150, 390, 280, 420, 290] },
],
},
};
const lineMonth = {
data: {
labels: ['Week 1', 'Week 2', 'Week 3', 'Week 4'],
datasets: [
{ label: 'Users', data: [870, 1020, 940, 1180] },
{ label: 'Sessions', data: [1540, 1830, 1650, 2100] },
],
},
};
</script>
<c-lbr.signals
$view="week"
:$chartData="{
'data': {
'labels': ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
'datasets': [
{'label': 'Users', 'data': [120, 180, 95, 210, 170, 230, 160]},
{'label': 'Sessions', 'data': [200, 310, 150, 390, 280, 420, 290]},
],
}
}"
/>
<div class="flex flex-col gap-3">
<div class="flex gap-2">
<c-lb.button
size="sm"
btnStyle="ghost"
data-class="{'btn-active': $view === 'week'}"
data-on:click="$view = 'week'; $chartData = lineWeek"
>
Weekly
</c-lb.button>
<c-lb.button
size="sm"
btnStyle="ghost"
data-class="{'btn-active': $view === 'month'}"
data-on:click="$view = 'month'; $chartData = lineMonth"
>
Monthly
</c-lb.button>
</div>
<c-lb.chart.line legend="bottom" data="$chartData" />
</div>
Live Feed
<script>
let liveTimer = null;
function nextLivePoint(chart, tick) {
const pad = n => String(n).padStart(2, '0');
const label = pad(Math.floor(tick * 5 / 60)) + ':' + pad((tick * 5) % 60);
const series = chart.data.datasets[0].data;
const last = series[series.length - 1];
const next = Math.round(Math.min(95, Math.max(5, last + (Math.random() * 20 - 10))));
let labels = chart.data.labels.concat([label]);
let values = series.concat([next]);
if (labels.length > 12) {
labels = labels.slice(1);
values = values.slice(1);
}
return { data: { labels, datasets: [{ label: 'Live metric', data: values }] } };
}
</script>
<c-lbr.signals
$running="false"
:$tick="0"
:$chartData="{
'data': {
'labels': ['00:00', '00:05', '00:10', '00:15', '00:20', '00:25', '00:30'],
'datasets': [{'label': 'Live metric', 'data': [42, 58, 35, 71, 49, 63, 55]}],
}
}"
/>
<div class="flex flex-col gap-3">
<div class="flex gap-2">
<c-lb.button
size="sm"
data-class="{'btn-error': $running, 'btn-primary': !$running}"
data-on:click="
$running = !$running;
if ($running) {
liveTimer = setInterval(() => {
$tick = $tick + 1;
$chartData = nextLivePoint($chartData, $tick);
}, 800);
} else {
clearInterval(liveTimer);
}
"
>
<span data-text="$running ? 'Stop' : 'Start live feed'"></span>
</c-lb.button>
</div>
<c-lb.chart.line data="$chartData" options='{"animation": false}' />
</div>
API Reference
| Property | Type | Default | Required | Description |
|---|---|---|---|---|
| class | string | - | No | Additional CSS classes applied to the chart wrapper div |
| height | string |
300
|
No | Canvas height in pixels |
| legend |
top
bottom
left
right
none
|
top
|
No | Legend position; use 'none' to hide the legend |
| data | string |
{}
|
No | JSON string — Chart.js data object with labels and datasets |
| options | string |
{}
|
No | JSON string — Chart.js options object merged on top of labb defaults |
| Slot Name | Description |
|---|---|
| default | Not used — chart is rendered via the data prop |