chart

Beautiful charts built with Apache ECharts. Copy and paste into your apps.

PreviousNext
Bar ChartShowing total visitors for the last 6 months
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-preview',
  imports: [ZardCardImports, ZardChartImports],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Bar Chart" />
        <z-card-description zDescription="Showing total visitors for the last 6 months" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="bar"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zXAxisKey="month"
          [zXAxisFormatter]="shortMonth"
          class="w-full"
        >
          <z-chart-tooltip zIndicator="dashed" />
          <z-chart-legend />
        </z-chart>
      </z-card-content>
    </z-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartPreviewComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series = ['desktop', 'mobile'];

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

About

The chart is built on Apache ECharts, wired into Angular through ngx-echarts. Apache ECharts

Installation

1

Run the CLI

Use the CLI to add chart to your project.

Copy
npx zard-cli@latest add chart
2

Register chart to your project

app.config.ts
Copy
import { ApplicationConfig } from '@angular/core';
import { provideZardCharts } from '@/shared/components/chart/chart-echarts.provider';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZardCharts(),
  ],
};

Usage

import { ZardChartImports } from '@/shared/components/chart/chart.imports';
Copy
<z-chart
  [zConfig]="chartConfig"
  [zData]="chartData"
  zType="bar"
  [zSeries]="['desktop', 'mobile']"
  zXAxisKey="month"
  class="h-[250px] w-full"
>
  <z-chart-tooltip zIndicator="dot" />
  <z-chart-legend />
</z-chart>
Copy

Examples

chart config

The chart config holds everything about the chart that is not the data itself — labels, colors and icons — keyed by data key.
chart.config.ts
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';

// The config is decoupled from the data. It maps every data key to how it should be
// presented — label, color and (optionally) an icon rendered by the legend.
export const chartConfig: ZardChartConfig = {
  desktop: {
    label: 'Desktop',
    color: 'var(--chart-1)',
    icon: 'lucideMonitor',
  },
  mobile: {
    label: 'Mobile',
    // `theme` wins over `color` and lets each mode pick its own value.
    theme: { light: 'var(--chart-2)', dark: 'var(--chart-5)' },
  },
};
Copy

theming

Colors are declared as CSS variables and resolved to computed values before ECharts sees them, so the chart follows the theme automatically.
styles.css
/* Recommended: declare the palette once, as CSS variables, and let every chart pick it up.
   The chart resolves `var(--token)` to a computed value before handing it to ECharts and
   re-resolves it whenever the theme changes. */
:root,
.dark {
  --chart-1: oklch(0.809 0.105 251.813);
  --chart-2: oklch(0.623 0.214 259.815);
  --chart-3: oklch(0.546 0.245 262.881);
  --chart-4: oklch(0.488 0.243 264.376);
  --chart-5: oklch(0.424 0.199 265.638);
}

/* Hex, rgb(), hsl() and oklch() literals are accepted too — anywhere a color is expected. */
Copy

height

The container must resolve to a real height, or ECharts initialises at zero pixels and draws nothing. z-chart handles that on its own with aspect-video; pass a height class only when you want a different shape, and note that a height without an aspect ratio needs a width too.
height.html
<z-chart zType="bar" [zData]="chartData" [zSeries]="series" />

<z-chart class="h-[250px] w-full" zType="bar" [zData]="chartData" />

<z-chart class="mx-auto aspect-square h-[250px]" zType="pie" [zData]="chartData" />
Copy

tree shaking

ECharts is registered through provideZardCharts() and imported lazily, so it never reaches the initial bundle. Trim the registry to what you actually render.
chart-echarts.registry.ts
import { BarChart, GaugeChart, LineChart, PieChart, RadarChart } from 'echarts/charts';
import {
  AriaComponent,
  BrushComponent,
  DatasetComponent,
  DataZoomComponent,
  GraphicComponent,
  GridComponent,
  LegendComponent,
  MarkAreaComponent,
  MarkLineComponent,
  MarkPointComponent,
  PolarComponent,
  TitleComponent,
  ToolboxComponent,
  TooltipComponent,
  TransformComponent,
} from 'echarts/components';
import * as echarts from 'echarts/core';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer, SVGRenderer } from 'echarts/renderers';

// Drop what you do not use — every entry removed here leaves the bundle.
// Two must stay: LegendComponent (the HTML legend dispatches `legendToggleSelect`
// through it) and SVGRenderer (the server renders through renderToSVGString()).
echarts.use([
  BarChart,
  LineChart,
  PieChart,
  RadarChart,
  GaugeChart,
  GridComponent,
  TooltipComponent,
  LegendComponent,
  TitleComponent,
  DataZoomComponent,
  MarkLineComponent,
  MarkAreaComponent,
  MarkPointComponent,
  PolarComponent,
  GraphicComponent,
  ToolboxComponent,
  BrushComponent,
  AriaComponent,
  DatasetComponent,
  TransformComponent,
  LabelLayout,
  UniversalTransition,
  CanvasRenderer,
  SVGRenderer,
]);

export const zardEcharts = echarts;
Copy
chart-echarts.provider.ts Copy
import { provideEchartsCore } from 'ngx-echarts';

// The registry above is imported lazily, so roughly a megabyte of ECharts stays out of
// your application's initial bundle: it is fetched the first time a chart is created.
export const provideZardCharts = () =>
  provideEchartsCore({ echarts: () => import('./chart-echarts.registry').then(module => module.zardEcharts) });

tooltip

z-chart-tooltip declares the tooltip: zLabelKey and zNameKey pick the config keys used for the heading and each row, zHideLabel and zHideIndicator control what shows, and the tooltip ships the same three indicator shapes as shadcn/ui — dot, line and dashed.
Tooltip IndicatorsThe three indicator shapes, side by side

zIndicator="dot"

zIndicator="line"

zIndicator="dashed"

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig, ZardChartTooltipIndicator } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-tooltip-indicators',
  imports: [ZardCardImports, ZardChartImports],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Tooltip Indicators" />
        <z-card-description zDescription="The three indicator shapes, side by side" />
      </z-card-header>
      <z-card-content>
        <div class="grid gap-6 md:grid-cols-3">
          @for (indicator of indicators; track indicator) {
            <div class="flex flex-col gap-2">
              <p class="text-muted-foreground text-xs">zIndicator="{{ indicator }}"</p>
              <z-chart
                zType="bar"
                [zConfig]="chartConfig"
                [zData]="chartData"
                [zSeries]="series"
                zXAxisKey="month"
                [zXAxisFormatter]="shortMonth"
                class="h-[180px] w-full"
              >
                <z-chart-tooltip [zIndicator]="indicator" [zDefaultIndex]="1" />
              </z-chart>
            </div>
          }
        </div>
      </z-card-content>
    </z-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartTooltipIndicatorsComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series = ['desktop', 'mobile'];

  protected readonly indicators: ZardChartTooltipIndicator[] = ['dot', 'line', 'dashed'];

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

legend

z-chart-legend renders the shadcn markup below (or above) the chart and toggles a series on click when it is hovered or pressed. zVerticalAlign picks which side it sits on.
LegendzVerticalAlign places z-chart-legend above or below the chart

zVerticalAlign="top"

zVerticalAlign="bottom"

import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';
import type { ZardChartLegendAlignVariants } from '@/shared/components/chart/chart.variants';

@Component({
  selector: 'z-demo-chart-legend',
  imports: [ZardCardImports, ZardChartImports],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Legend" />
        <z-card-description zDescription="zVerticalAlign places z-chart-legend above or below the chart" />
      </z-card-header>
      <z-card-content>
        <div class="grid gap-6 md:grid-cols-2">
          @for (align of aligns; track align) {
            <div class="flex flex-col gap-2">
              <p class="text-muted-foreground text-xs">zVerticalAlign="{{ align }}"</p>
              <z-chart
                zType="bar"
                [zConfig]="chartConfig"
                [zData]="chartData"
                [zSeries]="series"
                zXAxisKey="month"
                [zXAxisFormatter]="shortMonth"
                class="h-[220px] w-full"
              >
                <z-chart-legend [zVerticalAlign]="align" />
              </z-chart>
            </div>
          }
        </div>
      </z-card-content>
    </z-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartLegendComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series = ['desktop', 'mobile'];

  protected readonly aligns: ZardChartLegendAlignVariants[] = ['top', 'bottom'];

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

accessibility

zAccessibility (on by default) sets role="img" and a generated aria-label on the chart surface and turns on ECharts' own aria description. Turn it off only if an accessible summary is provided elsewhere.
AccessibilityzAccessibility puts an ARIA role and a generated label on the canvas

role="img" aria-label="bar chart of Desktop, Mobile"

import { ChangeDetectionStrategy, Component, signal } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';
import { ZardSwitchComponent } from '@/shared/components/switch/switch.component';

@Component({
  selector: 'z-demo-chart-accessibility',
  imports: [ZardCardImports, ZardChartImports, ZardSwitchComponent],
  template: `
    <z-card class="w-full">
      <z-card-header class="flex flex-row items-center justify-between gap-4">
        <div>
          <z-card-title zTitle="Accessibility" />
          <z-card-description zDescription="zAccessibility puts an ARIA role and a generated label on the canvas" />
        </div>
        <z-switch zId="chart-accessibility" [(zChecked)]="accessible">zAccessibility</z-switch>
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="bar"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zXAxisKey="month"
          [zXAxisFormatter]="shortMonth"
          [zAccessibility]="accessible()"
          class="h-[220px] w-full"
        />
        <p class="text-muted-foreground mt-3 font-mono text-xs">
          {{ accessible() ? 'role="img" aria-label="bar chart of Desktop, Mobile"' : 'role and aria-label removed' }}
        </p>
      </z-card-content>
    </z-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartAccessibilityComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series = ['desktop', 'mobile'];

  protected readonly accessible = signal(true);

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

opt in features

ECharts features Recharts has no counterpart for are opt-in, so the default chart stays visually identical to shadcn/ui.
ECharts Extras - Data ZoomOpt-in ECharts features Recharts has no counterpart for
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig, ZardChartSeries } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-echarts-datazoom',
  imports: [ZardCardImports, ZardChartImports],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="ECharts Extras - Data Zoom" />
        <z-card-description zDescription="Opt-in ECharts features Recharts has no counterpart for" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="line"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zXAxisKey="date"
          [zXAxisFormatter]="shortDate"
          zDataZoom
          zToolbox
          class="w-full"
        >
          <z-chart-tooltip zIndicator="dot" />
        </z-chart>
      </z-card-content>
    </z-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartEchartsDatazoomComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { date: '2024-06-01', desktop: 178, mobile: 200 },
    { date: '2024-06-02', desktop: 470, mobile: 410 },
    { date: '2024-06-03', desktop: 103, mobile: 160 },
    { date: '2024-06-04', desktop: 439, mobile: 380 },
    { date: '2024-06-05', desktop: 88, mobile: 140 },
    { date: '2024-06-06', desktop: 294, mobile: 250 },
    { date: '2024-06-07', desktop: 323, mobile: 370 },
    { date: '2024-06-08', desktop: 385, mobile: 320 },
    { date: '2024-06-09', desktop: 438, mobile: 480 },
    { date: '2024-06-10', desktop: 155, mobile: 200 },
    { date: '2024-06-11', desktop: 92, mobile: 150 },
    { date: '2024-06-12', desktop: 492, mobile: 420 },
    { date: '2024-06-13', desktop: 81, mobile: 130 },
    { date: '2024-06-14', desktop: 426, mobile: 380 },
    { date: '2024-06-15', desktop: 307, mobile: 350 },
    { date: '2024-06-16', desktop: 371, mobile: 310 },
    { date: '2024-06-17', desktop: 475, mobile: 520 },
    { date: '2024-06-18', desktop: 107, mobile: 170 },
    { date: '2024-06-19', desktop: 341, mobile: 290 },
    { date: '2024-06-20', desktop: 408, mobile: 450 },
    { date: '2024-06-21', desktop: 169, mobile: 210 },
    { date: '2024-06-22', desktop: 317, mobile: 270 },
    { date: '2024-06-23', desktop: 480, mobile: 530 },
    { date: '2024-06-24', desktop: 132, mobile: 180 },
    { date: '2024-06-25', desktop: 141, mobile: 190 },
    { date: '2024-06-26', desktop: 434, mobile: 380 },
    { date: '2024-06-27', desktop: 448, mobile: 490 },
    { date: '2024-06-28', desktop: 149, mobile: 200 },
    { date: '2024-06-29', desktop: 103, mobile: 160 },
    { date: '2024-06-30', desktop: 446, mobile: 400 },
  ];

  protected readonly series: ZardChartSeries[] = [
    { dataKey: 'desktop', smooth: true },
    { dataKey: 'mobile', smooth: true },
  ];

  protected readonly shortDate = (value: string) =>
    new Date(`${value}T00:00:00`).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
}

escape hatch

Anything the inputs do not cover is one [zOption] away — it is deep-merged over the option.
escape-hatch.ts
import type { ZardChartOptionOverride } from '@/shared/components/chart/chart.types';

// `[zOption]` is deep-merged over the generated option and always wins, so any ECharts
// feature is one property away. Arrays merge index by index: the object below patches
// the first series instead of replacing the whole list.
export const override: ZardChartOptionOverride = {
  series: [{ label: { position: 'insideLeft', color: '#fff', formatter: '{b}' } }],
  xAxis: { axisLabel: { rotate: 45 } },
};
Copy

limitations

Where ECharts and Recharts disagree, the chart delivers the closest equivalent. These are the differences worth knowing about.
  • Curve interpolation — Recharts distinguishes natural, monotone and basis; ECharts has a single smooth flag, so all three map to it. Pass a number between 0 and 1 to a series' smooth for finer control.
  • Stack normalisation — ECharts has none, so zStackOffset="expand" normalises the rows to 0-1 before they reach it and clamps the value axis. Format the ticks with [zYAxisFormatter].
  • Tick spacing — Recharts drops ticks whose gap falls below a pixel threshold. The chart sets axisLabel.hideOverlap instead: labels stop colliding, but the threshold is not tunable.
  • Legend — the ECharts legend cannot reproduce the shadcn markup, so z-chart-legend renders real HTML. The native legend stays registered but hidden, because it is what toggles a series.
  • Centre text and radial labels — Recharts nests SVG inside the chart for both. Here they are drawn as graphic text, so zCenterValue and zCenterLabel are plain strings, and zRadialLabel lays a ring name out one glyph at a time.
  • Rounded stacked bars — only the outermost bar of a stack is rounded, matching Recharts. On negative bars ECharts still rounds the top corners rather than the outward end.
  • Server-side rendering — the server paints a static SVG and the browser swaps in the live chart on hydration. It cannot read CSS variables, so the SVG uses the light palette; set [zSsrWidth] and [zSsrHeight] to match your layout.

bar multiple

Pass more than one data key to zSeries to draw them side by side.
Bar Chart - MultipleJanuary - June 2024
Trending up by 5.2% this month
Showing total visitors for the last 6 months
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrendingUp } from '@ng-icons/lucide';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-bar-multiple',
  imports: [ZardCardImports, ZardChartImports, NgIcon],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Bar Chart - Multiple" />
        <z-card-description zDescription="January - June 2024" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="bar"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zXAxisKey="month"
          [zXAxisFormatter]="shortMonth"
          class="w-full"
        >
          <z-chart-tooltip zIndicator="dashed" />
        </z-chart>
      </z-card-content>
      <z-card-footer class="flex-col items-start gap-2 bg-transparent px-4 pt-0 pb-4 text-sm">
        <div class="flex items-center gap-2 leading-none font-medium">
          Trending up by 5.2% this month
          <ng-icon name="lucideTrendingUp" class="size-4" />
        </div>
        <div class="text-muted-foreground leading-none">Showing total visitors for the last 6 months</div>
      </z-card-footer>
    </z-card>
  `,
  providers: [provideIcons({ lucideTrendingUp })],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartBarMultipleComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series = ['desktop', 'mobile'];

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

bar interactive

Series are plain inputs, so a signal is all it takes to make the chart interactive.
Bar Chart - InteractiveShowing total visitors for the last 3 months
import { ChangeDetectionStrategy, Component, computed, signal } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig, ZardChartSeries } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-bar-interactive',
  imports: [ZardCardImports, ZardChartImports],
  template: `
    <z-card class="w-full py-0">
      <z-card-header class="flex flex-col items-stretch border-b p-0! sm:flex-row">
        <div class="flex flex-1 flex-col justify-center gap-1 px-6 pt-4 pb-3 sm:py-0!">
          <z-card-title zTitle="Bar Chart - Interactive" />
          <z-card-description zDescription="Showing total visitors for the last 3 months" />
        </div>
        <div class="flex">
          @for (option of options; track option.key) {
            <button
              type="button"
              [attr.data-active]="active() === option.key"
              [attr.aria-pressed]="active() === option.key"
              class="data-[active=true]:bg-muted/50 relative z-30 flex flex-1 flex-col justify-center gap-1 border-t px-6 py-4 text-left even:border-l sm:border-t-0 sm:border-l sm:px-8 sm:py-6"
              (click)="select(option.key)"
            >
              <span class="text-muted-foreground text-xs">{{ option.label }}</span>
              <span class="text-lg leading-none font-bold sm:text-3xl">{{ totals()[option.key] }}</span>
            </button>
          }
        </div>
      </z-card-header>
      <z-card-content class="px-2 sm:p-6">
        <z-chart
          zType="bar"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series()"
          zXAxisKey="date"
          [zXAxisFormatter]="shortDate"
          class="aspect-auto h-[250px] w-full"
        >
          <z-chart-tooltip zIndicator="dot" zNameKey="views" class="w-[150px]" [zLabelFormatter]="longDate" zCursor />
        </z-chart>
      </z-card-content>
    </z-card>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartBarInteractiveComponent {
  protected readonly chartConfig: ZardChartConfig = {
    views: { label: 'Page Views' },
    desktop: { label: 'Desktop', color: 'var(--chart-2)' },
    mobile: { label: 'Mobile', color: 'var(--chart-1)' },
  };

  protected readonly chartData = [
    { date: '2024-04-01', desktop: 222, mobile: 150 },
    { date: '2024-04-02', desktop: 97, mobile: 180 },
    { date: '2024-04-03', desktop: 167, mobile: 120 },
    { date: '2024-04-04', desktop: 242, mobile: 260 },
    { date: '2024-04-05', desktop: 373, mobile: 290 },
    { date: '2024-04-06', desktop: 301, mobile: 340 },
    { date: '2024-04-07', desktop: 245, mobile: 180 },
    { date: '2024-04-08', desktop: 409, mobile: 320 },
    { date: '2024-04-09', desktop: 59, mobile: 110 },
    { date: '2024-04-10', desktop: 261, mobile: 190 },
    { date: '2024-04-11', desktop: 327, mobile: 350 },
    { date: '2024-04-12', desktop: 292, mobile: 210 },
    { date: '2024-04-13', desktop: 342, mobile: 380 },
    { date: '2024-04-14', desktop: 137, mobile: 220 },
    { date: '2024-04-15', desktop: 120, mobile: 170 },
    { date: '2024-04-16', desktop: 138, mobile: 190 },
    { date: '2024-04-17', desktop: 446, mobile: 360 },
    { date: '2024-04-18', desktop: 364, mobile: 410 },
    { date: '2024-04-19', desktop: 243, mobile: 180 },
    { date: '2024-04-20', desktop: 89, mobile: 150 },
    { date: '2024-04-21', desktop: 137, mobile: 200 },
    { date: '2024-04-22', desktop: 224, mobile: 170 },
    { date: '2024-04-23', desktop: 138, mobile: 230 },
    { date: '2024-04-24', desktop: 387, mobile: 290 },
    { date: '2024-04-25', desktop: 215, mobile: 250 },
    { date: '2024-04-26', desktop: 75, mobile: 130 },
    { date: '2024-04-27', desktop: 383, mobile: 420 },
    { date: '2024-04-28', desktop: 122, mobile: 180 },
    { date: '2024-04-29', desktop: 315, mobile: 240 },
    { date: '2024-04-30', desktop: 454, mobile: 380 },
    { date: '2024-05-01', desktop: 165, mobile: 220 },
    { date: '2024-05-02', desktop: 293, mobile: 310 },
    { date: '2024-05-03', desktop: 247, mobile: 190 },
    { date: '2024-05-04', desktop: 385, mobile: 420 },
    { date: '2024-05-05', desktop: 481, mobile: 390 },
    { date: '2024-05-06', desktop: 498, mobile: 520 },
    { date: '2024-05-07', desktop: 388, mobile: 300 },
    { date: '2024-05-08', desktop: 149, mobile: 210 },
    { date: '2024-05-09', desktop: 227, mobile: 180 },
    { date: '2024-05-10', desktop: 293, mobile: 330 },
    { date: '2024-05-11', desktop: 335, mobile: 270 },
    { date: '2024-05-12', desktop: 197, mobile: 240 },
    { date: '2024-05-13', desktop: 197, mobile: 160 },
    { date: '2024-05-14', desktop: 448, mobile: 490 },
    { date: '2024-05-15', desktop: 473, mobile: 380 },
    { date: '2024-05-16', desktop: 338, mobile: 400 },
    { date: '2024-05-17', desktop: 499, mobile: 420 },
    { date: '2024-05-18', desktop: 315, mobile: 350 },
    { date: '2024-05-19', desktop: 235, mobile: 180 },
    { date: '2024-05-20', desktop: 177, mobile: 230 },
    { date: '2024-05-21', desktop: 82, mobile: 140 },
    { date: '2024-05-22', desktop: 81, mobile: 120 },
    { date: '2024-05-23', desktop: 252, mobile: 290 },
    { date: '2024-05-24', desktop: 294, mobile: 220 },
    { date: '2024-05-25', desktop: 201, mobile: 250 },
    { date: '2024-05-26', desktop: 213, mobile: 170 },
    { date: '2024-05-27', desktop: 420, mobile: 460 },
    { date: '2024-05-28', desktop: 233, mobile: 190 },
    { date: '2024-05-29', desktop: 78, mobile: 130 },
    { date: '2024-05-30', desktop: 340, mobile: 280 },
    { date: '2024-05-31', desktop: 178, mobile: 230 },
    { date: '2024-06-01', desktop: 178, mobile: 200 },
    { date: '2024-06-02', desktop: 470, mobile: 410 },
    { date: '2024-06-03', desktop: 103, mobile: 160 },
    { date: '2024-06-04', desktop: 439, mobile: 380 },
    { date: '2024-06-05', desktop: 88, mobile: 140 },
    { date: '2024-06-06', desktop: 294, mobile: 250 },
    { date: '2024-06-07', desktop: 323, mobile: 370 },
    { date: '2024-06-08', desktop: 385, mobile: 320 },
    { date: '2024-06-09', desktop: 438, mobile: 480 },
    { date: '2024-06-10', desktop: 155, mobile: 200 },
    { date: '2024-06-11', desktop: 92, mobile: 150 },
    { date: '2024-06-12', desktop: 492, mobile: 420 },
    { date: '2024-06-13', desktop: 81, mobile: 130 },
    { date: '2024-06-14', desktop: 426, mobile: 380 },
    { date: '2024-06-15', desktop: 307, mobile: 350 },
    { date: '2024-06-16', desktop: 371, mobile: 310 },
    { date: '2024-06-17', desktop: 475, mobile: 520 },
    { date: '2024-06-18', desktop: 107, mobile: 170 },
    { date: '2024-06-19', desktop: 341, mobile: 290 },
    { date: '2024-06-20', desktop: 408, mobile: 450 },
    { date: '2024-06-21', desktop: 169, mobile: 210 },
    { date: '2024-06-22', desktop: 317, mobile: 270 },
    { date: '2024-06-23', desktop: 480, mobile: 530 },
    { date: '2024-06-24', desktop: 132, mobile: 180 },
    { date: '2024-06-25', desktop: 141, mobile: 190 },
    { date: '2024-06-26', desktop: 434, mobile: 380 },
    { date: '2024-06-27', desktop: 448, mobile: 490 },
    { date: '2024-06-28', desktop: 149, mobile: 200 },
    { date: '2024-06-29', desktop: 103, mobile: 160 },
    { date: '2024-06-30', desktop: 446, mobile: 400 },
  ];

  protected readonly options = [
    { key: 'desktop', label: 'Desktop' },
    { key: 'mobile', label: 'Mobile' },
  ];

  protected readonly active = signal('desktop');

  protected readonly totals = computed<Record<string, string>>(() => ({
    desktop: this.sum('desktop'),
    mobile: this.sum('mobile'),
  }));

  protected readonly series = computed<ZardChartSeries[]>(() => [{ dataKey: this.active() }]);

  protected readonly shortDate = (value: string) =>
    new Date(`${value}T00:00:00`).toLocaleDateString('en-US', { month: 'short', day: 'numeric' });

  protected readonly longDate = (value: string) =>
    new Date(`${value}T00:00:00`).toLocaleDateString('en-US', { month: 'short', day: 'numeric', year: 'numeric' });

  protected select(key: string): void {
    this.active.set(key);
  }

  private sum(key: 'desktop' | 'mobile'): string {
    return this.chartData.reduce((total, row) => total + row[key], 0).toLocaleString();
  }
}

area gradient

Use zGradient to fill the area under a zType="area" series with a vertical gradient.
Area Chart - GradientShowing total visitors for the last 6 months
Trending up by 5.2% this month
January - June 2024
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrendingUp } from '@ng-icons/lucide';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig, ZardChartSeries } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-area-gradient',
  imports: [ZardCardImports, ZardChartImports, NgIcon],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Area Chart - Gradient" />
        <z-card-description zDescription="Showing total visitors for the last 6 months" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="area"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zXAxisKey="month"
          [zXAxisFormatter]="shortMonth"
          zStacked
          zGradient
          class="w-full"
        >
          <z-chart-tooltip zIndicator="dot" />
        </z-chart>
      </z-card-content>
      <z-card-footer class="flex-col items-start gap-2 bg-transparent px-4 pt-0 pb-4 text-sm">
        <div class="flex items-center gap-2 leading-none font-medium">
          Trending up by 5.2% this month
          <ng-icon name="lucideTrendingUp" class="size-4" />
        </div>
        <div class="text-muted-foreground leading-none">January - June 2024</div>
      </z-card-footer>
    </z-card>
  `,
  providers: [provideIcons({ lucideTrendingUp })],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartAreaGradientComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
    mobile: { label: 'Mobile', color: 'var(--chart-2)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series: ZardChartSeries[] = [
    { dataKey: 'mobile', smooth: true },
    { dataKey: 'desktop', smooth: true },
  ];

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

line default

The plainest line chart: one series, one axis.
Line ChartJanuary - June 2024
Trending up by 5.2% this month
Showing total visitors for the last 6 months
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrendingUp } from '@ng-icons/lucide';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig, ZardChartSeries } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-line-default',
  imports: [ZardCardImports, ZardChartImports, NgIcon],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Line Chart" />
        <z-card-description zDescription="January - June 2024" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="line"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zXAxisKey="month"
          [zXAxisFormatter]="shortMonth"
          class="w-full"
        >
          <z-chart-tooltip zIndicator="line" />
        </z-chart>
      </z-card-content>
      <z-card-footer class="flex-col items-start gap-2 bg-transparent px-4 pt-0 pb-4 text-sm">
        <div class="flex items-center gap-2 leading-none font-medium">
          Trending up by 5.2% this month
          <ng-icon name="lucideTrendingUp" class="size-4" />
        </div>
        <div class="text-muted-foreground leading-none">Showing total visitors for the last 6 months</div>
      </z-card-footer>
    </z-card>
  `,
  providers: [provideIcons({ lucideTrendingUp })],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartLineDefaultComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series: ZardChartSeries[] = [{ dataKey: 'desktop', smooth: true }];

  protected readonly shortMonth = (value: string) => value.slice(0, 3);
}

pie donut text

Use zInnerRadius for the donut and zCenterValue / zCenterLabel for the text in the middle.
Pie Chart - Donut with TextJanuary - June 2024
Trending up by 5.2% this month
Showing total visitors for the last 6 months
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrendingUp } from '@ng-icons/lucide';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-pie-donut-text',
  imports: [ZardCardImports, ZardChartImports, NgIcon],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Pie Chart - Donut with Text" />
        <z-card-description zDescription="January - June 2024" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="pie"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zNameKey="browser"
          zInnerRadius="48%"
          zCenterValue="925"
          zCenterLabel="Visitors"
          class="mx-auto aspect-square h-[250px]"
        >
          <z-chart-tooltip zTrigger="item" zIndicator="dot" zHideLabel />
        </z-chart>
      </z-card-content>
      <z-card-footer class="flex-col gap-2 bg-transparent px-4 pt-0 pb-4 text-sm">
        <div class="flex items-center gap-2 leading-none font-medium">
          Trending up by 5.2% this month
          <ng-icon name="lucideTrendingUp" class="size-4" />
        </div>
        <div class="text-muted-foreground leading-none">Showing total visitors for the last 6 months</div>
      </z-card-footer>
    </z-card>
  `,
  providers: [provideIcons({ lucideTrendingUp })],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartPieDonutTextComponent {
  protected readonly chartConfig: ZardChartConfig = {
    visitors: { label: 'Visitors' },
    chrome: { label: 'Chrome', color: 'var(--chart-1)' },
    safari: { label: 'Safari', color: 'var(--chart-2)' },
    firefox: { label: 'Firefox', color: 'var(--chart-3)' },
    edge: { label: 'Edge', color: 'var(--chart-4)' },
    other: { label: 'Other', color: 'var(--chart-5)' },
  };

  protected readonly chartData = [
    { browser: 'chrome', visitors: 275 },
    { browser: 'safari', visitors: 200 },
    { browser: 'firefox', visitors: 187 },
    { browser: 'edge', visitors: 173 },
    { browser: 'other', visitors: 90 },
  ];

  protected readonly series = ['visitors'];
}

radar default

A radar chart with two series over the same set of indicators.
Radar ChartShowing total visitors for the last 6 months
Trending up by 5.2% this month
January - June 2024
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrendingUp } from '@ng-icons/lucide';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-radar-default',
  imports: [ZardCardImports, ZardChartImports, NgIcon],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Radar Chart" />
        <z-card-description zDescription="Showing total visitors for the last 6 months" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="radar"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zNameKey="month"
          class="mx-auto aspect-square h-[250px]"
        >
          <z-chart-tooltip zTrigger="item" zIndicator="dot" zHideLabel />
        </z-chart>
      </z-card-content>
      <z-card-footer class="flex-col gap-2 bg-transparent px-4 pt-0 pb-4 text-sm">
        <div class="flex items-center gap-2 leading-none font-medium">
          Trending up by 5.2% this month
          <ng-icon name="lucideTrendingUp" class="size-4" />
        </div>
        <div class="text-muted-foreground leading-none">January - June 2024</div>
      </z-card-footer>
    </z-card>
  `,
  providers: [provideIcons({ lucideTrendingUp })],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartRadarDefaultComponent {
  protected readonly chartConfig: ZardChartConfig = {
    desktop: { label: 'Desktop', color: 'var(--chart-1)' },
  };

  protected readonly chartData = [
    { month: 'January', desktop: 186, mobile: 80 },
    { month: 'February', desktop: 305, mobile: 200 },
    { month: 'March', desktop: 237, mobile: 120 },
    { month: 'April', desktop: 73, mobile: 190 },
    { month: 'May', desktop: 209, mobile: 130 },
    { month: 'June', desktop: 214, mobile: 140 },
  ];

  protected readonly series = ['desktop'];
}

radial simple

A single radial bar, the simplest zRadialVariant="bar" chart.
Radial ChartJanuary - June 2024
Trending up by 5.2% this month
Showing total visitors for the last 6 months
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideTrendingUp } from '@ng-icons/lucide';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardChartImports } from '@/shared/components/chart/chart.imports';
import type { ZardChartConfig } from '@/shared/components/chart/chart.types';

@Component({
  selector: 'z-demo-chart-radial-simple',
  imports: [ZardCardImports, ZardChartImports, NgIcon],
  template: `
    <z-card class="w-full">
      <z-card-header>
        <z-card-title zTitle="Radial Chart" />
        <z-card-description zDescription="January - June 2024" />
      </z-card-header>
      <z-card-content>
        <z-chart
          zType="radial"
          [zConfig]="chartConfig"
          [zData]="chartData"
          [zSeries]="series"
          zNameKey="browser"
          zInnerRadius="24%"
          zOuterRadius="88%"
          class="mx-auto aspect-square h-[250px]"
        >
          <z-chart-tooltip zTrigger="item" zIndicator="dot" zHideLabel />
        </z-chart>
      </z-card-content>
      <z-card-footer class="flex-col gap-2 bg-transparent px-4 pt-0 pb-4 text-sm">
        <div class="flex items-center gap-2 leading-none font-medium">
          Trending up by 5.2% this month
          <ng-icon name="lucideTrendingUp" class="size-4" />
        </div>
        <div class="text-muted-foreground leading-none">Showing total visitors for the last 6 months</div>
      </z-card-footer>
    </z-card>
  `,
  providers: [provideIcons({ lucideTrendingUp })],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoChartRadialSimpleComponent {
  protected readonly chartConfig: ZardChartConfig = {
    visitors: { label: 'Visitors' },
    chrome: { label: 'Chrome', color: 'var(--chart-1)' },
    safari: { label: 'Safari', color: 'var(--chart-2)' },
    firefox: { label: 'Firefox', color: 'var(--chart-3)' },
    edge: { label: 'Edge', color: 'var(--chart-4)' },
    other: { label: 'Other', color: 'var(--chart-5)' },
  };

  protected readonly chartData = [
    { browser: 'chrome', visitors: 275 },
    { browser: 'safari', visitors: 200 },
    { browser: 'firefox', visitors: 187 },
    { browser: 'edge', visitors: 173 },
    { browser: 'other', visitors: 90 },
  ];

  protected readonly series = ['visitors'];
}

API Reference

z-chartComponent

A chart container built on Apache ECharts through ngx-echarts.

PropertyDescriptionTypeDefault
[class] Additional CSS classes ClassValue ''
[zConfig] Labels, colors and icons per data key ZardChartConfig {}
[zData] The rows to plot Record<string, unknown>[] []
[zType] Default type of every series 'area' | 'bar' | 'line' | 'pie' | 'radar' | 'radial' 'bar'
[zSeries] Series to render, either as data keys or fully described string[] | ZardChartSeries[] []
[zXAxisKey] Key used for the category axis string -
[zNameKey] Key naming each slice or segment on pie, radar and radial charts. Falls back to zXAxisKey string -
[zStacked] Stacks every series together boolean false
[zStackOffset] 'expand' normalises the stack to 0-1, the Recharts stackOffset equivalent 'none' | 'expand' 'none'
[zHorizontal] Swaps the category and value axes boolean false
[zGrid] Grid lines to draw, by direction. Equivalent to CartesianGrid boolean | 'horizontal' | 'vertical' 'horizontal'
[zXAxis] Shows the category axis labels, whichever side `zHorizontal` puts them on boolean true
[zYAxis] Shows the value axis labels, whichever side `zHorizontal` puts them on boolean false
[zXAxisFormatter] Formats every category tick. Equivalent to tickFormatter (value: string) => string -
[zYAxisFormatter] Formats every value tick (value: number) => string -
[zInnerRadius] Inner radius of pie, donut and radial charts string | number -
[zOuterRadius] Outer radius of pie, donut, radar and radial charts string | number -
[zRadialVariant] How a radial chart is drawn: polar bars or a gauge 'bar' | 'gauge' 'bar'
[zTrack] Radial only: the muted ring drawn behind each bar. Equivalent to RadialBar background boolean true
[zRadialLabel] Radial only: writes each category's name along its own ring. Equivalent to LabelList boolean false
[zRadarRadialLines] Radar only: the spokes running from the centre to each indicator boolean true
[zRadarShape] Shape of the radar grid. Equivalent to PolarGrid gridType 'polygon' | 'circle' 'polygon'
[zStartAngle] Start angle of pie and radial charts number -
[zEndAngle] End angle of pie and radial charts number -
[zPadAngle] Gap between pie slices, in degrees number 0
[zGradient] Fills area series with a vertical gradient instead of a flat tint boolean false
[zLabel] Prints the value on every data point. Equivalent to LabelList boolean false
[zCenterValue] Big text in the middle of a donut or radial chart string -
[zCenterLabel] Caption under zCenterValue string -
[zAccessibility] Enables ECharts' aria description plus role and aria-label on the canvas boolean true
[zAnimation] Animates the chart on data changes boolean true
[zLazyRender] Waits for the chart to scroll into view before drawing it, so the entry animation plays where it can be seen boolean true
[zDataZoom] ECharts extra, opt-in: adds inside and slider zooming boolean false
[zBrush] ECharts extra, opt-in: adds the brush selection toolbox boolean false
[zToolbox] ECharts extra, opt-in: adds the zoom, restore and export toolbox boolean false
[zRenderer] ECharts renderer 'canvas' | 'svg' 'canvas'
[zSsrWidth] Width, in pixels, of the SVG rendered on the server number 600
[zSsrHeight] Height, in pixels, of the SVG rendered on the server number 300
[zOption] Escape hatch deep-merged over the generated option, always winning EChartsOption {}
(zChartInit) Emits the ECharts instance once created EChartsType -
(zChartClick) Emitted when a data item is clicked ECElementEvent -
(zLegendSelectChanged) Emitted when ECharts' legend selection changes unknown -
(zDataZoomChange) Emitted while the data zoom moves unknown -

z-chart-tooltipComponent

Declares the tooltip the parent chart should build. Renders no DOM of its own.

PropertyDescriptionTypeDefault
[class] Additional CSS classes on the tooltip container ClassValue ''
[zIndicator] Shape of the color indicator on each row 'dot' | 'line' | 'dashed' 'dot'
[zCursor] Draws the axis pointer under the tooltip: a line on curves, a band on bars boolean false
[zDefaultIndex] Opens the tooltip on this data index as soon as the chart draws number -
[zHideLabel] Hides the tooltip heading boolean false
[zHideIndicator] Hides the color indicator boolean false
[zLabelKey] Config key used for the heading string -
[zNameKey] Config key used for each row name string -
[zLabelFormatter] Formats the heading (value: string) => string -
[zValueFormatter] Formats every value (value: number, name: string) => string -
[zTrigger] 'axis' groups every series of a category, 'item' shows the hovered item only 'axis' | 'item' 'axis'
[zLabelClass] Additional CSS classes on the heading ClassValue ''

z-chart-legendComponent

Renders the shadcn legend markup below (or above) the chart and toggles series on click.

PropertyDescriptionTypeDefault
[class] Additional CSS classes ClassValue ''
[zVerticalAlign] Places the legend above or below the chart 'top' | 'bottom' 'bottom'
github iconwhatsapp icondiscord iconX icon

Made with ❤ in Brazil. Open source and available on GitHub .