Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support custom locale in date axis #24753

Merged
merged 12 commits into from
Sep 14, 2022
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": "patch",
"comment": "Add support for custom locale for date axis",
"packageName": "@fluentui/react-charting",
"email": "atishay.jain@microsoft.com",
"dependentChangeType": "patch"
}
88 changes: 84 additions & 4 deletions packages/react-charting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,6 @@ To import charting components:
import { ComponentName } from '@fluentui/react-charting/lib/ComponentName';
```

**Technical Guide**

Technical information about chart components is available at [Technical details](./TechnicalDetails.md)

**Contributing**

Refer the main fluentui [wiki](https://github.com/microsoft/fluentui/wiki) for detailed instructions on setup and contributing to the package.
Expand All @@ -56,3 +52,87 @@ You could also create issues under the [charting](https://github.com/microsoft/f
**Coding Guidelines**

Refer fluent [Coding guidelines](https://github.com/microsoft/fluentui/wiki/Coding-Style)

# Technical details

**Overview**

This document describes different chart components in detail.

This can be used as a guide to use the charts and contribute new functionalities or improvements to the library.

**Components**

The charting components are built using following building blocks.

- Cartesian Charts.

- Charts built using cartesian coordinate system (two axes - x axis perpendicular to y axis) are called cartesian charts. Majority of the chart in the library are cartesian charts. Some charts like horizontal chart, donut chart, sankey and tree charts are non cartesian charts.

- Legends.

- A legend contains a list of the variables appearing in the chart and an example of their appearance. This information allows the data from each variable to be identified in the chart.

- Hover Callouts.

- Whenever the mouse is hovered over a datapoint, a callout is shown representing the details of data for that point. For a stacked chart, the hover callout can represent the data for all the points for the same X coordinate.

- Axes.

- Our charts currently support cartesian axes. Different charts support different type of axes - numerical axis, date or time series axis, string or categorical axis. Detals about supported axes can be found in readme for each chart.

- Axes support for different charts

| Chart | Numeric Axis | Date Axis | String Axis |
| -------------------------- | ------------ | --------- | ----------- |
| Line Chart | Yes | Yes | No |
| Area Chart | Yes | Yes | No |
| Vertical Bar Chart | Yes | No | Yes |
| Vertical Stacked Bar Chart | Yes | No | Yes |
| Grouped Vertical Bar Chart | No | No | Yes |
| Heatmap Chart | Yes | Yes | Yes |
| Horizontal Bar Chart | -- | -- | -- |
| Donut Chart | -- | -- | -- |
| Sankey Chart | -- | -- | -- |
| Tree Chart | -- | -- | -- |
| Sparkline Chart | -- | -- | -- |

- Axis localization
The axes support 2 ways of localization.
1. Javascript provided inbuilt localization for numeric and date axis. Specify the culture and dateLocalizeOptions for date axis to define target localization. Refer the [javascript localization guide](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString) for usage.
2. Custom locale definition: The consumer of the library can specify a custom locale definition as supported by d3 (like [this](https://github.com/d3/d3-time-format/blob/main/locale/en-US.json)). The date axis will use the date range and the multiformat specified in the definition to determine the correct format to show in the ticks. For example - If the date range is in days then the axis will show hourly ticks. If the date range spans across months then the axis will show months in tick labels and so on.
Specify the custom locale definition in the timeFormatLocale prop.
Refer to the Custom Locale Date Axis example in line chart for sample usage.

- Event annotations (Available in line charts).

- Data can be annotated using vertical lines representing the events of interest. See [line chart with events](https://fluentuipr.z22.web.core.windows.net/heads/master/react-charting/demo/index.html#/examples/linechart#Variants) for example.

- Typography.

- Our font classes represent the type ramp for the fluent design language. Each base class sets a default size, weight, and color.

- Colors

- The charts are designed using the accessible color palette defined for the fluent design system.

- Themes

- The library supports light and dark mode out of box. In addition, consumers can define their own themese as detailed [here](https://github.com/microsoft/fluentui/wiki/Theming)

- Accessibility.

- Our charts have elaborate accessibility support. The charts are WCAG 2.1 MAS C compliant for accessibility.
Consumers can define their own aria labels for each point by setting the `xAxisCalloutAccessibilityData` and `callOutAccessibilityData` properties.

- RTL Support

- The charts support RTL languages wherever applicable.

- Component Styling

- [This article](https://github.com/microsoft/fluentui/wiki/Component-Styling) talks about the styling approach followed within charting library.

- Details about ticks.
- Tick values are applicable only for date axis. Doesn't work for string or numeric axis.
Tickcount works for numeric and date axis. Doesn't work for string (scaleBand) axis.
80 changes: 0 additions & 80 deletions packages/react-charting/TechnicalDetails.md

This file was deleted.

2 changes: 2 additions & 0 deletions packages/react-charting/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"@types/d3-selection": "1.4.1",
"@types/d3-shape": "^1.2.3",
"@types/d3-time-format": "^2.1.0",
"@types/d3-time": "^1.1.0",
"@fluentui/set-version": "^8.2.2",
"d3-array": "1.2.1",
"d3-axis": "1.0.8",
Expand All @@ -55,6 +56,7 @@
"d3-selection": "1.3.0",
"d3-shape": "^1.2.0",
"d3-time-format": "^2.1.3",
"d3-time": "^1.1.0",
"tslib": "^2.1.0"
},
"peerDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
svgProps,
culture,
dateLocalizeOptions,
timeFormatLocale,
} = this.props;
if (this.props.parentRef) {
this._fitParentContainer();
Expand Down Expand Up @@ -197,7 +198,7 @@ export class CartesianChartBase extends React.Component<IModifiedCartesianChartP
xScale = createNumericXAxis(XAxisParams, culture);
break;
case XAxisTypes.DateAxis:
xScale = createDateXAxis(XAxisParams, this.props.tickParams!, culture, dateLocalizeOptions);
xScale = createDateXAxis(XAxisParams, this.props.tickParams!, culture, dateLocalizeOptions, timeFormatLocale);
break;
case XAxisTypes.StringAxis:
xScale = createStringXAxis(XAxisParams, this.props.tickParams!, this.props.datasetForXAxisDomain!, culture);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ICalloutProps } from '@fluentui/react/lib/Callout';
import { ILegendsProps } from '../Legends/index';
import { IAccessibilityProps, IMargins } from '../../types/index';
import { ChartTypes, IChartHoverCardProps, XAxisTypes, YAxisType } from '../../utilities/index';
import * as d3TimeFormat from 'd3-time-format';

export interface ICartesianChartStyleProps {
/**
Expand Down Expand Up @@ -328,6 +329,11 @@ export interface ICartesianChartProps {
*/
dateLocalizeOptions?: Intl.DateTimeFormatOptions;

/**
* The prop used to define a custom locale for the date time format.
*/
timeFormatLocale?: d3TimeFormat.TimeLocaleDefinition;

/**
* Call to provide customized styling that will layer on top of the variant rules.
*/
Expand Down
43 changes: 43 additions & 0 deletions packages/react-charting/src/utilities/utilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@ import { scaleLinear as d3ScaleLinear, scaleTime as d3ScaleTime, scaleBand as d3
import { select as d3Select, event as d3Event, selectAll as d3SelectAll } from 'd3-selection';
import { format as d3Format } from 'd3-format';
import * as d3TimeFormat from 'd3-time-format';
import {
timeSecond as d3TimeSecond,
timeMinute as d3TimeMinute,
timeHour as d3TimeHour,
timeDay as d3TimeDay,
timeMonth as d3TimeMonth,
timeWeek as d3TimeWeek,
timeYear as d3TimeYear,
} from 'd3-time';
import {
IAccessibilityProps,
IEventsAnnotationProps,
Expand Down Expand Up @@ -152,6 +161,33 @@ export function createNumericXAxis(xAxisParams: IXAxisParams, culture?: string)
return xAxisScale;
}

function multiFormat(date: Date, locale: d3TimeFormat.TimeLocaleObject) {
const formatMillisecond = locale.format('.%L');
const formatSecond = locale.format(':%S');
const formatMinute = locale.format('%I:%M');
const formatHour = locale.format('%I %p');
const formatDay = locale.format('%a %d');
const formatWeek = locale.format('%b %d');
const formatMonth = locale.format('%B');
const formatYear = locale.format('%Y');

return (d3TimeSecond(date) < date
? formatMillisecond
: d3TimeMinute(date) < date
? formatSecond
: d3TimeHour(date) < date
? formatMinute
: d3TimeDay(date) < date
? formatHour
: d3TimeMonth(date) < date
? d3TimeWeek(date) < date
? formatDay
: formatWeek
: d3TimeYear(date) < date
? formatMonth
: formatYear)(date);
}

/**
* Creating Date x axis of the Chart
* @export
Expand All @@ -163,6 +199,7 @@ export function createDateXAxis(
tickParams: ITickParams,
culture?: string,
options?: Intl.DateTimeFormatOptions,
timeFormatLocale?: d3TimeFormat.TimeLocaleDefinition,
) {
const { domainNRangeValues, xAxisElement, tickPadding = 6, xAxistickSize = 6, xAxisCount = 6 } = xAxisParams;
const xAxisScale = d3ScaleTime()
Expand All @@ -174,6 +211,12 @@ export function createDateXAxis(
xAxis.tickFormat((domainValue: Date, _index: number) => {
return domainValue.toLocaleString(culture, options);
});
} else if (timeFormatLocale) {
const locale: d3TimeFormat.TimeLocaleObject = d3TimeFormat.timeFormatLocale(timeFormatLocale!);

xAxis.tickFormat((domainValue: Date, _index: number) => {
return multiFormat(domainValue, locale);
});
}

tickParams.tickValues ? xAxis.tickValues(tickParams.tickValues) : '';
Expand Down
4 changes: 3 additions & 1 deletion packages/react-examples/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
"@fluentui/eslint-plugin": "*",
"@fluentui/scripts": "^1.0.0",
"@fluentui/storybook": "^1.0.0",
"@types/d3-format": "^1.3.1"
"@types/d3-format": "^1.3.1",
"@types/d3-fetch": "^3.0.1"
},
"dependencies": {
"@fluentui/azure-themes": "^8.4.34",
Expand All @@ -44,6 +45,7 @@
"@fluentui/theme-samples": "^8.6.34",
"@fluentui/utilities": "^8.13.1",
"@microsoft/load-themed-styles": "^1.10.26",
"d3-fetch": "3.0.1",
"d3-format": "^1.4.4",
"react": "17.0.2",
"react-dom": "17.0.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,23 @@ export class AreaChart extends React.Component<IComponentDemoPageProps, {}> {
and <code>callOutAccessibilityData</code> to configure x axis and y axis accessibility messages
respectively.
</p>
<h4>Date Axis localization</h4>
<p>
The axes support 2 ways of localization. <br />
1. Javascript provided inbuilt localization for numeric and date axis. Specify the culture and
dateLocalizeOptions for date axis to define target localization. Refer the
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString">
Javascript localization guide
</a>
for usage. <br />
2. Custom locale definition: The consumer of the library can specify a custom locale definition as
supported by d3 <a href="https://github.com/d3/d3-time-format/blob/main/locale/en-US.json">like this</a>.
The date axis will use the date range and the multiformat specified in the definition to determine the
correct labels to show in the ticks. For example - If the date range is in days then the axis will show
hourly ticks. If the date range spans across months then the axis will show months in tick labels and so
on. Specify the custom locale definition in the <code>timeFormatLocale</code> prop. Refer to the Custom
Locale Date Axis example in line chart for sample usage.
</p>
</div>
}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,23 @@ export class HeatMapChart extends React.Component<IComponentDemoPageProps, {}> {
<p>
For string y axis use: <code>yAxisStringFormatter</code>
</p>
<h4>Date Axis localization</h4>
<p>
The axes support 2 ways of localization. <br />
1. Javascript provided inbuilt localization for numeric and date axis. Specify the culture and
dateLocalizeOptions for date axis to define target localization. Refer the
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleDateString">
Javascript localization guide
</a>
for usage. <br />
2. Custom locale definition: The consumer of the library can specify a custom locale definition as
supported by d3 <a href="https://github.com/d3/d3-time-format/blob/main/locale/en-US.json">like this</a>.
The date axis will use the date range and the multiformat specified in the definition to determine the
correct labels to show in the ticks. For example - If the date range is in days then the axis will show
hourly ticks. If the date range spans across months then the axis will show months in tick labels and so
on. Specify the custom locale definition in the <code>timeFormatLocale</code> prop. Refer to the Custom
Locale Date Axis example in line chart for sample usage.
</p>
</div>
}
/>
Expand Down
Loading