Getting StartedComponentsDesign TokensThemingTheme SynthesizerFrameworksAccessibilityUtilitiesServer RenderingBrowser SupportContributingChangelog App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip
ARC UI ARC Radiant Components
v3.2 Docs Components Tokens Synthesizer
Getting StartedFrameworksServer Rendering Design TokensThemingTheme SynthesizerTypographyUtilities All ComponentsAccessibilityBrowser SupportChangelogContributingStats App ShellAspect GridAuth ShellCenterClusterContainerDashboard GridDockFloat BarInsetMasonryPage HeaderPage LayoutResizableResponsive SwitcherSectionSettings LayoutSplit PaneStatus BarStickyToolbar Anchor NavBottom NavBreadcrumbBreadcrumb MenuCommand BarDrawerFooterLinkMenubarNavigation MenuPage IndicatorPaginationRailScroll IndicatorScroll SpyScroll To TopSidebarSkip LinkSpeed DialStepper NavTabsTop BarTree View AccordionAspect RatioAvatarAvatar GroupCalloutCardCarouselCollapsibleColor SwatchCTA BannerDividerEmpty StateFeature CardIconImageImage CompareImage HotspotsInfinite ScrollLightboxMarqueeQR CodeScroll AreaSeparatorSkeletonSpinnerStackVideoVirtual List Activity HeatmapAnimated NumberBadgeChartClockComparisonCountdown TimerData GridData TableDescription ListDiffEvent CalendarGaugeJSON TreeKanbanKey ValueLevel MeterListMeterSparklineStatStepperTableTagTimelineUptimeValue CardWaveform BlockquoteCode BlockGradient TextHighlightKbdKeyboard MapMarkdownNumber FormatProseTerminalTextTime AgoTruncateTypewriter ButtonButton GroupCalendarCheckboxChipColor PickerComboboxCopy ButtonDate PickerDate Range PickerFieldsetFile UploadFormHotkeyIcon ButtonImage CropperInline EditInputInput GroupKnobLabelMasked InputMulti SelectNumber InputOTP InputPassword InputPin InputRadio GroupRange SliderRatingSearchSegmented ControlSelectSignature PadSliderSortable ListSwitch GroupTag InputTextareaTheme ToggleTime PickerToggleTransfer ListTree Select AlertAnnouncementBannerCommand PaletteConfirmConnection StatusContext MenuConversationDialogDropdown MenuGuided TourHover CardInline MessageLoading OverlayModalNotification PanelPopoverProgressProgress ToastSheetSnackbarSpotlightToastTooltip

Chart

An SVG chart component for dashboards with line, area, bar, and donut types. Data-driven from a series array, with automatic nice-tick scales, a legend, hover crosshair and tooltips, and a visually-hidden data table for assistive technology.

Components Chart
data interactive beta
<arc-chart>

Overview

Chart renders line, area, grouped/stacked bar, and donut charts from plain JavaScript data — no external charting library. Pass a `series` array of `{ label, data }` objects and a `labels` array of x-axis categories, and the component computes a nice 1/2/5-step y scale, recessive horizontal gridlines, abbreviated axis numbers (1.2k, 3.4M), and thin marks in the fixed ARC chart palette. Series colors are assigned in fixed order from `--chart-1` through `--chart-6` and are never cycled. When more than six series are provided, the extras are summed into an "Other" series and flagged in the legend, so identity stays readable. The legend renders automatically for two or more series and is omitted for a single series. A hover layer ships by default: line and area charts show a vertical crosshair with a tooltip listing every series value at the hovered category, while bar and donut charts show per-mark tooltips. Hit targets are invisible full-height columns per category, so users never have to hit a 2px line. Clicking a mark emits `arc-mark-click` with the series index, category index, and value. For assistive technology, the chart container carries a generated `role="img"` summary and a visually-hidden `<table>` exposes the real values.

Guidelines

When to use

  • Keep charts to 6 or fewer series — beyond that, pre-aggregate or split into small multiples
  • Use type="area" for a single dominant series and type="line" when comparing trends
  • Use stacked only when the total is meaningful; use grouped bars to compare series per category
  • Set value-format="percent" with fractional data (0.24 renders as 24%)
  • Provide a label for every series — labels drive the legend, tooltip, and data table
  • Listen to arc-mark-click to drive drill-down navigation or detail panels

When not to use

  • Do not plot two measures of different scale on one chart — there is one y-axis, never dual axes
  • Do not use donut charts for more than ~6 segments or for precise comparisons — use bars instead
  • Do not hide the legend on multi-series charts unless the series are directly labeled nearby
  • Do not encode meaning in custom mark colors — the fixed palette keeps series identity consistent
  • Do not use hide-axis on charts where readers need to look up values — it is for compact trend panels
  • Do not feed stacked bars negative values; stacking assumes non-negative data

Features

  • Four chart types: line, area, grouped bar, stacked bar, and donut
  • Fixed-order series colors `--chart-1` through `--chart-6`, never cycled
  • More than 6 series automatically fold into a summed "Other" series
  • Nice-tick y scale (1/2/5 steps) with abbreviated axis numbers (1.2k, 3.4M)
  • Single y-axis with recessive 1px horizontal gridlines only
  • Hover crosshair + all-series tooltip on line/area; per-mark tooltips on bar/donut
  • Full-plot-height invisible hover columns — no pixel-hunting thin marks
  • `arc-mark-click` event with seriesIndex, index, and value
  • Intl.NumberFormat value formatting: number, percent, or currency
  • Legend with 8px color chips, rendered automatically for 2+ series
  • `role="img"` summary label plus a visually-hidden data table for AT users
  • ResizeObserver-driven responsive width; respects `prefers-reduced-motion`
  • Styleable via ::part(chart), ::part(legend), ::part(tooltip), ::part(axis)

Preview

Usage

This component requires JavaScript. No pure HTML/CSS version is available — use the Web Component directly or a framework wrapper.

<arc-chart id="revenue-chart" type="bar" stacked value-format="currency" height="280"></arc-chart>

<script type="module">
  import '@arclux/arc-ui/chart';

  const chart = document.querySelector('#revenue-chart');
  chart.labels = ['Q1', 'Q2', 'Q3', 'Q4'];
  chart.series = [
    { label: 'Subscriptions', data: [42000, 48000, 51000, 62000] },
    { label: 'Services', data: [18000, 16500, 21000, 24000] },
    { label: 'Licensing', data: [9000, 11000, 10500, 14000] }
  ];

  chart.addEventListener('arc-mark-click', (e) => {
    const { seriesIndex, index, value } = e.detail;
    console.log('clicked', seriesIndex, index, value);
  });
</script>
import { Chart } from '@arclux/arc-ui-react';

const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
const series = [
  { label: 'Sessions', data: [1200, 1850, 1640, 2100, 2400, 1980] },
  { label: 'Signups', data: [180, 240, 210, 320, 380, 300] }
];

export function TrafficChart() {
  return (
    <Chart
      type="line"
      labels={labels}
      series={series}
      height={280}
      onArcMarkClick={(e) => console.log(e.detail)}
    />
  );
}
<script setup>
import { Chart } from '@arclux/arc-ui-vue';

const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
const series = [
  { label: 'Sessions', data: [1200, 1850, 1640, 2100, 2400, 1980] },
  { label: 'Signups', data: [180, 240, 210, 320, 380, 300] }
];
</script>

<template>
  <Chart type="line" :labels="labels" :series="series" :height="280" />
</template>
<script>
  import { Chart } from '@arclux/arc-ui-svelte';

  const labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
  const series = [
    { label: 'Sessions', data: [1200, 1850, 1640, 2100, 2400, 1980] },
    { label: 'Signups', data: [180, 240, 210, 320, 380, 300] }
  ];
</script>

<Chart type="line" {labels} {series} height={280} on:arc-mark-click={(e) => console.log(e.detail)} />
import { Component } from '@angular/core';
import { Chart } from '@arclux/arc-ui-angular';

@Component({
  imports: [Chart],
  template: `
    <arc-chart
      type="line"
      [labels]="labels"
      [series]="series"
      [height]="280"
      (arcMarkClick)="onMarkClick($event)"
    ></arc-chart>
  `,
})
export class TrafficChartComponent {
  labels = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'];
  series = [
    { label: 'Sessions', data: [1200, 1850, 1640, 2100, 2400, 1980] },
    { label: 'Signups', data: [180, 240, 210, 320, 380, 300] }
  ];

  onMarkClick(e: CustomEvent) {
    console.log(e.detail);
  }
}

API

type 'line' | 'area' | 'bar' | 'donut' 'line'
The chart form. Line and area share the x axis across all series; bar renders grouped columns (or stacked with the `stacked` attribute); donut renders one segment per series (or per category when a single series is given).
series Array<{label:string,data:number[]}> []
The data that drives the chart. Each entry is one series; all series share the x axis defined by `labels`. Set via JavaScript property, not an attribute. Colors are assigned in fixed order from --chart-1 to --chart-6; series beyond six are summed into an "Other" series noted in the legend.
labels string[] []
Category labels for the x axis (or donut segment names when a single series is given). Labels that would collide are automatically thinned — every Nth label renders based on available width.
stacked boolean false
Bar type only. Stacks series segments on a shared baseline with 2px surface gaps between segments; only the outermost segment gets the rounded value end. Assumes non-negative data.
hide-legend boolean false
Suppresses the legend. By default the legend renders for two or more series and is omitted for a single series.
hide-axis boolean false
Removes the axis layer — gridlines, y tick labels, and x category labels — for compact trend panels where exact values are read from the tooltip.
height number 260
Chart height in pixels. Width is fluid and tracked with a ResizeObserver.
value-format 'number' | 'percent' | 'currency' 'number'
How values are formatted in tooltips, the axis, and the accessible data table, via Intl.NumberFormat. Percent expects fractional data (0.24 → 24%). Axis numbers are abbreviated (1.2k, 3.4M).
currency string 'USD'
ISO 4217 currency code used when value-format="currency".

Events

arc-mark-click
Fired when a mark (bar, stacked segment, line point column, or donut segment) is clicked. detail: { seriesIndex, index, value }. Indices refer to displayed series after any "Other" folding; a folded donut segment reports seriesIndex -1.

See Also