Skip to content
CodeAtlas UI

Charts

Sparkline

Inline micro charts for KPI cards, table rows and live streams.

<script>
  import { Sparkline } from "@codeatlasdev/ui/charts";
</script>

<Sparkline data={[42, 51, 58, 63, 72]} trend="up" height="32px" />

A sparkline has no axes, legend or tooltip. trend picks the color: success for up, error for down and a neutral tone otherwise.

KPI cards with trend lines

Monthly Revenue $112k
+18.4%
Active Users 24.8k
+12.1%
Churn Rate 2.3%
-0.4%
Avg Session 4m 12s
-8.2%
Code
svelte
<script lang="ts">
  import { GlassCard, Grid, Stack, Row } from '@codeatlasdev/ui';
  import { Sparkline } from '@codeatlasdev/ui/charts';

  const kpis = [
    { label: 'Monthly Revenue', value: '$112k', change: '+18.4%', trend: 'up' as const, data: [42, 51, 58, 63, 72, 80, 88, 95, 112] },
    { label: 'Active Users', value: '24.8k', change: '+12.1%', trend: 'up' as const, data: [18, 19, 21, 20, 22, 23, 22, 24, 25] },
    { label: 'Churn Rate', value: '2.3%', change: '-0.4%', trend: 'down' as const, data: [3.1, 2.9, 2.8, 2.7, 2.9, 2.6, 2.5, 2.4, 2.3] },
    { label: 'Avg Session', value: '4m 12s', change: '-8.2%', trend: 'down' as const, data: [5.1, 4.8, 4.6, 4.7, 4.4, 4.5, 4.3, 4.2, 4.2] },
  ];
</script>

<Grid cols="repeat(auto-fill,minmax(220px,1fr))" gap={16}>
  {#each kpis as k}
    <GlassCard>
      <Stack gap={8}>
        <span class="meta">{k.label}</span>
        <span class="value">{k.value}</span>
        <Row justify="space-between" align="center" gap={8}>
          <span class="change" class:up={k.trend === 'up'} class:down={k.trend === 'down'}>{k.change}</span>
          <div class="spark"><Sparkline data={k.data} trend={k.trend} height="32px" /></div>
        </Row>
      </Stack>
    </GlassCard>
  {/each}
</Grid>

<style>
  .meta { font-size: var(--ca-font-size-caption); color: var(--ca-text-secondary); }
  .value { font-size: var(--ca-font-size-h5); font-weight: 700; color: var(--ca-text-primary); }
  .change { font-size: var(--ca-font-size-caption); }
  .up { color: var(--ca-semantic-success); }
  .down { color: var(--ca-semantic-error); }
  .spark { flex: 1; min-width: 0; }
</style>

Table row sparklines

ProductLast 6 monthsTrend
Atlas Pro
▲ Growing
Nova Suite
▲ Growing
Relay SDK
→ Stable
Mesh API
▼ Declining
Code
svelte
<script lang="ts">
  import { GlassCard } from '@codeatlasdev/ui';
  import { Sparkline } from '@codeatlasdev/ui/charts';

  const rows = [
    { product: 'Atlas Pro', revenue: [84, 91, 88, 96, 102, 110], trend: 'up' as const },
    { product: 'Nova Suite', revenue: [62, 58, 64, 61, 67, 72], trend: 'up' as const },
    { product: 'Relay SDK', revenue: [45, 47, 44, 43, 46, 45], trend: 'neutral' as const },
    { product: 'Mesh API', revenue: [38, 35, 32, 30, 28, 26], trend: 'down' as const },
  ];
  const labels = { up: '▲ Growing', down: '▼ Declining', neutral: '→ Stable' };
</script>

<GlassCard flush full>
  <table>
    <thead>
      <tr><th>Product</th><th>Last 6 months</th><th class="right">Trend</th></tr>
    </thead>
    <tbody>
      {#each rows as row}
        <tr>
          <td class="name">{row.product}</td>
          <td class="spark"><Sparkline data={row.revenue} trend={row.trend} height="32px" /></td>
          <td class="right trend">{labels[row.trend]}</td>
        </tr>
      {/each}
    </tbody>
  </table>
</GlassCard>

<style>
  table { width: 100%; border-collapse: collapse; font-size: var(--ca-font-size-body2); }
  th, td { padding: var(--ca-space-3) var(--ca-space-4); }
  th { text-align: left; color: var(--ca-text-secondary); font-weight: 500; box-shadow: inset 0 -1px 0 var(--ca-outline-subtle); }
  tr + tr td { box-shadow: inset 0 1px 0 var(--ca-outline-subtle); }
  .name { font-weight: 500; color: var(--ca-text-primary); }
  .spark { width: 40%; }
  .right { text-align: right; }
  .trend { font-size: var(--ca-font-size-caption); color: var(--ca-text-secondary); }
</style>

Bar sparklines

variant bar draws narrow columns instead of a line.

Weekly sessions
Bounce rate
Avg pages
Code
svelte
<script lang="ts">
  import { Row, Stack } from '@codeatlasdev/ui';
  import { Sparkline } from '@codeatlasdev/ui/charts';

  const items = [
    { label: 'Weekly sessions', data: [42, 38, 55, 61, 48, 72, 65], trend: 'up' as const },
    { label: 'Bounce rate', data: [38, 41, 37, 43, 36, 39, 35], trend: 'down' as const },
    { label: 'Avg pages', data: [3.2, 3.4, 3.1, 3.5, 3.3, 3.4, 3.6], trend: 'neutral' as const },
  ];
</script>

<Row gap={24} wrap align="center">
  {#each items as s}
    <div class="item">
      <Stack gap={6}>
        <span class="label">{s.label}</span>
        <Sparkline data={s.data} variant="bar" trend={s.trend} height="40px" />
      </Stack>
    </div>
  {/each}
</Row>

<style>
  .item { width: 160px; }
  .label { font-size: var(--ca-font-size-caption); color: var(--ca-text-secondary); }
</style>

Live streaming micro charts

CPU 62%
Memory 73%
Network 35%
Code
svelte
<script lang="ts">
  import { GlassCard, Grid, Stack, Row } from '@codeatlasdev/ui';
  import { Sparkline } from '@codeatlasdev/ui/charts';
  import { onMount } from 'svelte';

  let live = $state({
    cpu: [45, 48, 52, 49, 55, 58, 54, 60, 57, 62],
    mem: [62, 65, 63, 67, 70, 68, 72, 71, 74, 73],
    net: [12, 18, 15, 22, 19, 28, 24, 31, 27, 35],
  });

  const next = (a: number[], lo: number, hi: number, step: number) =>
    [...a.slice(1), Math.min(hi, Math.max(lo, a[a.length - 1] + (Math.random() - 0.45) * step))];

  onMount(() => {
    const id = setInterval(() => {
      live = { cpu: next(live.cpu, 20, 95, 8), mem: next(live.mem, 40, 95, 5), net: next(live.net, 5, 80, 12) };
    }, 600);
    return () => clearInterval(id);
  });

  const metrics = $derived([
    { label: 'CPU', data: live.cpu },
    { label: 'Memory', data: live.mem },
    { label: 'Network', data: live.net },
  ]);
</script>

<Grid cols="repeat(auto-fit,minmax(200px,1fr))" gap={16}>
  {#each metrics as m}
    <GlassCard>
      <Stack gap={4}>
        <Row justify="space-between">
          <span class="label">{m.label}</span>
          <span class="value">{m.data[m.data.length - 1].toFixed(0)}%</span>
        </Row>
        <Sparkline data={m.data} height="40px" />
      </Stack>
    </GlassCard>
  {/each}
</Grid>

<style>
  .label { font-size: var(--ca-font-size-caption); color: var(--ca-text-secondary); }
  .value { color: var(--ca-brand-text); font-weight: 600; }
</style>

Props

PropTypeDefaultDescription
datanumber[]–Values to plot.
variant'line' | 'bar''line'Line with a soft area, or narrow bars.
trend'up' | 'down' | 'neutral'–Colors the series: success, error or neutral.
colorstring–Explicit hex or rgb color. Overrides trend. Use hex or rgb, not oklch.
heightstring'48px'CSS height of the chart.
classstring''Extra class names.