Charts with ApexCharts
Use uiChart(config) for analytical charts with ApexCharts options and datasets. The shared provider loads the pinned ApexCharts 7.4.0 dependency only when it has data to render. createAdmin registers the provider. The factory is also exported as chartView from @agon/atrium and @agon/atrium/components/chart. See the working showcase at /components/chart.
API integration
Your application owns the endpoint, authentication, authorization, filters, and response normalization. Supply load({ signal }) and return { options, series }. Forward the cancellation signal to your HTTP client. The component does not assume an API URL or store credentials.
Register your page provider in its lazy route module:
import { createHttpClient } from '@agon/atrium/services/http';
/** * Register an application-owned reporting page. * * @param {object} context - Lazy page context. * @param {object} context.Alpine - Shared Alpine runtime. * @returns {void} Registers report configuration before the page mounts. */export function register({ Alpine }) { const request = createHttpClient({ base: '/api/' }); Alpine.data( 'reportsPage', /** * Create independent settings for one reporting page. * * @returns {object} Page-owned chart configuration. */ () => ({ trafficChart: { label: 'Monthly requests', options: { chart: { type: 'area', height: 360 }, stroke: { curve: 'smooth' }, }, /** * Fetch chart configuration and data from the application API. * * @param {object} query - Chart request context. * @param {AbortSignal} query.signal - Request cancellation signal. * @returns {Promise<object>} ApexCharts options and series envelope. */ load({ signal }) { return request('reports/traffic', { signal }); }, }, }), );}Declare the page’s module and template in your route metadata, following lazy page contracts. Its template has one root:
<section x-data="reportsPage"> <h1>Traffic</h1> <div x-data="uiChart(trafficChart)"> <include src="{{ uiRoot }}/chart.html"></include> </div></section>The endpoint returns JSON such as:
{ "options": { "chart": { "type": "area" }, "xaxis": { "categories": ["Jan", "Feb", "Mar"] } }, "series": [ { "name": "Requests", "data": [120, 180, 150] } ]}series is the dataset in ApexCharts’ native format. Axis charts accept named series with data arrays, including { x, y } points. Pie, donut, and radial charts accept numeric series with corresponding options.labels. See the upstream series formats and options reference. A different backend envelope should be mapped by your adapter before returning it.
Settings and methods
| Setting or method | Contract |
|---|---|
options | Local ApexCharts defaults. Optional. Defaults to a line chart with a 320px height. |
series | Local dataset when no load adapter is supplied. Optional. Defaults to an empty array. |
load({ signal }) | Optional asynchronous adapter returning { options?: object, series: Array }. |
label | Plain-text accessible name for the chart region. Defaults to the translated chart label. |
init() | Automatically loads and renders when Alpine mounts the component. |
refresh() | Cancels previous work and reloads the adapter, or restores the initial local configuration. |
update({ options, series }) | Replaces the chart using a complete payload without calling the adapter. Local defaults still apply. |
status | idle, loading, ready, empty, or error. |
destroy() | Cancels requests, removes the chart, and disconnects observers. Alpine calls it during teardown. |
Options are recursively merged in this order: theme defaults, local options, response options. Arrays replace previous arrays. The top-level series always supplies the dataset, even if an options object contains a series property. Each render receives independent copies of options records and arrays. Local JavaScript callbacks retain their identity. Remote JSON is never evaluated as JavaScript. Keep formatter and event functions in trusted application code, and only pass API options from a trusted backend. The component validates the envelope, while the adapter owns chart-specific data validation and any option allowlist for user-authored settings.
A local chart can use { options: { chart: { type: 'donut' }, labels: ['Used', 'Free'] }, series: [65, 35] }. Call update(nextPayload) when application filters, streams, or other state produce a new dataset. Configuration is not deeply watched. Refresh and explicit updates recreate the chart so changing types or removing options cannot retain stale settings. They reset zoom and legend selection. Use the ApexCharts native methods in a consumer-specific integration if preserving that interaction state is required.
Lifecycle, theme, and accessibility
Every request owns an AbortSignal. Replacing the chart or navigating away aborts it. Late successes and failures are ignored even if an adapter does not honor cancellation. A chart still finishing its initial render is detached immediately and disposed when that render settles. Native instances remain outside Alpine’s proxies. The included template leaves native chart descendants under x-ignore.
Empty series and axis series with no points display a localized empty state without downloading the renderer. Zero-valued samples remain valid data. Network failures, malformed envelopes, and rendering failures display a generic error and allow retry. Error text does not expose backend diagnostics.
The component uses Atrium text, accent, grid, and palette tokens. Theme changes recreate the chart from the cached payload without requesting data again. This also refreshes native tooltip state and resets zoom and legend selection. Explicit API or local colors override theme defaults. ApexCharts owns resize listeners and releases them on destruction. The default chart has animations and the export toolbar disabled. Consumers enabling animations must honor reduced-motion preferences. Chart axes remain left-to-right inside RTL layouts, while the surrounding controls follow the application direction.
Use a meaningful label and provide a prose summary or accessible data table when chart values carry essential information. Loading states are announced, refresh is a native button, and empty/error messages remain accessible. The production showcase is checked under the application’s CSP without inline scripts or unsafe-eval. Its existing inline-style allowance is still required by native chart positioning.
The showcase retrieves static JSON fixtures over real HTTP under the application’s base path. Selecting the unavailable scenario intentionally requests a missing fixture to demonstrate HTTP failure and retry. These illustrative records belong to the showcase, not the shared package.
ApexCharts retains its own upstream license. Atrium’s license does not replace the dependency’s terms. Applications own any applicable ApexCharts licensing and license configuration.
Author
Laurent Declercq l.declercq@agon-innovation.ch
License
Unless otherwise stated all source code is licensed under LGPL 2.1 and has the following copyright:
© 2026, Agon Partners Innovation AG, All rights reserved.The design material and the “Agon Ātrium” trademark is the property of their authors. Reuse of them without prior consent of their respective authors is strictly prohibited.
Version
Version: 20260921