Skip to content

Commit

Permalink
feat(data-viz): highcharts a11y (#4053)
Browse files Browse the repository at this point in the history
* feat(data-viz): initial modules impl

* chore(website): fix typos in variables

* fix(docs): ignore case sensitivity on getFeature

* feat(docs-viz): add documentation

* chore(data-viz): changeset

* chore(docs): typos

* chore(data-viz): disable chromatic checks and add aria desc

* chore(data-viz): changeset

* chore(data-viz): test update

* chore(pr): linting issues

* chore(pr): address comments

* Update packages/paste-website/src/pages/foundations/data-visualization/index.mdx

Co-authored-by: Sarah <[email protected]>

* chore(pr): address comments

---------

Co-authored-by: Sarah <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Sep 4, 2024
1 parent 26e425a commit b20a3a1
Show file tree
Hide file tree
Showing 21 changed files with 214 additions and 66 deletions.
6 changes: 6 additions & 0 deletions .changeset/tiny-colts-attack.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@twilio-paste/data-visualization-library": minor
"@twilio-paste/core": minor
---

[Data Visualization]: added a new helper function, applyPasteHighchartsModules, that applies any number of modules to Highcharts setting accesibility required.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

exports[`usePasteHighChartsTheme hook should return a deepmerged options object when options are passed 1`] = `
Object {
"accessibility": Object {
"description": "This chart shows the solar employment growth by sector from 2010 to 2016.",
},
"chart": Object {
"backgroundColor": "rgb(255, 255, 255)",
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { applyPasteHighchartsModules } from "../src";

type MockHighcarts = {
modules: Set<string>;
};

let mockHighcarts: MockHighcarts;

const a11yModule = (highcharts: MockHighcarts): void => {
highcharts.modules.add("accessibility");
};

const exportingModule = (highcharts: MockHighcarts): void => {
highcharts.modules.add("exporting");
};

const sankeyModule = (highcharts: MockHighcarts): void => {
highcharts.modules.add("sankeyModule");
};

describe("applyPasteHighchartsModules hook", () => {
beforeEach(() => {
mockHighcarts = {
modules: new Set(),
};
});

it("should fail when Highcarts is not present", () => {
expect(applyPasteHighchartsModules).toThrow(
"[applyPasteHighchartsModules]: Must provide highcharts into this function.",
);
});

it("should apply modules", () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
applyPasteHighchartsModules(mockHighcarts, a11yModule, exportingModule, sankeyModule);
expect(mockHighcarts.modules).toEqual(new Set(["accessibility", "exporting", "sankeyModule"]));
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import Highcharts from "highcharts";

/**
* A hook to apply any Highcharts modules iwth accessibility being mandatory.
*/
export const applyPasteHighchartsModules = (
highcharts: typeof Highcharts,
accessibilityModule: (highcharts: typeof Highcharts) => void,
...rest: Array<(highcharts: typeof Highcharts) => void>
): void => {
if (highcharts === undefined) {
throw new Error("[applyPasteHighchartsModules]: Must provide highcharts into this function.");
}

if (accessibilityModule === undefined) {
throw new Error(
'[applyPasteHighchartsModules]: Must provide accessibility module into this function. You can do this using `import HighchartsAccessibility Module from "highcharts/modules/accessibility"`',
);
}

accessibilityModule(highcharts);
rest.forEach((module) => module(highcharts));
};
1 change: 1 addition & 0 deletions packages/paste-libraries/data-visualization/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export { usePasteHighchartsTheme } from "./usePasteHighchartsTheme";
export { applyPasteHighchartsModules } from "./applyPasteHighchartsModules";
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import { Stack } from "@twilio-paste/stack";
/* eslint-disable import/no-extraneous-dependencies */
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import HighchartsAccessibilityModule from "highcharts/modules/accessibility";
import * as React from "react";
/* eslint-enable */

import { usePasteHighchartsTheme } from "../src";
import { applyPasteHighchartsModules, usePasteHighchartsTheme } from "../src";
import { basicAreaChartOptions } from "./options/basicAreaChartOptions";
import { columnChartOptions } from "./options/columnChartOptions";
import { lineChartOptions } from "./options/lineChartOptions";
Expand All @@ -19,12 +20,28 @@ export default {
title: "Libraries/data-visualization",
parameters: {
chromatic: { disableSnapshot: true },
a11y: {
// no need to a11y check composition of a11y checked components
disable: true,
},
},
} as Meta;

export const LineChart: StoryFn = () => {
const themedLineChartOptions = usePasteHighchartsTheme(lineChartOptions);

return (
<Stack orientation="vertical" spacing="space100">
<HighchartsReact highcharts={Highcharts} options={themedLineChartOptions} key="chart1" />
<HighchartsReact highcharts={Highcharts} options={lineChartOptions} key="chart2" />
</Stack>
);
};

export const LineChartWithAccessibility: StoryFn = () => {
applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule);
const themedLineChartOptions = usePasteHighchartsTheme(lineChartOptions);

return (
<Stack orientation="vertical" spacing="space100">
<HighchartsReact highcharts={Highcharts} options={themedLineChartOptions} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import type Highcharts from "highcharts";

export const lineChartOptions: Highcharts.Options = {
accessibility: {
description: "This chart shows the solar employment growth by sector from 2010 to 2016.",
},
title: {
text: "Solar Employment Growth by Sector, 2010-2016",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ export const LineChartCaption = (): JSX.Element => (
export const LineChartOptions = {
title: { text: "Solar Employment Growth by Sector, 2010-2016" },
subtitle: { text: "Source: thesolarfoundation.com" },
accessibility: {
description: "This chart shows the solar employment growth by sector from 2010 to 2016.",
},
chart: {
// this controls animation of updates, to disable animation on initial render you have to disable animation on the series
animation: !inCypress(),
Expand Down Expand Up @@ -100,6 +103,7 @@ export const LineChartOptions = {

export const LineChartExample = `
const LineChartExample = () => {
applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule);
const themedLineChartOptions = usePasteHighchartsTheme(LineChartOptions);
return <HighchartsReact highcharts={Highcharts} options={themedLineChartOptions} />;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const NormalizedComponentHeader: React.FC<React.PropsWithChildren<Normali
githubUrl,
storybookUrl,
Feature,
shoudShowInPageNav = true,
shouldShowInPageNav = true,
} = merge(normalizedData, props);

const componentPageBasePath = getPackagePath(categoryRoute, Feature);
Expand All @@ -64,7 +64,7 @@ export const NormalizedComponentHeader: React.FC<React.PropsWithChildren<Normali
githubUrl={githubUrl}
storybookUrl={storybookUrl}
>
{shoudShowInPageNav ? (
{shouldShowInPageNav ? (
<PageHeaderInPageNavigation>
<InPageNavigation aria-label="Component page navigation">
<Link href={componentPageNavLinks.GUIDELINES} legacyBehavior passHref>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
export const meta = {
title: 'Data visualization library',
package: '@twilio-paste/data-visualization-library',
description: 'A library that helps theme data visualizations with Paste tokens.',
slug: '/core/libraries/data-visualization/',
title: "Data visualization library",
package: "@twilio-paste/data-visualization-library",
description: "A library that helps theme data visualizations with Paste tokens.",
slug: "/core/libraries/data-visualization/",
};

import {PageHeaderSeparator} from '@twilio-paste/page-header';
import {Separator} from '@twilio-paste/separator';
import DefaultLayout from '../../../../layouts/DefaultLayout';
import packageJson from '@twilio-paste/data-visualization-library/package.json';
import Changelog from '@twilio-paste/data-visualization-library/CHANGELOG.md';
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import {usePasteHighchartsTheme} from '@twilio-paste/data-visualization-library';
import {SidebarCategoryRoutes} from '../../../../constants';
import {getNavigationData} from '../../../../utils/api';
import { PageHeaderSeparator } from "@twilio-paste/page-header";
import { Separator } from "@twilio-paste/separator";
import DefaultLayout from "../../../../layouts/DefaultLayout";
import packageJson from "@twilio-paste/data-visualization-library/package.json";
import Changelog from "@twilio-paste/data-visualization-library/CHANGELOG.md";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import { usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library";
import { SidebarCategoryRoutes } from "../../../../constants";
import { getNavigationData } from "../../../../utils/api";

export default DefaultLayout;

Expand All @@ -40,7 +40,7 @@ export const getStaticProps = async () => {
description={props.data.description}
>
<PageHeaderSeparator>
<Separator orientation="horizontal"/>
<Separator orientation="horizontal" />
</PageHeaderSeparator>
</GenericHeader>

Expand All @@ -63,32 +63,32 @@ yarn add @twilio-paste/data-visualization-library - or - yarn add @twilio-paste/
This is a React Hook to take a Highcharts config and add Paste colors and fonts.

```jsx
import Highcharts from 'highcharts';
import HighchartsReact from 'highcharts-react-official';
import {usePasteHighchartsTheme} from '@twilio-paste/data-visualization-library';
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import { usePasteHighchartsTheme } from "@twilio-paste/data-visualization-library";

const LineChartOptions = {
title: {text: 'Solar Employment Growth by Sector, 2010-2016'},
subtitle: {text: 'Source: thesolarfoundation.com'},
title: { text: "Solar Employment Growth by Sector, 2010-2016" },
subtitle: { text: "Source: thesolarfoundation.com" },
series: [
{
name: 'Installation',
name: "Installation",
data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175],
},
{
name: 'Manufacturing',
name: "Manufacturing",
data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434],
},
{
name: 'Sales & Distribution',
name: "Sales & Distribution",
data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387],
},
{
name: 'Project Development',
name: "Project Development",
data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227],
},
{
name: 'Other',
name: "Other",
data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111],
},
],
Expand All @@ -109,10 +109,29 @@ The hook adds [the following styles](https://github.com/twilio-labs/paste/blob/4

To learn more about the configurations available, check out [the Highcharts API documentation](https://api.highcharts.com/highcharts/).

### applyPasteHighchartsModules

This is a helper function to initiate Highcharts modules that are not included by default. The [accessibility](https://www.highcharts.com/docs/accessibility/accessibility-module) module is a mandatory module, but you can pass as many other modules as you want. This hook should be used at the component level where the Highcharts namespace is passed to HighchartsReact.

```jsx
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
import HighchartsAccessibilityModule from "highcharts/modules/accessibility";
import HighchartsExportingModule from "highcharts/modules/exporting";
import { applyPasteHighchartsModules } from "@twilio-paste/data-visualization-library";

applyPasteHighchartsModules(Highcharts, HighchartsAccessibilityModule, HighchartsExportingModule);

const LineChartExample = () => {
return <HighchartsReact highcharts={Highcharts} />;
};
```

<ChangelogRevealer>
<Changelog />
</ChangelogRevealer>

</content>

</contentwrapper>
```
Loading

0 comments on commit b20a3a1

Please sign in to comment.