Skip to content
Merged
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,7 @@
{
"type": "none",
"comment": "chore: fix test target dependencies",
"packageName": "@fluentui/react-button",
"email": "[email protected]",
"dependentChangeType": "none"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "patch",
"comment": "support chart title from plotly schema",
"packageName": "@fluentui/react-charts",
"email": "[email protected]",
"dependentChangeType": "patch"
}

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/a11y-testing/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# @fluentui/a11y-testing

Tests for testing a11y conformance of components and hooks, together with typings for creating custom definitions.

> [!NOTE]
> This package was developed and used primarily for react-northstar (v0). There is only [one module for the `react-button` package](./src/definitions/react-button/buttonAccessibilityBehaviorDefinition.ts) that is used in its tests.
19 changes: 19 additions & 0 deletions packages/charts/react-charts/library/etc/react-charts.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```ts

import { CurveFactory } from 'd3-shape';
import type { Font } from '@fluentui/chart-utilities';
import type { JSXElement } from '@fluentui/react-utilities';
import type { Margin } from '@fluentui/chart-utilities';
import { PositioningShorthand } from '@fluentui/react-positioning';
Expand Down Expand Up @@ -233,6 +234,7 @@ export interface CartesianChartProps {
tickPadding?: number;
tickValues?: number[] | Date[] | string[] | undefined;
timeFormatLocale?: TimeLocaleDefinition;
titleStyles?: TitleStyles;
useUTC?: string | boolean;
width?: number;
wrapXAxisLables?: boolean;
Expand Down Expand Up @@ -508,6 +510,7 @@ export const ChartTable: React_2.FunctionComponent<ChartTableProps>;

// @public
export interface ChartTableProps {
chartTitle?: string;
className?: string;
componentRef?: React_2.Ref<Chart>;
headers: {
Expand All @@ -520,6 +523,7 @@ export interface ChartTableProps {
style?: React_2.CSSProperties;
}[][];
styles?: ChartTableStyles;
titleStyles?: TitleStyles;
width?: string | number;
}

Expand All @@ -530,10 +534,14 @@ export interface ChartTableStyles {
// (undocumented)
chart?: string;
// (undocumented)
chartTitle?: string;
// (undocumented)
headerCell?: string;
// (undocumented)
root?: string | React_2.CSSProperties;
// (undocumented)
svgTooltip?: string;
// (undocumented)
table?: string;
}

Expand Down Expand Up @@ -732,6 +740,7 @@ export interface DonutChartProps extends CartesianChartProps {
roundCorners?: boolean;
showLabelsInPercent?: boolean;
styles?: DonutChartStyles;
titleStyles?: TitleStyles;
valueInsideDonut?: string | number;
width?: number;
}
Expand All @@ -744,9 +753,11 @@ export interface DonutChartStyleProps extends CartesianChartStyleProps {
export interface DonutChartStyles {
axisAnnotation?: string;
chart?: string;
chartTitle?: string;
chartWrapper?: string;
legendContainer: string;
root?: string;
svgTooltip?: string;
}

// @public (undocumented)
Expand Down Expand Up @@ -813,6 +824,7 @@ export interface FunnelChartProps {
legendProps?: Partial<LegendsProps>;
orientation?: 'horizontal' | 'vertical';
styles?: FunnelChartStyles;
titleStyles?: TitleStyles;
width?: number;
}

Expand All @@ -827,7 +839,9 @@ export interface FunnelChartStyleProps {
export interface FunnelChartStyles {
calloutContentRoot?: string;
chart?: string;
chartTitle?: string;
root?: string;
svgTooltip?: string;
text?: string;
}

Expand Down Expand Up @@ -895,6 +909,7 @@ export interface GaugeChartProps {
segments: GaugeChartSegment[];
styles?: GaugeChartStyles;
sublabel?: string;
titleStyles?: TitleStyles;
variant?: GaugeChartVariant;
width?: number;
}
Expand Down Expand Up @@ -1600,6 +1615,7 @@ export interface SankeyChartProps {
enableReflow?: boolean;
formatNumberOptions?: Intl.NumberFormatOptions;
height?: number;
hideLegend?: boolean;
parentRef?: HTMLElement | null;
pathColor?: string;
reflowProps?: {
Expand All @@ -1608,6 +1624,7 @@ export interface SankeyChartProps {
shouldResize?: number;
strings?: SankeyChartStrings;
styles?: SankeyChartStyles;
titleStyles?: TitleStyles;
width?: number;
}

Expand All @@ -1619,11 +1636,13 @@ export interface SankeyChartStrings {
// @public
export interface SankeyChartStyles {
chart?: string;
chartTitle?: string;
chartWrapper?: string;
links?: string;
nodes?: string;
nodeTextContainer?: string;
root?: string;
svgTooltip?: string;
toolTip?: string;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { tokens } from '@fluentui/react-theme';
import * as d3 from 'd3-color';
import { getColorContrast } from '../../utilities/colors';
import { resolveCSSVariables } from '../../utilities/utilities';
import { ChartTitle } from '../../utilities/index';
import { useImageExport } from '../../utilities/hooks';
import { useArrowNavigationGroup } from '@fluentui/react-tabster';

Expand Down Expand Up @@ -47,7 +48,7 @@ function getSafeBackgroundColor(chartContainer: HTMLElement, foreground?: string

export const ChartTable: React.FunctionComponent<ChartTableProps> = React.forwardRef<HTMLDivElement, ChartTableProps>(
(props, forwardedRef) => {
const { headers, rows, width, height } = props;
const { headers, rows, width, height, chartTitle } = props;
const { chartContainerRef: _rootElem } = useImageExport(props.componentRef, true, false);
const classes = useChartTableStyles(props);
const arrowAttributes = useArrowNavigationGroup({ axis: 'grid' });
Expand Down Expand Up @@ -89,16 +90,33 @@ export const ChartTable: React.FunctionComponent<ChartTableProps> = React.forwar
}
}

const titleHeight = chartTitle ? 30 : 0;
const totalHeight = typeof height === 'number' ? height : 650;
const tableHeight = `${totalHeight - titleHeight}px`;
const svgWidth = typeof width === 'number' ? width : '100%';
const titleMaxWidth = typeof width === 'number' ? width - 20 : undefined;
const titleX = typeof width === 'number' ? width / 2 : 0;

return (
<div
ref={el => {
_rootElem.current = el;
}}
className={classes.root as string}
style={{ height: height ? `${height}px` : '650px', overflow: 'hidden' }}
style={{ height: `${totalHeight}px`, overflow: 'hidden' }}
>
<svg width={width ?? '100%'} height={height ?? '650px'}>
<foreignObject x="0" y="0" width="100%" height="100%">
<svg width={svgWidth} height={`${totalHeight}px`}>
{chartTitle && (
<ChartTitle
title={chartTitle}
x={titleX}
maxWidth={titleMaxWidth}
className={classes.chartTitle}
titleStyles={props.titleStyles}
tooltipClassName={classes.svgTooltip}
/>
)}
<foreignObject x="0" y={titleHeight} width="100%" height={tableHeight}>
<div
style={{
maxHeight: height ? `${height}px` : '650px',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import * as React from 'react';
import type { TitleStyles } from '../../utilities/Common.styles';
import { Chart } from './index';

/**
* Chart Table properties
* {@docCategory ChartTable}
*/
export interface ChartTableProps {
/**
* Title styles configuration for the chart title
*/
titleStyles?: TitleStyles;

/**
* 1d or 2d Array of header values.
*/
Expand All @@ -28,6 +34,11 @@ export interface ChartTableProps {
*/
height?: string | number;

/**
* Chart title to display above the table
*/
chartTitle?: string;

/**
* Additional class name(s) to apply to the table chart
*/
Expand Down Expand Up @@ -55,4 +66,6 @@ export interface ChartTableStyles {
headerCell?: string;
bodyCell?: string;
chart?: string;
chartTitle?: string;
svgTooltip?: string;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
'use client';

import { makeStyles, mergeClasses } from '@griffel/react';
import { GriffelStyle, makeStyles, mergeClasses } from '@griffel/react';
import type { SlotClassNames } from '@fluentui/react-utilities';
import { ChartTableProps, ChartTableStyles } from './ChartTable.types';
import { tokens, typographyStyles } from '@fluentui/react-theme';
import { getChartTitleStyles, HighContrastSelector } from '../../utilities/index';

/**
* @internal
Expand All @@ -14,6 +15,8 @@ export const chartTableClassNames: SlotClassNames<ChartTableStyles> = {
headerCell: 'fui-ChartTable__headerCell',
bodyCell: 'fui-ChartTable__bodyCell',
chart: 'fui-ChartTable__chart',
chartTitle: 'fui-ChartTable__chartTitle',
svgTooltip: 'fui-ChartTable__svgTooltip',
};

const useStyles = makeStyles({
Expand Down Expand Up @@ -47,6 +50,13 @@ const useStyles = makeStyles({
color: 'WindowText',
},
},
chartTitle: getChartTitleStyles() as GriffelStyle,
svgTooltip: {
fill: tokens.colorNeutralBackground1,
[HighContrastSelector]: {
fill: 'Canvas',
},
},
});

/**
Expand All @@ -61,5 +71,7 @@ export const useChartTableStyles = (props: ChartTableProps): ChartTableStyles =>
headerCell: mergeClasses(chartTableClassNames.headerCell, baseStyles.headerCell /*props.styles?.headerCell*/),
bodyCell: mergeClasses(chartTableClassNames.bodyCell, baseStyles.bodyCell /*props.styles?.bodyCell*/),
chart: mergeClasses(chartTableClassNames.chart /*props.styles?.chart*/),
chartTitle: mergeClasses(chartTableClassNames.chartTitle, baseStyles.chartTitle /*props.styles?.chartTitle*/),
svgTooltip: mergeClasses(chartTableClassNames.svgTooltip, baseStyles.svgTooltip /*props.styles?.svgTooltip*/),
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
getSecureProps,
DEFAULT_WRAP_WIDTH,
autoLayoutXAxisLabels,
getChartTitleInlineStyles,
} from '../../utilities/index';
import { useId } from '@fluentui/react-utilities';
import type { JSXElement } from '@fluentui/react-utilities';
Expand Down Expand Up @@ -786,10 +787,15 @@ export const CartesianChart: React.FunctionComponent<ModifiedCartesianChartProps
content={props.xAxisAnnotation}
textProps={{
x: margins.left! + AXIS_TITLE_PADDING + xAxisTitleMaxWidth / 2,
y: VERTICAL_MARGIN_FOR_XAXIS_TITLE - AXIS_TITLE_PADDING,
y: Math.max(
(typeof props.titleStyles?.titleFont?.size === 'number' ? props.titleStyles.titleFont.size : 13) +
AXIS_TITLE_PADDING,
VERTICAL_MARGIN_FOR_XAXIS_TITLE - AXIS_TITLE_PADDING,
),
className: classes.axisAnnotation!,
textAnchor: 'middle',
'aria-hidden': true,
style: getChartTitleInlineStyles(props.titleStyles?.titleFont),
}}
maxWidth={xAxisTitleMaxWidth}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import type { JSXElement } from '@fluentui/react-utilities';
import { LegendsProps } from '../Legends/index';
import type { TitleStyles } from '../../utilities/Common.styles';
import {
AccessibilityProps,
Chart,
Expand Down Expand Up @@ -176,6 +177,11 @@ export interface CartesianChartStyles {
* {@docCategory CartesianChart}
*/
export interface CartesianChartProps {
/**
* Title styles configuration for the chart title
*/
titleStyles?: TitleStyles;

/**
* Below height used for resizing of the chart
* Wrap chart in your container and send the updated height and width to these props.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
sanitizeJson,
} from '@fluentui/chart-utilities';
import type { GridProperties } from './PlotlySchemaAdapter';
import { tokens } from '@fluentui/react-theme';
import { tokens, typographyStyles } from '@fluentui/react-theme';
import { ThemeContext_unstable as V9ThemeContext } from '@fluentui/react-shared-contexts';
import { Theme, webLightTheme } from '@fluentui/tokens';
import * as d3Color from 'd3-color';
Expand Down Expand Up @@ -40,6 +40,7 @@ import {
transformPlotlyJsonToGanttChartProps,
transformPlotlyJsonToAnnotationChartProps,
} from './PlotlySchemaAdapter';
import { getChartTitleInlineStyles } from '../../utilities/index';
import type { ColorwayType } from './PlotlyColorAdapter';
import { AnnotationOnlyChart } from '../AnnotationOnlyChart/AnnotationOnlyChart';
import { DonutChart } from '../DonutChart/index';
Expand Down Expand Up @@ -537,9 +538,23 @@ export const DeclarativeChart: React.FunctionComponent<DeclarativeChartProps> =
);

type ChartType = keyof ChartTypeMap;

const titleObj = plotlyInputWithValidData.layout?.title;
const chartTitle = typeof titleObj === 'string' ? titleObj : titleObj?.text ?? '';
const titleFont = typeof titleObj === 'object' ? titleObj?.font : undefined;

const titleStyle: React.CSSProperties = {
...typographyStyles.caption1,
color: tokens.colorNeutralForeground1,
textAlign: 'center',
marginBottom: tokens.spacingVerticalS,
...getChartTitleInlineStyles(titleFont),
};

// map through the grouped traces and render the appropriate chart
return (
<>
{isMultiPlot.current && chartTitle && <div style={titleStyle}>{chartTitle}</div>}
<div
style={{
display: 'grid',
Expand Down Expand Up @@ -581,8 +596,6 @@ export const DeclarativeChart: React.FunctionComponent<DeclarativeChartProps> =
? {}
: {
...interactiveCommonProps,
xAxisAnnotation: cellProperties?.xAnnotation,
yAxisAnnotation: cellProperties?.yAnnotation,
}
) as Partial<ReturnType<typeof transformer>>;

Expand All @@ -592,8 +605,8 @@ export const DeclarativeChart: React.FunctionComponent<DeclarativeChartProps> =
[transformedInput, isMultiPlot.current, colorMap, colorwayType, isDarkTheme],
{
...resolvedCommonProps,
xAxisAnnotation: cellProperties?.xAnnotation,
yAxisAnnotation: cellProperties?.yAnnotation,
...(cellProperties?.xAnnotation && { xAxisAnnotation: cellProperties.xAnnotation }),
...(cellProperties?.yAnnotation && { yAxisAnnotation: cellProperties.yAnnotation }),
componentRef: (ref: Chart | null) => {
chartRefs.current[chartIdx] = {
compRef: ref,
Expand Down
Loading
Loading