Skip to main content

Spectrum 2 Overview

Work in progress

Spectrum 2 support in React Spectrum Charts is actively under development. The S2 package still has some Spectrum 1 dependencies that are being incrementally migrated. We will make an effort not to introduce breaking API changes to Spectrum 2 features prior to Adobe Summit.

React Spectrum Charts offers two paths for Spectrum 2 support. This page explains the difference between them, how to install the full S2 package, and how theming works.

S2 prop vs. the S2 package​

s2 prop (partial S2 support)​

The @adobe/react-spectrum-charts package includes an s2 prop on the Chart component. When set to true, it enables Spectrum 2 styling for supported chart types. Currently supported: Line, Bar, and Donut.

import { Chart, Bar } from '@adobe/react-spectrum-charts';

<Chart data={data} s2>
<Bar color="series" />
</Chart>

Use this approach if you are already using @adobe/react-spectrum-charts and only need S2 theming for supported chart types.

@spectrum-charts/react-spectrum-charts-s2 package (full S2 support)​

The S2 package is a separate alpha package built entirely on Spectrum 2. It provides a full S2-native implementation of the chart library with additional features not available in the base package. All components are imported from this package instead of @adobe/react-spectrum-charts.

Use this approach when you need access to S2-exclusive features such as line gradients, line labels, line interpolation, or S2 reference lines.


Installing the S2 package​

The S2 package is published under the alpha tag on npm.

npm install @spectrum-charts/react-spectrum-charts-s2
# or
yarn add @spectrum-charts/react-spectrum-charts-s2

Import components from the S2 package instead of the base package:

import { Chart, Axis, Line, Legend } from '@spectrum-charts/react-spectrum-charts-s2';

The S2 package has these peer dependencies, which your app must install:

PackageVersion
@react-spectrum/s2>=1.0.0
react, react-dom>=19.0.0
react-aria-components^1.14.0, matching the version your @react-spectrum/s2 depends on
vega^6.2.0
vega-lite^6.4.2

Since 1.3.0, @react-spectrum/s2 pins an exact react-aria-components version. Install that same version so your app has one copy and charts share React Aria context with S2:

npm install @react-spectrum/s2 react react-dom vega vega-lite
npm ls react-aria-components # shows the version @react-spectrum/s2 uses
npm install react-aria-components@<that version>

Module format​

The S2 packages ship ES modules only, one file per module, so bundlers include only what you import. require() and the UMD global are not supported, and Node.js 20.19 or later is required.

Jest​

Jest runs CommonJS, so it must transform the package and its ES module dependencies (Vega and d3), and stub CSS. Works with Jest 29 and 30:

// jest.config.js — transforms use your babel.config.js; a .babelrc does not apply to node_modules.
module.exports = {
testEnvironment: './jest.environment.js',
transformIgnorePatterns: [
'node_modules/(?!(@spectrum-charts|vega|vega-[^/]+|d3-[^/]+|internmap|delaunator|robust-predicates|json-stringify-pretty-compact)/)',
],
moduleNameMapper: {
'\\.css$': '<rootDir>/test/styleStub.js',
// Jest 30 otherwise loads vega-canvas's Node build, which uses top-level await.
'^vega-canvas$': '<rootDir>/node_modules/vega-canvas/build/vega-canvas.browser.js',
},
};
// jest.environment.js — jsdom does not provide structuredClone, which Vega-Lite uses.
const { TestEnvironment } = require('jest-environment-jsdom');

module.exports = class extends TestEnvironment {
async setup() {
await super.setup();
this.global.structuredClone = structuredClone;
}
};
// test/styleStub.js
module.exports = {};

Vitest​

Vitest runs ES modules natively. Inline this package and @react-spectrum/s2 so Vite handles their CSS imports:

// vitest.config.js
import { defineConfig } from 'vitest/config';

export default defineConfig({
test: {
environment: 'jsdom',
server: {
deps: { inline: ['@spectrum-charts/react-spectrum-charts-s2', '@react-spectrum/s2'] },
},
},
});

Theming​

Color scheme​

The Chart component accepts a colorScheme prop to switch between light and dark mode. This controls both the chart's visual theme and the styling of tooltips and popovers.

<Chart data={data} colorScheme="dark">
<Line color="series" />
</Chart>
ValueDescription
'light'Light mode (default)
'dark'Dark mode

Colors​

The S2 package uses Spectrum 2 categorical color scales by default. You can override the color scale using the colors prop on Chart.

Available S2 color scales: s2Categorical6, s2Categorical12, s2Categorical16, s2Categorical20.

<Chart data={data} colors="s2Categorical12">
<Line color="series" />
</Chart>

Inspect panels​

Inspect panels in the S2 package are styled automatically to match the Spectrum 2 design specification — including the correct font (adobe-clean), text colors, border, and elevated box shadow. No additional configuration is required.

Add a ChartInspect as a child of a mark component to enable inspect panels:

<Line color="series">
<ChartInspect>
{(datum) => (
<div>
<div>Series: {datum.series}</div>
<div>Value: {datum.value}</div>
</div>
)}
</ChartInspect>
</Line>

Popovers​

Popovers are styled to match the Spectrum 2 elevated surface style (border, box shadow, font). Add a ChartPopover as a child of a mark component to enable click-to-open popovers:

<Line color="series">
<ChartPopover width={200}>
{(datum, close) => (
<div>
<div>Series: {datum.series}</div>
<div>Value: {datum.value}</div>
<button onClick={close}>Close</button>
</div>
)}
</ChartPopover>
</Line>

ChartInspect props​

nametypedefaultdescription
children(datum: Datum) => ReactNode–Callback that returns the content to render inside the inspect panel. Optional inside a Donut, which renders default content when omitted.
excludeDataKeysstring[]–Keys in the data that, if they have truthy values, will suppress the inspect panel for that data point.
highlightBy'series' | 'dimension' | 'item' | string[]'item'Controls which marks are highlighted when an inspect panel is visible.
targets('dimensionArea' | 'item')[]['item']The hit targets that trigger the inspect panel.

ChartPopover props​

nametypedefaultdescription
children(datum: Datum, close: () => void) => ReactNode–Callback that returns the content to render inside the popover. The second argument is a function that closes the popover. Optional inside a Donut, which renders default content when omitted.
widthnumber | 'auto'250Width of the popover in pixels, or 'auto' to size to content.
minWidthnumber0Minimum width of the popover in pixels.
maxWidthnumber–Maximum width of the popover in pixels.
heightnumber | 'auto'–Height of the popover in pixels.
minHeightnumber–Minimum height of the popover in pixels.
maxHeightnumber–Maximum height of the popover in pixels.
contentMarginnumber12Inner margin applied around the popover content in pixels.
onOpenChange(isOpen: boolean) => void–Callback fired when the popover opens or closes.
rightClickbooleanfalseWhen true, the popover opens on right-click instead of left-click.
containerPaddingnumber12Minimum distance between the popover and the edges of its container.