@@ -121,9 +121,70 @@ export function InternalCoreChart({
121121 const inverted = ! ! options . chart ?. inverted ;
122122 const isRtl = getIsRtl ( rootRef ?. current ) ;
123123
124- // Compute RTL-adjusted options that will be used for both legend positioning and chart rendering
125- const rtlAdjustedOptions : Highcharts . Options = {
124+ // The Highcharts options takes all provided Highcharts options and custom properties and merges them together, so that
125+ // the Cloudscape features and custom Highcharts extensions co-exist.
126+ // For certain options we provide Cloudscape styling, but in all cases this can be explicitly overridden.
127+ options = {
126128 ...options ,
129+ // Hide credits by default.
130+ credits : options . credits ?? { enabled : false } ,
131+ // Hide chart title by default.
132+ title : options . title ?? { text : "" } ,
133+ // Use Cloudscape color palette by default.
134+ // This cannot be reset to Highcharts' default from the outside, but it is possible to provide custom palette.
135+ colors : options . colors ?? Styles . colors ,
136+ chart : {
137+ // Animations are disabled by default.
138+ // This is done for UX and a11y reasons as Highcharts animations do not match our animation timings, and do
139+ // not respect disabled motion settings. These issues can likely be resolved or we can provide custom animations
140+ // instead, but this is not a priority.
141+ animation : false ,
142+ ...Styles . chart ,
143+ ...options . chart ,
144+ className : clsx ( testClasses [ "chart-plot" ] , options . chart ?. className ) ,
145+ // The debug errors are enabled by default in development mode, but this only works
146+ // if the Highcharts debugger module is loaded.
147+ displayErrors : options . chart ?. displayErrors ?? isDevelopment ,
148+ style : { ...Styles . chartPlotCss , ...options . chart ?. style } ,
149+ } ,
150+ series : options . series ,
151+ // Highcharts legend is disabled by default in favour of the custom Cloudscape legend.
152+ legend : options . legend ?? { enabled : false } ,
153+ lang : {
154+ ...options . lang ,
155+ accessibility : {
156+ // The default chart title is disabled by default to prevent the default "Chart" in the screen-reader detail.
157+ defaultChartTitle : "" ,
158+ chartContainerLabel : labels . chartLabel ,
159+ svgContainerLabel : labels . chartContainerLabel ,
160+ // We used {names[0]} to inject the axis title, see: https://api.highcharts.com/highcharts/lang.accessibility.axis.xAxisDescriptionSingular.
161+ axis : {
162+ xAxisDescriptionSingular : labels . chartXAxisLabel ? `${ labels . chartXAxisLabel } , {names[0]}` : undefined ,
163+ yAxisDescriptionSingular : labels . chartYAxisLabel ? `${ labels . chartYAxisLabel } , {names[0]}` : undefined ,
164+ } ,
165+ ...options . lang ?. accessibility ,
166+ } ,
167+ } ,
168+ accessibility : {
169+ description : labels . chartDescription ,
170+ screenReaderSection : {
171+ // We use custom before-message to remove detail that are currently not supported with our i18n.
172+ // See: https://api.highcharts.com/highcharts/accessibility.screenReaderSection.beforeChartFormat.
173+ beforeChartFormat : "<div>{xAxisDescription}</div><div>{yAxisDescription}</div>" ,
174+ // We hide after message as it is currently not supported with our i18n.
175+ afterChartFormat : "" ,
176+ } ,
177+ ...options . accessibility ,
178+ // Highcharts keyboard navigation is disabled by default in favour of the custom Cloudscape navigation.
179+ keyboardNavigation : options . accessibility ?. keyboardNavigation ?? { enabled : ! keyboardNavigation } ,
180+ point : {
181+ // Point description formatter is overridden to respect custom axes value formatters.
182+ descriptionFormatter : ( point ) => getPointAccessibleDescription ( point , labels ) ,
183+ ...options . accessibility ?. point ,
184+ } ,
185+ } ,
186+ // We use the rtl adjusted axes (instead of the original options.xAxis/yAxis) to ensure the chart renders
187+ // with the correct axis orientation for RTL layouts, matching what was used for legend positioning above.
127188 xAxis : castArray ( options . xAxis ) ?. map ( ( xAxisOptions ) => ( {
128189 ...Styles . xAxisOptions ,
129190 ...xAxisOptions ,
@@ -148,48 +209,59 @@ export function InternalCoreChart({
148209 // correspond the order of stacks.
149210 reversedStacks : yAxisOptions . reversedStacks ?? true ,
150211 } ) ) ,
212+ plotOptions : {
213+ ...options . plotOptions ,
214+ series : {
215+ // Animations are disabled by default, same as in the options.chart.
216+ animation : false ,
217+ // Sticky tracking is disabled by default due to sub-optimal UX in dense charts.
218+ stickyTracking : false ,
219+ borderColor : Styles . seriesBorderColor ,
220+ ...options . plotOptions ?. series ,
221+ dataLabels : { style : Styles . seriesDataLabelsCss , ...options . plotOptions ?. series ?. dataLabels } ,
222+ states : {
223+ ...options . plotOptions ?. series ?. states ,
224+ inactive : { opacity : Styles . seriesOpacityInactive , ...options . plotOptions ?. series ?. states ?. inactive } ,
225+ } ,
226+ } ,
227+ area : { ...Styles . areaSeries , ...options . plotOptions ?. area } ,
228+ areaspline : { ...Styles . areaSeries , ...options . plotOptions ?. areaspline } ,
229+ arearange : { ...Styles . areaSeries , ...options . plotOptions ?. arearange } ,
230+ areasplinerange : { ...Styles . areaSeries , ...options . plotOptions ?. areasplinerange } ,
231+ line : { ...Styles . lineSeries , ...options . plotOptions ?. line } ,
232+ spline : { ...Styles . lineSeries , ...options . plotOptions ?. spline } ,
233+ column : { ...Styles . columnSeries , ...options . plotOptions ?. column } ,
234+ errorbar : { ...Styles . errorbarSeries , ...options . plotOptions ?. errorbar } ,
235+ // Pie chart is shown in legend by default, that is required for standalone pie charts.
236+ pie : {
237+ showInLegend : true ,
238+ ...Styles . pieSeries ,
239+ ...options . plotOptions ?. pie ,
240+ dataLabels : { ...Styles . pieSeriesDataLabels , ...options . plotOptions ?. pie ?. dataLabels } ,
241+ } ,
242+ } ,
243+ // We don't use Highcharts tooltip, but certain tooltip options such as tooltip.snap or tooltip.shared
244+ // affect the hovering behavior of Highcharts. That is only the case when the tooltip is not disabled,
245+ // so we render it, but hide with styles.
246+ tooltip : options . tooltip ?? { enabled : true , snap : Styles . tooltipSnap , style : { opacity : 0 } } ,
151247 } ;
152248
153- const legendProps = getLegendsProps ( rtlAdjustedOptions , legendOptions ) ;
249+ const legendProps = getLegendsProps ( options , legendOptions ) ;
154250
155251 return (
156252 < div { ...rootProps } >
157253 < ChartContainer
158254 { ...containerProps }
159255 chart = { ( height ) => {
160- // The Highcharts options takes all provided Highcharts options and custom properties and merges them together, so that
161- // the Cloudscape features and custom Highcharts extensions co-exist.
162- // For certain options we provide Cloudscape styling, but in all cases this can be explicitly overridden.
163- // We use the rtl adjusted axes (instead of the original options.xAxis/yAxis) to ensure the chart renders
164- // with the correct axis orientation for RTL layouts, matching what was used for legend positioning above.
256+ // We declare event handlers here to ensure that no event fires until the chart is initialized.
165257 const highchartsOptions : Highcharts . Options = {
166258 ...options ,
167- xAxis : rtlAdjustedOptions . xAxis ,
168- yAxis : rtlAdjustedOptions . yAxis ,
169- // Hide credits by default.
170- credits : options . credits ?? { enabled : false } ,
171- // Hide chart title by default.
172- title : options . title ?? { text : "" } ,
173- // Use Cloudscape color palette by default.
174- // This cannot be reset to Highcharts' default from the outside, but it is possible to provide custom palette.
175- colors : options . colors ?? Styles . colors ,
176259 chart : {
177- // Animations are disabled by default.
178- // This is done for UX and a11y reasons as Highcharts animations do not match our animation timings, and do
179- // not respect disabled motion settings. These issues can likely be resolved or we can provide custom animations
180- // instead, but this is not a priority.
181- animation : false ,
182- ...Styles . chart ,
183260 ...options . chart ,
184- className : clsx ( testClasses [ "chart-plot" ] , options . chart ?. className ) ,
185261 // Use height computed from chartHeight, chartMinHeight, and fitHeight settings by default.
186262 // It is possible to override it by explicitly providing chart.height, but this will not be
187263 // compatible with any of the above settings.
188264 height : options . chart ?. height ?? height ,
189- // The debug errors are enabled by default in development mode, but this only works
190- // if the Highcharts debugger module is loaded.
191- displayErrors : options . chart ?. displayErrors ?? isDevelopment ,
192- style : { ...Styles . chartPlotCss , ...options . chart ?. style } ,
193265 // We override certain chart events to inject additional behaviors, but it is still possible to define
194266 // custom callbacks. The Cloudscape behaviors can be disabled or altered via components API. For instance,
195267 // if no-data props are not provided - the related on-render computations will be skipped.
@@ -209,60 +281,10 @@ export function InternalCoreChart({
209281 } ,
210282 } ,
211283 } ,
212- series : options . series ,
213- // Highcharts legend is disabled by default in favour of the custom Cloudscape legend.
214- legend : options . legend ?? { enabled : false } ,
215- lang : {
216- ...options . lang ,
217- accessibility : {
218- // The default chart title is disabled by default to prevent the default "Chart" in the screen-reader detail.
219- defaultChartTitle : "" ,
220- chartContainerLabel : labels . chartLabel ,
221- svgContainerLabel : labels . chartContainerLabel ,
222- // We used {names[0]} to inject the axis title, see: https://api.highcharts.com/highcharts/lang.accessibility.axis.xAxisDescriptionSingular.
223- axis : {
224- xAxisDescriptionSingular : labels . chartXAxisLabel
225- ? `${ labels . chartXAxisLabel } , {names[0]}`
226- : undefined ,
227- yAxisDescriptionSingular : labels . chartYAxisLabel
228- ? `${ labels . chartYAxisLabel } , {names[0]}`
229- : undefined ,
230- } ,
231- ...options . lang ?. accessibility ,
232- } ,
233- } ,
234- accessibility : {
235- description : labels . chartDescription ,
236- screenReaderSection : {
237- // We use custom before-message to remove detail that are currently not supported with our i18n.
238- // See: https://api.highcharts.com/highcharts/accessibility.screenReaderSection.beforeChartFormat.
239- beforeChartFormat : "<div>{xAxisDescription}</div><div>{yAxisDescription}</div>" ,
240- // We hide after message as it is currently not supported with our i18n.
241- afterChartFormat : "" ,
242- } ,
243- ...options . accessibility ,
244- // Highcharts keyboard navigation is disabled by default in favour of the custom Cloudscape navigation.
245- keyboardNavigation : options . accessibility ?. keyboardNavigation ?? { enabled : ! keyboardNavigation } ,
246- point : {
247- // Point description formatter is overridden to respect custom axes value formatters.
248- descriptionFormatter : ( point ) => getPointAccessibleDescription ( point , labels ) ,
249- ...options . accessibility ?. point ,
250- } ,
251- } ,
252284 plotOptions : {
253285 ...options . plotOptions ,
254286 series : {
255- // Animations are disabled by default, same as in the options.chart.
256- animation : false ,
257- // Sticky tracking is disabled by default due to sub-optimal UX in dense charts.
258- stickyTracking : false ,
259- borderColor : Styles . seriesBorderColor ,
260287 ...options . plotOptions ?. series ,
261- dataLabels : { style : Styles . seriesDataLabelsCss , ...options . plotOptions ?. series ?. dataLabels } ,
262- states : {
263- ...options . plotOptions ?. series ?. states ,
264- inactive : { opacity : Styles . seriesOpacityInactive , ...options . plotOptions ?. series ?. states ?. inactive } ,
265- } ,
266288 // We override certain point events to inject additional behaviors, but it is still possible to define
267289 // custom callbacks. The Cloudscape behaviors can be disabled or altered via components API.
268290 point : {
@@ -284,26 +306,7 @@ export function InternalCoreChart({
284306 } ,
285307 } ,
286308 } ,
287- area : { ...Styles . areaSeries , ...options . plotOptions ?. area } ,
288- areaspline : { ...Styles . areaSeries , ...options . plotOptions ?. areaspline } ,
289- arearange : { ...Styles . areaSeries , ...options . plotOptions ?. arearange } ,
290- areasplinerange : { ...Styles . areaSeries , ...options . plotOptions ?. areasplinerange } ,
291- line : { ...Styles . lineSeries , ...options . plotOptions ?. line } ,
292- spline : { ...Styles . lineSeries , ...options . plotOptions ?. spline } ,
293- column : { ...Styles . columnSeries , ...options . plotOptions ?. column } ,
294- errorbar : { ...Styles . errorbarSeries , ...options . plotOptions ?. errorbar } ,
295- // Pie chart is shown in legend by default, that is required for standalone pie charts.
296- pie : {
297- showInLegend : true ,
298- ...Styles . pieSeries ,
299- ...options . plotOptions ?. pie ,
300- dataLabels : { ...Styles . pieSeriesDataLabels , ...options . plotOptions ?. pie ?. dataLabels } ,
301- } ,
302309 } ,
303- // We don't use Highcharts tooltip, but certain tooltip options such as tooltip.snap or tooltip.shared
304- // affect the hovering behavior of Highcharts. That is only the case when the tooltip is not disabled,
305- // so we render it, but hide with styles.
306- tooltip : options . tooltip ?? { enabled : true , snap : Styles . tooltipSnap , style : { opacity : 0 } } ,
307310 } ;
308311 return (
309312 < >
0 commit comments