Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

/* eslint-disable @typescript-eslint/no-unused-vars */
import { FC } from 'react';

import { DEFAULT_METRIC } from '@spectrum-charts/constants';

import { GaugeProps } from '../../../types';

const DEFAULT_ARC_SIZE = 2 / 3;
const DEFAULT_HOLE_RATIO = 0.8;
const DEFAULT_MAX_SCALE_VALUE = 100;
const DEFAULT_METHOD = 'last';
const DEFAULT_MIN_SCALE_VALUE = 0;
const DEFAULT_NUMBER_FORMAT = 'shortNumber';
const DEFAULT_SIZE = 'M';

// destructure props here and set defaults so that storybook can pick them up
const Gauge: FC<GaugeProps> = ({
arcSize = DEFAULT_ARC_SIZE,
children,
color = 'categorical-01',
holeRatio = DEFAULT_HOLE_RATIO,
label,
maxScaleValue = DEFAULT_MAX_SCALE_VALUE,
method = DEFAULT_METHOD,
metric = DEFAULT_METRIC,
minScaleValue = DEFAULT_MIN_SCALE_VALUE,
name,
numberFormat = DEFAULT_NUMBER_FORMAT,
showNeedle = true,
showRangeLabels = false,
size = DEFAULT_SIZE,
target,
targetLabel,
thresholds,
ticks,
}) => {
return null;
};

// displayName is used to validate the component type in the spec builder
Gauge.displayName = 'Gauge';

export { Gauge };
13 changes: 13 additions & 0 deletions packages/react-spectrum-charts-s2/src/rc/components/Gauge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

export * from './Gauge';
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@

export * from './Donut';
export * from './DonutSummary';
export * from './Gauge';
export * from './SegmentLabel';
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { Line } from '../components/Line';
import { LineDirectLabel } from '../components/LineDirectLabel';
import { ReferenceLine } from '../components/ReferenceLine';
import { Title } from '../components/Title';
import { Donut, DonutSummary, SegmentLabel } from '../rc';
import { Donut, DonutSummary, Gauge, SegmentLabel } from '../rc';
import {
AxisProps,
AxisThumbnailProps,
Expand All @@ -47,6 +47,7 @@ import {
ChartTooltipProps,
DonutProps,
DonutSummaryProps,
GaugeProps,
LegendProps,
LineDirectLabelProps,
LineProps,
Expand All @@ -60,6 +61,7 @@ import { getBarOptions } from './barAdapter';
import { getChartPopoverOptions } from './chartPopoverAdapter';
import { getChartTooltipOptions } from './chartTooltipAdapter';
import { getDonutOptions } from './donutAdapter';
import { getGaugeOptions } from './gaugeAdapter';
import { getLegendOptions } from './legendAdapter';
import { getLineOptions } from './lineAdapter';

Expand Down Expand Up @@ -130,6 +132,10 @@ export const childrenToOptions = (
marks.push(getDonutOptions(child.props as DonutProps));
break;

case Gauge.displayName:
marks.push(getGaugeOptions(child.props as GaugeProps));
break;

case DonutSummary.displayName:
donutSummaries.push(child.props as DonutSummaryProps);
break;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { GaugeOptions } from '@spectrum-charts/vega-spec-builder-s2';

import { GaugeProps } from '../types';
import { childrenToOptions } from './childrenAdapter';

export const getGaugeOptions = ({ children, ...gaugeProps }: GaugeProps): GaugeOptions => {
const { chartTooltips } = childrenToOptions(children);
return {
...gaugeProps,
chartTooltips,
markType: 'gauge',
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/*
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { ReactElement } from 'react';

import { StoryFn } from '@storybook/react';

import { Chart } from '../../../Chart';
import useChartProps from '../../../hooks/useChartProps';
import { Gauge } from '../../../rc';
import { bindWithProps } from '../../../test-utils';
import { ChartProps, GaugeProps } from '../../../types';
import { gaugeMultiRowData, gaugeWithTargetData } from './data';

export default {
title: 'React Spectrum Charts 2/Gauge/Features',
component: Gauge,
};

const SIZE = 275;

const defaultChartProps: ChartProps = {
data: [],
width: SIZE,
height: SIZE,
};

const GaugeStory: StoryFn<GaugeProps & { width?: number; height?: number; value?: number }> = (args): ReactElement => {
const { width, height, value = 65, ...gaugeProps } = args;
const chartProps = useChartProps({ ...defaultChartProps, data: [{ value }], width: width ?? SIZE, height: height ?? SIZE });
return (
<Chart {...chartProps}>
<Gauge {...gaugeProps} />
</Chart>
);
};

const GaugeAggregationStory: StoryFn<GaugeProps & { width?: number; height?: number }> = (args): ReactElement => {
const { width, height, ...gaugeProps } = args;
const chartProps = useChartProps({ ...defaultChartProps, data: gaugeMultiRowData, width: width ?? SIZE, height: height ?? SIZE });
return (
<Chart {...chartProps}>
<Gauge {...gaugeProps} />
</Chart>
);
};

const GaugeWithTargetStory: StoryFn<GaugeProps & { width?: number; height?: number; value?: number }> = (args): ReactElement => {
const { width, height, value = 65, ...gaugeProps } = args;
const chartProps = useChartProps({
...defaultChartProps,
data: [{ ...gaugeWithTargetData[0], value }],
width: width ?? SIZE,
height: height ?? SIZE,
});
return (
<Chart {...chartProps}>
<Gauge {...gaugeProps} />
</Chart>
);
};

// Needle mode (default)
const Basic = bindWithProps(GaugeStory);
Basic.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
};

// Fill mode (no needle)
const FillMode = bindWithProps(GaugeStory);
FillMode.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: false,
};

// Needle with target marker
const WithTarget = bindWithProps(GaugeWithTargetStory);
WithTarget.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
target: 'target',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
};

// Threshold zones with needle
const WithThresholds = bindWithProps(GaugeStory);
WithThresholds.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
thresholds: [
{ value: 20, color: 'red-700', label: 'Poor' },
{ value: 70, color: 'gray-300', label: 'Normal' },
{ value: 100, color: 'blue-700', label: 'Good' },
],
};

// Size variants
const WithSizeS = bindWithProps(GaugeStory);
WithSizeS.args = { value: 65, label: 'Completion Rate', metric: 'value', size: 'S', width: 100, height: 100, ticks: 'normal' };

const WithSizeM = bindWithProps(GaugeStory);
WithSizeM.args = { value: 65, label: 'Completion Rate', metric: 'value', size: 'M', width: 200, height: 200, ticks: 'normal' };

const WithSizeL = bindWithProps(GaugeStory);
WithSizeL.args = { value: 65, label: 'Completion Rate', metric: 'value', size: 'L', width: 275, height: 275, ticks: 'normal' };

const WithSizeXL = bindWithProps(GaugeStory);
WithSizeXL.args = { value: 65, label: 'Completion Rate', metric: 'value', size: 'XL', width: 350, height: 350, ticks: 'normal' };

// Tick marks — minimal (6-10 evenly spaced major ticks)
const WithTicksMinimal = bindWithProps(GaugeStory);
WithTicksMinimal.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
ticks: 'minimal',
};

// Tick marks — normal (alternating tall/short)
const WithTicksNormal = bindWithProps(GaugeStory);
WithTicksNormal.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
ticks: 'normal',
};

// Tick marks — dense (major ticks with 3 minor ticks between each)
const WithTicksDense = bindWithProps(GaugeStory);
WithTicksDense.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
ticks: 'dense',
};

// Aggregation method — avg of [40, 60, 80] = 60
const WithAggregation = bindWithProps(GaugeAggregationStory);
WithAggregation.args = {
label: 'Avg Completion',
metric: 'value',
method: 'avg',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
};

// Range labels
const WithRangeLabels = bindWithProps(GaugeStory);
WithRangeLabels.args = {
value: 65,
label: 'Completion Rate',
metric: 'value',
minScaleValue: 0,
maxScaleValue: 100,
showNeedle: true,
showRangeLabels: true,
};

export { Basic, FillMode, WithAggregation, WithRangeLabels, WithSizeL, WithSizeM, WithSizeS, WithSizeXL, WithTarget, WithThresholds, WithTicksDense, WithTicksMinimal, WithTicksNormal };
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/

export const basicGaugeData = [{ value: 65 }];

export const gaugeWithTargetData = [{ value: 65, target: 80, targetLabel: 'Goal' }];

export const gaugeMultiRowData = [{ value: 40 }, { value: 60 }, { value: 80 }];
4 changes: 2 additions & 2 deletions packages/react-spectrum-charts-s2/src/types/chart.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ import {
import { AxisElement } from './axis';
import { ChartPopoverElement, ChartTooltipElement } from './dialogs';
import { LegendElement } from './legend.types';
import { BarAnnotationElement, BarElement, DonutElement, DonutSummaryElement, LineElement } from './marks';
import { BarAnnotationElement, BarElement, DonutElement, DonutSummaryElement, GaugeElement, LineElement } from './marks';
import { TitleElement } from './title.types';
import { Children } from './util.types';

export type ChartChildElement = AxisElement | BarElement | DonutElement | LegendElement | LineElement | TitleElement;
export type ChartChildElement = AxisElement | BarElement | DonutElement | GaugeElement | LegendElement | LineElement | TitleElement;
export type MarkChildElement = BarAnnotationElement | ChartPopoverElement | ChartTooltipElement | DonutSummaryElement;

export interface SharedChartProps extends Omit<ChartOptions, 'axes' | 'legends' | 'marks' | 'titles'> {
Expand Down
23 changes: 23 additions & 0 deletions packages/react-spectrum-charts-s2/src/types/marks/gauge.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2026 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
import { JSXElementConstructor, ReactElement } from 'react';

import { GaugeOptions } from '@spectrum-charts/vega-spec-builder-s2';

import { ChartTooltipElement } from '../dialogs';
import { Children } from '../util.types';

export interface GaugeProps extends Omit<GaugeOptions, 'chartTooltips' | 'markType'> {
children?: Children<ChartTooltipElement>;
}

export type GaugeElement = ReactElement<GaugeProps, JSXElementConstructor<GaugeProps>>;
1 change: 1 addition & 0 deletions packages/react-spectrum-charts-s2/src/types/marks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

export * from './bar.types';
export * from './donut.types';
export * from './gauge.types';
export * from './line.types';

export * from './supplemental';
Loading
Loading