ComponentsComponents
IconsIcons
GuidesGuides
ExamplesExamples
Getting startedGetting started
ComponentsIconsGuidesExamplesGetting startedComponentsIconsGuidesExamplesGetting started
GitHub repository
GitHub repository
Chart overview
One architecture for data, series, interaction and presentation across every chart component.
The family contains line, area, bar, scatter,
candlestick, gauge, pie and
sparkline. They are separate custom elements, but they inherit the same ChartBase and use the same
normalized frame, series definitions, theme tokens, presenters, state UI, events and update pipeline.
Every example on this page uses Apple fiscal-year data published in the public
SEC Company Facts API or the product mix in
Apple’s 2025 Form 10-K.
Amounts are USD billions. It is a useful common dataset: trends suit Cartesian charts, product mix suits a pie,
and annual values make realtime interpolation easy to see.
Architecture
The shared architecture keeps application code independent from the drawing engine:
data, revision or a dataSource enters the data path.
ChartFrameBuilder normalizes rows, arrays or columns into one typed frame.
c2-chart-series adds labels, colors, axes and formatting without changing the data.
The concrete chart projects that frame through its uPlot or ECharts adapter.
ChartBase owns resize, lazy loading, states, legend, tooltip and semantic events around the canvas.
Engines
The components lazy-load optional peer engines only when first rendered. Line, area, bar and sparkline use
uPlot for a small, fast Cartesian path. Pie, gauge, scatter and candlestick use modular
Apache ECharts for specialized series, labels, visual maps and canvas/SVG renderers.
chart-ready reports the active engine; application code still sees the same chart API.
Charts animate their first draw by default and keep later data updates immediate. ECharts uses its native
shape animation, while uPlot charts use a lightweight plot reveal. Use animation="none" to disable the
entrance animation. Both paths respect the user’s reduced-motion preference.
Install only the engine your selected elements need:
npm install @c2n/chart uplot # line, area, bar, sparklinenpm install @c2n/chart echarts # pie, gauge, scatter, candlesticknpm install @c2n/chart uplot echarts # the full family
Data and series
Every chart accepts row objects, number[], columnar [xs, ys…], or an already normalized ChartFrame.
Rows are the readable default; columnar data is the zero-conversion path for large numeric datasets. Declare
series as c2-chart-series children or assign the series property. Children win when both are present.
x-field, x-type, label-field and locale control interpretation and display. A series can add a label,
explicit color, second axis, gap behavior and a property-only format(value) function. With no definitions,
numeric fields are inferred from the first row.
legend="top|bottom|start|end|none" and tooltip="axis|item|none" provide useful built-ins. For product UI,
link independent c2-chart-legend and c2-chart-tooltip elements with for="chart-id". They can live anywhere
in the same document or shadow root and automatically suppress the corresponding built-in presenter.
The linked elements expose renderLegend, renderLegendItem and renderTooltip properties for data-driven Lit
templates. This example uses recognizable finance/product icons, current values, growth, margin, mix and percentage
context rather than repeating the chart labels.
The realtime path is shared and intentionally separate from presentation updates:
updateData(next) replaces a dataset immediately without waiting for Lit.
appendPoint(x, values) writes into spare frame capacity and redraws once.
increment revision after mutating an owned input buffer in place.
dataSource.getWindow() pulls lazy ranges; optional subscribe() pushes points through the append path.
max-points bounds a moving window.
uPlot redraws immediately; it does not invent values between samples. A slow annual feed therefore looks stepped.
The demo interpolates consecutive SEC observations with requestAnimationFrame() and calls updateData on each
frame. That smoothness comes from the feed policy, not a chart-engine limitation. For high-frequency telemetry,
append real samples directly and leave animation off so transitions never overlap.
const source = { async getWindow({ xMin, xMax, maxPoints, signal }) { return { data: await fetchWindow({ xMin, xMax, maxPoints, signal }) } }, subscribe(push) { return marketFeed.subscribe(({ time, revenue, income }) => push(time, [revenue, income])) },}chart.dataSource = source
Events and interaction
Every chart reports chart-ready, chart-error, point-click, point-hover, tooltip-change,
legend-change and series-toggle. Cartesian charts also emit range-change after zooming or brushing.
Point and range events do not bubble, so attach listeners to the chart itself. Use data-chart-ready as the
stable test signal after the first frame is drawn.
Hover a point or toggle a legend item below to see the same semantic event model used by external presenters.
Canvas has no intrinsic size. The host gets width from layout and height from --c2-chart--height (320px by
default, 32px for a sparkline). A ResizeObserver keeps the engine canvas synchronized without resize loops.
lazy-render defers both engine import and first draw until the host enters the viewport.
All elements use the --c2-chart__* namespace. Set the palette, typography, axes, grid, crosshair, legend,
tooltip and state variables once on a container and every chart beneath it inherits them. Canvas marks cannot be
reached with ::part(), so the component resolves CSS variables with getComputedStyle and gives the result to
the engine. Theme changes redraw without replacing data.
loading, error and empty data replace the plot with a consistent state layer. Each state has a named slot,
and empty-message changes the default copy. The shared actions slot places controls above the plot; legend
and tooltip slots replace their built-ins. Series definitions occupy the default slot.
Exit
ResetSave to collection
Loading…
Loading filingReading SEC Company Facts…Loading filingReading SEC Company Facts…
No data
No comparable periodChoose another fiscal range.No comparable periodChoose another fiscal range.
The filing could not be loaded
SEC request failedKeep the last valid frame and retry.SEC request failedKeep the last valid frame and retry.
Loading · empty · errorCustomized
<style> .state-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); width: 100%; gap: 12px; } .state-grid c2-line-chart { --c2-chart--height: 170px; } .state-card { display: grid; place-items: center; gap: 5px; text-align: center; } .state-card strong { color: var(--c2-chart--color); }</style><div class="state-grid"> <c2-line-chart loading> <span slot="loading" class="state-card"><strong>Loading filing</strong><small>Reading SEC Company Facts…</small></span> </c2-line-chart> <c2-line-chart data="[]"> <span slot="empty" class="state-card"><strong>No comparable period</strong><small>Choose another fiscal range.</small></span> </c2-line-chart> <c2-line-chart error="The filing could not be loaded"> <span slot="error" class="state-card"><strong>SEC request failed</strong><small>Keep the last valid frame and retry.</small></span> </c2-line-chart></div>
Shared API
Use each component’s API tab for its additions: line curve/points, area fill, bar sizing, pie radii/labels,
and sparkline type/tone. Cartesian charts also share axes, grid, cursor, zoom and y-domain controls through their
uPlot base; pie instead adds ECharts renderer and polar-layout options.
Chart overview
One architecture for data, series, interaction and presentation across every chart component.
The family contains line, area, bar, scatter,
candlestick, gauge, pie and
sparkline. They are separate custom elements, but they inherit the same ChartBase and use the same
normalized frame, series definitions, theme tokens, presenters, state UI, events and update pipeline.
Every example on this page uses Apple fiscal-year data published in the public
SEC Company Facts API or the product mix in
Apple’s 2025 Form 10-K.
Amounts are USD billions. It is a useful common dataset: trends suit Cartesian charts, product mix suits a pie,
and annual values make realtime interpolation easy to see.
Architecture
The shared architecture keeps application code independent from the drawing engine:
data, revision or a dataSource enters the data path.
ChartFrameBuilder normalizes rows, arrays or columns into one typed frame.
c2-chart-series adds labels, colors, axes and formatting without changing the data.
The concrete chart projects that frame through its uPlot or ECharts adapter.
ChartBase owns resize, lazy loading, states, legend, tooltip and semantic events around the canvas.
Engines
The components lazy-load optional peer engines only when first rendered. Line, area, bar and sparkline use
uPlot for a small, fast Cartesian path. Pie, gauge, scatter and candlestick use modular
Apache ECharts for specialized series, labels, visual maps and canvas/SVG renderers.
chart-ready reports the active engine; application code still sees the same chart API.
Charts animate their first draw by default and keep later data updates immediate. ECharts uses its native
shape animation, while uPlot charts use a lightweight plot reveal. Use animation="none" to disable the
entrance animation. Both paths respect the user’s reduced-motion preference.
Install only the engine your selected elements need:
npm install @c2n/chart uplot # line, area, bar, sparklinenpm install @c2n/chart echarts # pie, gauge, scatter, candlesticknpm install @c2n/chart uplot echarts # the full family
Data and series
Every chart accepts row objects, number[], columnar [xs, ys…], or an already normalized ChartFrame.
Rows are the readable default; columnar data is the zero-conversion path for large numeric datasets. Declare
series as c2-chart-series children or assign the series property. Children win when both are present.
x-field, x-type, label-field and locale control interpretation and display. A series can add a label,
explicit color, second axis, gap behavior and a property-only format(value) function. With no definitions,
numeric fields are inferred from the first row.
legend="top|bottom|start|end|none" and tooltip="axis|item|none" provide useful built-ins. For product UI,
link independent c2-chart-legend and c2-chart-tooltip elements with for="chart-id". They can live anywhere
in the same document or shadow root and automatically suppress the corresponding built-in presenter.
The linked elements expose renderLegend, renderLegendItem and renderTooltip properties for data-driven Lit
templates. This example uses recognizable finance/product icons, current values, growth, margin, mix and percentage
context rather than repeating the chart labels.
The realtime path is shared and intentionally separate from presentation updates:
updateData(next) replaces a dataset immediately without waiting for Lit.
appendPoint(x, values) writes into spare frame capacity and redraws once.
increment revision after mutating an owned input buffer in place.
dataSource.getWindow() pulls lazy ranges; optional subscribe() pushes points through the append path.
max-points bounds a moving window.
uPlot redraws immediately; it does not invent values between samples. A slow annual feed therefore looks stepped.
The demo interpolates consecutive SEC observations with requestAnimationFrame() and calls updateData on each
frame. That smoothness comes from the feed policy, not a chart-engine limitation. For high-frequency telemetry,
append real samples directly and leave animation off so transitions never overlap.
const source = { async getWindow({ xMin, xMax, maxPoints, signal }) { return { data: await fetchWindow({ xMin, xMax, maxPoints, signal }) } }, subscribe(push) { return marketFeed.subscribe(({ time, revenue, income }) => push(time, [revenue, income])) },}chart.dataSource = source
Events and interaction
Every chart reports chart-ready, chart-error, point-click, point-hover, tooltip-change,
legend-change and series-toggle. Cartesian charts also emit range-change after zooming or brushing.
Point and range events do not bubble, so attach listeners to the chart itself. Use data-chart-ready as the
stable test signal after the first frame is drawn.
Hover a point or toggle a legend item below to see the same semantic event model used by external presenters.
Canvas has no intrinsic size. The host gets width from layout and height from --c2-chart--height (320px by
default, 32px for a sparkline). A ResizeObserver keeps the engine canvas synchronized without resize loops.
lazy-render defers both engine import and first draw until the host enters the viewport.
All elements use the --c2-chart__* namespace. Set the palette, typography, axes, grid, crosshair, legend,
tooltip and state variables once on a container and every chart beneath it inherits them. Canvas marks cannot be
reached with ::part(), so the component resolves CSS variables with getComputedStyle and gives the result to
the engine. Theme changes redraw without replacing data.
loading, error and empty data replace the plot with a consistent state layer. Each state has a named slot,
and empty-message changes the default copy. The shared actions slot places controls above the plot; legend
and tooltip slots replace their built-ins. Series definitions occupy the default slot.
Exit
ResetSave to collection
Loading…
Loading filingReading SEC Company Facts…Loading filingReading SEC Company Facts…
No data
No comparable periodChoose another fiscal range.No comparable periodChoose another fiscal range.
The filing could not be loaded
SEC request failedKeep the last valid frame and retry.SEC request failedKeep the last valid frame and retry.
Loading · empty · errorCustomized
<style> .state-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); width: 100%; gap: 12px; } .state-grid c2-line-chart { --c2-chart--height: 170px; } .state-card { display: grid; place-items: center; gap: 5px; text-align: center; } .state-card strong { color: var(--c2-chart--color); }</style><div class="state-grid"> <c2-line-chart loading> <span slot="loading" class="state-card"><strong>Loading filing</strong><small>Reading SEC Company Facts…</small></span> </c2-line-chart> <c2-line-chart data="[]"> <span slot="empty" class="state-card"><strong>No comparable period</strong><small>Choose another fiscal range.</small></span> </c2-line-chart> <c2-line-chart error="The filing could not be loaded"> <span slot="error" class="state-card"><strong>SEC request failed</strong><small>Keep the last valid frame and retry.</small></span> </c2-line-chart></div>
Shared API
Use each component’s API tab for its additions: line curve/points, area fill, bar sizing, pie radii/labels,
and sparkline type/tone. Cartesian charts also share axes, grid, cursor, zoom and y-domain controls through their
uPlot base; pie instead adds ECharts renderer and polar-layout options.
escAccordionConnected, animated panels with shared borders and single or multiple expansion.LayoutArea chartA line chart with the region under each line filled — every line-chart attribute, plus a fill opacity.ChartAttachmentFile and image attachments with metadata, upload progress, failure states, and actions.Data displayAutocompleteSearchable combobox for local or remote items with customizable list rows.InputsAvatarImage, initials or icon for a person, with status dot and badge.Data displayBadgeTinted pill for status text, counts and dots, optionally pinned to a corner of another element.Data displayBar chartBars over categories or time buckets, with several series drawn side by side within each band.ChartBorder BeamA decorative beam that travels around the border of any positioned container.LayoutBreadcrumbNavigation trail of link buttons with separators, a current page and optional collapsing.NavigationButtonThemeable button with slots for text, prefix, suffix and running icons.ButtonsButton GroupJoined actions and polished segmented controls with single or multiple selection.ButtonsCandlestick chartAn ECharts OHLC chart for market sessions and other open-close ranges, with semantic positive and negative colours.ChartCardGroups related content and actions on a single bordered surface.LayoutCascaderSelect a value from related, multi-level data in one floating panel.InputsChat InputAuto-growing message composer with keyboard submission, toolbar actions and native form support.ChatChat MessageFlexible message row for conversations, assistant answers and activity updates.ChatCheckboxNative checkbox behaviour in a quiet, themeable box with an opt-in hover layer.InputsCode EditorEditable, syntax-highlighted source field on CodeMirror 6, themed entirely through CSS variables.InputsCode ViewerSyntax-highlighted code with line numbers, copy button and dark mode, powered by shiki.Data displayColor AreaTwo-dimensional area for picking saturation and value of a colour.InputsColor SelectColour swatch that opens a full picker built from area and slider.InputsColor SliderHorizontal slider for choosing a hue from 0 to 360.InputsCopy ButtonButton that copies text to the clipboard — the element it sits in, another element by id, or a literal string.ButtonsDashboardGrid of resizable panes, dragged by the edges they share.LayoutDate InputForm-associated single-date input with native picker, constraints, helper text and error states.InputsDate SelectorAccessible one- or two-month calendar for choosing a date range.InputsDetailsCollapsible disclosure built on native details and summary.LayoutGauge chartA focused radial KPI gauge drawn by ECharts, with a configurable scale, progress arc and pointer.ChartHeaderArranges brand, navigation, actions and a mobile trigger in a reusable site shell.LayoutIcon ButtonRound, hoverable button wrapping a slotted SVG icon.ButtonsKbdKeyboard key label for shortcuts and command hints, with the semantics of the native kbd element.Data displayLabelCaption that names and activates the control referenced by its for attribute, with a required marker.InputsLine chartA line chart over a time or numeric x axis, drawn on canvas by uPlot, with series declared as children.ChartLink ButtonText-styled control for link and navigation actions, rendered as a real anchor or a button.NavigationListVertical list container with single or multiple selection.Data displayList ItemSelectable row with icon slots, used on its own or as the option of list and select.Data displayMenuCommands, links, checkboxes and submenus in a popover anchored to a trigger.NavigationModalDialog built on the native dialog element: focus trap, backdrop, Escape, title, body and footer.FeedbackNavigation MenuSite navigation bar whose triggers open panels of links below the header.NavigationNumber InputForm-associated numeric input with native validation, step controls, adornments and helper states.InputsOverlayAnchored popup built on the browser Popover API, positioned with floating-ui.FeedbackPaginationPage navigation in three layouts: numbered pages, a simple page status, or a table-footer row with rows-per-page.NavigationPie chartA pie or donut chart drawn by ECharts, where one row is one slice and label-field names it.ChartProgressLinear progress bar, indeterminate or filling to a value, with an optional label and count.FeedbackQR CodeGenerate accessible, themeable QR codes locally as crisp SVG graphics.Data displayQuestionnaireA multi-step single- and multiple-choice flow with validation, shortcuts and form submission.InputsRadar chartCompare several profiles across the same set of normalized indicators.ChartRadioRadio options built on native inputs, grouped into one value with keyboard navigation.InputsRateAccessible star rating input with hover preview, keyboard control and optional half values.InputsReorder ListReorder a vertical queue with pointer or keyboard input while the application owns persistence.Data displayScatter chartAn ECharts scatter plot for finding relationships, clusters and outliers across two numeric measures.ChartSelectDropdown that pairs a themeable trigger with an anchored list of c2-list-item options.InputsSeperatorHorizontal or vertical rule with an optional label, for dividing content and toolbars.LayoutSheetDialog pinned to an edge of the screen, for content that complements the page rather than interrupting it.FeedbackSide NavResponsive navigation drawer beside the page: pushes the content on large screens, slides over it with a backdrop on small ones.NavigationSkeletonPlaceholder block standing in for content that has not arrived, in three shapes and three animations.FeedbackSliderRange input with a themeable track, thumb, step ticks and value bubble.InputsSparklineA chromeless trend line sized for a table cell, a list row or the trend slot of a c2-stat.ChartSpinnerCircular progress indicator, indeterminate or showing a value, with optional text.FeedbackStatDisplays a KPI with an optional icon, trend and supporting description.Data displayStatus PanelCommunicate empty states, operation outcomes and recoverable errors with clear next steps.FeedbackStepsA vertical trace of a task as it runs: statuses, durations, and stages that open while they work and close when they are done.Data displaySwitchOn/off toggle on a native switch input, with label, description and thumb icons.InputsTableVirtualized data grid with declarative columns, sorting, selection, pinning and resizing.Data displayTabsTab strip that shows one content panel at a time.NavigationText FieldSingle-line input with icon slots, clear button, helper and error text, and a character counter.InputsTextareaMultiline text input with resizing, helper and error text, and a character counter.InputsTheme SelectColour-theme switcher: click to step to the next mode, hover for the full menu.InputsToastNotification cards and a manager for stacked, queued notifications with independent lifetimes.FeedbackTooltipContextual hint shown when its target is hovered or focused, rendered in the top layer.FeedbackTreeHierarchical tree view with expansion, selection, checkboxes and lazy loading.Data displayUploadDrag-and-drop file selection with validation, upload progress, retry, cancellation, and attachment results.InputsVirtual ListWindowed list with built-in search, sorting, selection and an async data source.Data displayFeather Icons287 open-source Feather icons, one web component each.IconsMat Icon2,234 Material Icons ligatures rendered through a single element.IconsPhosphor Icons1,512 flexible icons in six weights, one web component each.IconsThemingTheme every c2n component from a handful of design tokens with @c2n/theme, or reach for any component variable directly.GuideFrameworksUse the components from React, Vue, Angular, Svelte, Lit or plain HTML — typed events, generated template types, and the one piece of configuration each framework needs.GuideUsing c2n in an applicationThe workflow behind every c2n app: load the theme once, use c2-* tags directly, and turn every repeated pattern into a small variant or composed component.GuideAI toolsGive Claude Code, Codex or Google Antigravity the c2n skill, live component APIs, examples and application conventions.Guide