1. Components
  2. chart

Chart

Zoomable time series, candlesticks, heatmaps, radar, scatter and funnels, drawn by Apache ECharts and themed with your Flexiwind tokens.

Demo

Drag the handles under the chart, or scroll inside it, to zoom.

Daily sessions
Date Sessions
2026-01-01 1.4k
2026-01-02 1.4k
2026-01-03 1.5k
2026-01-04 1.5k
2026-01-05 1.5k
2026-01-06 1.5k
2026-01-07 1.6k
2026-01-08 1.6k
2026-01-09 1.6k
2026-01-10 1.6k
2026-01-11 1.6k
2026-01-12 1.6k
2026-01-13 1.6k
2026-01-14 1.6k
2026-01-15 1.6k
2026-01-16 1.6k
2026-01-17 1.6k
2026-01-18 1.6k
2026-01-19 1.6k
2026-01-20 1.7k
2026-01-21 1.7k
2026-01-22 1.7k
2026-01-23 1.7k
2026-01-24 1.7k
2026-01-25 1.7k
2026-01-26 1.7k
2026-01-27 1.7k
2026-01-28 1.7k
2026-01-29 1.7k
2026-01-30 1.7k
2026-01-31 1.6k
2026-02-01 1.6k
2026-02-02 1.6k
2026-02-03 1.6k
2026-02-04 1.6k
2026-02-05 1.6k
2026-02-06 1.6k
2026-02-07 1.6k
2026-02-08 1.6k
2026-02-09 1.6k
2026-02-10 1.6k
2026-02-11 1.6k
2026-02-12 1.6k
2026-02-13 1.6k
2026-02-14 1.6k
2026-02-15 1.5k
2026-02-16 1.5k
2026-02-17 1.5k
2026-02-18 1.5k
2026-02-19 1.4k
2026-02-20 1.4k
2026-02-21 1.4k
2026-02-22 1.4k
2026-02-23 1.3k
2026-02-24 1.3k
2026-02-25 1.3k
2026-02-26 1.3k
2026-02-27 1.3k
2026-02-28 1.3k
2026-03-01 1.4k
2026-03-02 1.4k
2026-03-03 1.4k
2026-03-04 1.4k
2026-03-05 1.4k
2026-03-06 1.4k
2026-03-07 1.4k
2026-03-08 1.4k
2026-03-09 1.4k
2026-03-10 1.3k
2026-03-11 1.3k
2026-03-12 1.3k
2026-03-13 1.3k
2026-03-14 1.3k
2026-03-15 1.3k
2026-03-16 1.3k
2026-03-17 1.4k
2026-03-18 1.4k
2026-03-19 1.4k
2026-03-20 1.4k
2026-03-21 1.5k
2026-03-22 1.5k
2026-03-23 1.5k
2026-03-24 1.6k
2026-03-25 1.6k
2026-03-26 1.6k
2026-03-27 1.6k
2026-03-28 1.6k
2026-03-29 1.6k
2026-03-30 1.6k
2026-03-31 1.6k
2026-04-01 1.6k
2026-04-02 1.6k
2026-04-03 1.6k
2026-04-04 1.6k
2026-04-05 1.7k
2026-04-06 1.7k
2026-04-07 1.7k
2026-04-08 1.8k
2026-04-09 1.8k
2026-04-10 1.8k
2026-04-11 1.9k
2026-04-12 1.9k
2026-04-13 1.9k
2026-04-14 1.9k
2026-04-15 1.9k
2026-04-16 1.9k
2026-04-17 1.9k
2026-04-18 1.9k
2026-04-19 1.9k
2026-04-20 1.8k
2026-04-21 1.8k
2026-04-22 1.8k
2026-04-23 1.8k
2026-04-24 1.8k
2026-04-25 1.8k
2026-04-26 1.8k
2026-04-27 1.9k
2026-04-28 1.9k
2026-04-29 1.9k
2026-04-30 1.9k
2026-05-01 1.9k
2026-05-02 1.9k
2026-05-03 1.9k
2026-05-04 1.9k
2026-05-05 1.9k
2026-05-06 1.8k
2026-05-07 1.8k
2026-05-08 1.8k
2026-05-09 1.7k
2026-05-10 1.7k
2026-05-11 1.7k
2026-05-12 1.7k
2026-05-13 1.7k
2026-05-14 1.7k
2026-05-15 1.6k
2026-05-16 1.7k
2026-05-17 1.7k
2026-05-18 1.7k
2026-05-19 1.7k
2026-05-20 1.7k
2026-05-21 1.7k
2026-05-22 1.7k
2026-05-23 1.7k
2026-05-24 1.6k
2026-05-25 1.6k
2026-05-26 1.6k
2026-05-27 1.6k
2026-05-28 1.5k
2026-05-29 1.5k
2026-05-30 1.5k
2026-05-31 1.5k
2026-06-01 1.5k
2026-06-02 1.5k
2026-06-03 1.5k
2026-06-04 1.5k
2026-06-05 1.5k
2026-06-06 1.6k
2026-06-07 1.6k
2026-06-08 1.6k
2026-06-09 1.6k
2026-06-10 1.6k
2026-06-11 1.7k
2026-06-12 1.7k
2026-06-13 1.7k
2026-06-14 1.7k
2026-06-15 1.7k
2026-06-16 1.6k
2026-06-17 1.6k
2026-06-18 1.6k
2026-06-19 1.6k
2026-06-20 1.7k
2026-06-21 1.7k
2026-06-22 1.7k
2026-06-23 1.7k
2026-06-24 1.8k
2026-06-25 1.8k
2026-06-26 1.8k
2026-06-27 1.9k
2026-06-28 1.9k
2026-06-29 1.9k
2026-06-30 2k
2026-07-01 2k
2026-07-02 2k
2026-07-03 2k
2026-07-04 2k
2026-07-05 2k
2026-07-06 2k
2026-07-07 2k
2026-07-08 2k
2026-07-09 2k
2026-07-10 2k
2026-07-11 2k
2026-07-12 2k
2026-07-13 2k
2026-07-14 2.1k
2026-07-15 2.1k
2026-07-16 2.1k
2026-07-17 2.1k
2026-07-18 2.1k
2026-07-19 2.2k
2026-07-20 2.2k
2026-07-21 2.2k
2026-07-22 2.1k
2026-07-23 2.1k
2026-07-24 2.1k
2026-07-25 2.1k
2026-07-26 2.1k
2026-07-27 2k
2026-07-28 2k
2026-07-29 2k
2026-07-30 2k
2026-07-31 2k
2026-08-01 2k
2026-08-02 2k
2026-08-03 2k
2026-08-04 2k
2026-08-05 2k
2026-08-06 2k
2026-08-07 2k
2026-08-08 2k
2026-08-09 2k
2026-08-10 2k
2026-08-11 1.9k
2026-08-12 1.9k
2026-08-13 1.9k
2026-08-14 1.8k
2026-08-15 1.8k
2026-08-16 1.8k
2026-08-17 1.8k
2026-08-18 1.8k
2026-08-19 1.8k
2026-08-20 1.8k
2026-08-21 1.8k
2026-08-22 1.8k
2026-08-23 1.8k
2026-08-24 1.8k
2026-08-25 1.8k
2026-08-26 1.8k
2026-08-27 1.8k
2026-08-28 1.8k
2026-08-29 1.8k
2026-08-30 1.8k
2026-08-31 1.8k
2026-09-01 1.8k
2026-09-02 1.8k
2026-09-03 1.7k
2026-09-04 1.7k
2026-09-05 1.7k
2026-09-06 1.7k
2026-09-07 1.7k
2026-09-08 1.8k
2026-09-09 1.8k
2026-09-10 1.8k
2026-09-11 1.8k
2026-09-12 1.9k
2026-09-13 1.9k
2026-09-14 1.9k
2026-09-15 2k
2026-09-16 2k
2026-09-17 2k
2026-09-18 2k
2026-09-19 2k
2026-09-20 2k
2026-09-21 2k
2026-09-22 2k
2026-09-23 2k
2026-09-24 2k
2026-09-25 2k
2026-09-26 2k
2026-09-27 2.1k
2026-09-28 2.1k
2026-09-29 2.1k
2026-09-30 2.2k
2026-10-01 2.2k
2026-10-02 2.2k
2026-10-03 2.3k
2026-10-04 2.3k
2026-10-05 2.3k
2026-10-06 2.3k
2026-10-07 2.3k
2026-10-08 2.3k
2026-10-09 2.3k
2026-10-10 2.3k
2026-10-11 2.3k
2026-10-12 2.3k
2026-10-13 2.3k
2026-10-14 2.3k
2026-10-15 2.2k
2026-10-16 2.3k
2026-10-17 2.3k
2026-10-18 2.3k
2026-10-19 2.3k
2026-10-20 2.3k
2026-10-21 2.3k
2026-10-22 2.3k
2026-10-23 2.3k
2026-10-24 2.3k
2026-10-25 2.3k
2026-10-26 2.3k
2026-10-27 2.3k
2026-10-28 2.3k
2026-10-29 2.2k
2026-10-30 2.2k
2026-10-31 2.2k
2026-11-01 2.2k
2026-11-02 2.1k
2026-11-03 2.1k
2026-11-04 2.1k
2026-11-05 2.1k
2026-11-06 2.1k
2026-11-07 2.1k
2026-11-08 2.1k
2026-11-09 2.1k
2026-11-10 2.1k
2026-11-11 2.1k
2026-11-12 2.1k
2026-11-13 2.1k
2026-11-14 2.1k
2026-11-15 2.1k
2026-11-16 2.1k
2026-11-17 2k
2026-11-18 2k
2026-11-19 2k
2026-11-20 2k
2026-11-21 1.9k
2026-11-22 1.9k
2026-11-23 1.9k
2026-11-24 1.9k
2026-11-25 1.9k
2026-11-26 1.9k
2026-11-27 2k
2026-11-28 2k
2026-11-29 2k
2026-11-30 2k
2026-12-01 2k
2026-12-02 2.1k
2026-12-03 2.1k
2026-12-04 2.1k
2026-12-05 2.1k
2026-12-06 2.1k
2026-12-07 2.1k
2026-12-08 2.1k
2026-12-09 2.1k
2026-12-10 2.1k
2026-12-11 2.1k
2026-12-12 2.1k
2026-12-13 2.1k
2026-12-14 2.1k
2026-12-15 2.1k
2026-12-16 2.2k
2026-12-17 2.2k
2026-12-18 2.2k
2026-12-19 2.3k
2026-12-20 2.3k
2026-12-21 2.3k
2026-12-22 2.4k
2026-12-23 2.4k
2026-12-24 2.4k
2026-12-25 2.4k
2026-12-26 2.4k
2026-12-27 2.4k
2026-12-28 2.4k
2026-12-29 2.4k
2026-12-30 2.4k
2026-12-31 2.4k
@php
    // One year of daily sessions. In an app: a query grouped by day.
    $days = collect(range(0, 364))->map(fn (int $i) => [
        'date' => now()->startOfYear()->addDays($i)->format('Y-m-d'),
        'sessions' => (int) round(1400 + $i * 2.4 + sin($i / 14) * 220 + sin($i / 3.1) * 60),
    ])->all();
@endphp

<x-ui.echart type="area" datetime zoom :data="$days" index="date" label="Daily sessions" class="h-80 w-full"
    :config="['sessions' => ['label' => 'Sessions']]" />

When to use it

Flexiwind has two chart components with the same data , index and config :

  • Chart draws on the server, with no chart library. It covers most dashboards: bar, line, area, pie, donut, radial.
  • <x-ui.echart> , on this page, hands the data to Apache ECharts for what only a charting library does well: zoom and pan on long time series, candlesticks, heatmaps, radar, scatter, funnels, and thousands of points.

Switching from one to the other is a one-word change. Every chart type has its own page in the ECharts group of the sidebar, from a simple example to more involved ones.

Installation

Shell
php artisan flexi:add echarts

This adds the Blade component, two plugin files, the resources/js/charts.js entry and the echarts npm package.

ECharts gets its own bundle, never mixed into flexilla.js . Two steps make that happen.

1. Declare the entry in vite.config.js , next to your other inputs:

laravel({
    input: [
        "resources/css/app.css",
        "resources/js/app.js",
        "resources/js/flexilla.js",
        "resources/js/charts.js",
    ],
}),

2. Load it only in the layouts that show charts:

@vite(['resources/js/app.js', 'resources/js/flexilla.js', 'resources/js/charts.js'])

resources/js/charts.js registers the plugin; there is nothing to add to flexilla.js :

import { EChartsPlugin } from "./plugins/echarts";

Alpine.plugin(EChartsPlugin);

Do not register EChartsPlugin in flexilla.js , and never import "echarts" yourself: ECharts would then be downloaded by every page, with or without a chart.

Apache ECharts is licensed under Apache 2.0: free for every project and every company, with no revenue threshold and no license key.

Bundle size

Because charts.js is its own Vite input, the build writes ECharts to separate files, and a layout that does not load charts.js never downloads them:

File Loaded Size (gzip)
flexilla.js , your plugins on every page no ECharts code
charts.js , the plugin on pages whose layout loads it ~4 kB
ECharts core, SVG renderer, grid, tooltip, legend with the first chart of a page ~155 kB
One file per chart type (line, bar, pie…) when a chart of that type appears 3 to 10 kB each
Zoom with the first zoom chart ~12 kB
Canvas renderer with the first large chart ~5 kB

Inside that bundle, the plugin still loads the core and each chart type on demand: a page with a line chart loads the core and the line module, not candlesticks, not heatmaps.

Keep it that way:

  • One entry, one bundle. charts.js stays in input of vite.config.js and in the @vite call of the chart layouts only.
  • Never import echarts from app.js or flexilla.js . A static import pulls the whole library into every page.
  • Add chart types in echarts-core.js , as one more line in LOADERS . Each new type becomes its own file.

Theming

Colors come from your theme: series use --chart-1 to --chart-5 , text and grid lines use --muted-foreground and --border , candlesticks use --success and --destructive . Switching between light and dark mode redraws the charts with the new colors.

Livewire

The chart follows your component: when the data changes, it animates to the new values instead of being rebuilt.

<x-ui.echart type="bar" :data="$this->salesByMonth" index="month" wire:key="sales" />

Anything else

options is merged last into the ECharts options, so everything ECharts supports is one array away. Arrays of objects are merged item by item: 'series' => [['label' => …]] restyles the first series without losing its data. Only JSON — no JavaScript functions.

<x-ui.echart type="line" :data="$data" index="day" :options="[
    'yAxis' => ['min' => 0, 'max' => 100],
    'animation' => false,
]" />

Props

Prop Description
data , index , config Same as Chart . For pie, donut and funnel, config is keyed by category.
type (line|area|bar|scatter|pie|donut|funnel|radar|heatmap|candlestick) Defaults to line .
stacked , horizontal (boolean) For bars, lines and areas.
datetime (boolean) The index column holds dates (2026-07-01 , 2026-07-01T14:30 ): the axis becomes a time axis.
zoom (boolean) Adds a zoom slider, and zooming with the wheel or a pinch.
curve (smooth|linear) Line interpolation.
max (number) Top of each radar axis. Defaults to the largest value.
format , prefix , suffix Same as Chart .
legend (boolean|null) Shown by default for two series or more.
renderer (svg|canvas|null) svg by default, canvas past 2,000 points.
options (array) Raw ECharts options, merged last.
label (string) Accessible name.

Size the chart with classes: class="h-96" . It defaults to h-80 w-full .

Accessibility

The drawing is hidden from screen readers, which read a visually hidden data table instead — up to 500 rows. Past that, they get a one-line summary: a 5,000-row table helps nobody.