Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/sophiamersmann/friendly-charts
Screen reader friendly charts with minimal effort
https://github.com/sophiamersmann/friendly-charts
a11y charts keyboard-accesible screen-reader
Last synced: 24 days ago
JSON representation
Screen reader friendly charts with minimal effort
- Host: GitHub
- URL: https://github.com/sophiamersmann/friendly-charts
- Owner: sophiamersmann
- License: mit
- Created: 2022-07-21T18:26:22.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2023-02-09T08:48:35.000Z (over 1 year ago)
- Last Synced: 2024-10-02T23:14:06.081Z (about 1 month ago)
- Topics: a11y, charts, keyboard-accesible, screen-reader
- Language: TypeScript
- Homepage:
- Size: 728 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Friendly Charts
Screen reader friendly charts with minimal effort
## Install
```bash
npm install friendly-charts
```> **Warning**
>
> Under construction## Features
You ✨ bring your own chart ✨ and Friendly Charts will:
- expose a chart description to screen readers
- make your chart keyboard accessible, allowing screen reader users to explore charts via keyboard interactionsFriendly Charts exports a number of functions that expect a DOM element as input. Friendly Charts is framework agnostic but in Svelte and Solid, for example, the exported functions can be applied as use directives/actions.
The interaction design for keyboard accessible charts is borrowed from [Visa Chart Components](https://developer.visa.com/pages/chart-components):
- _TAB_ to the chart area
- _ENTER_ to drill down a level
- _ESCAPE_ to drill up a level
- _LEFT_ and _RIGHT_ arrows to move between sibling elements
- _UP_ and _DOWN_ arrows to move across groupshttps://user-images.githubusercontent.com/12461810/191855514-5c5db343-8b8c-48e2-8829-bf7314938def.mov
## Example
To make a chart friendly, apply the `chart` function to a container element, providing a chart title, subtitle and description. To make the chart keyboard accessible, use the `axis`, `symbol` and `group` functions to outline the chart's structure and provide accessible names. Friendly charts will then wire up the necessary focus and event management to let a screen reader user navigate the chart via keyboard interactions. For example, in Svelte:
```svelte
import { chart } from 'friendly-charts';
import locale from 'friendly-charts/locale/en-US';const data = [
{ category: "A", value: 82 },
{ category: "B", value: 50 },
{ category: "C", value: 10 }
];
Chart title
Chart subtitle
``````svelte
import { axis } from 'friendly-charts';
{#each [0, 20, 40, 60, 80] as tick (tick)}
{tick}
{/each}```
```svelte
import { symbol } from 'friendly-charts';
export let data;
{#each data as d, i (d.category)}
{d.category}
{/each}```
CodeSandbox: https://codesandbox.io/s/friendly-tiny-bar-chart-10weeu?file=/App.svelte
## Documentation
Exported are:
- `chart`: exposes a chart description and makes the chart keyboard accessible
- `axis`: declares an axis
- `symbol`: declares a symbol (e.g. a single bar)
- `group`: declares a group of symbols (e.g. bars of the same category)
- `focus`: custom focus ring to highlight active elements on navigation (only needed to override default styles)### `chart(node, options)`
_Exposes a chart description and makes the chart keyboard accessible_
**Examples:**
```js
import { chart } from 'friendly-charts';
import locale from 'friendly-charts/locale/en-US.json';// minimal configuration
chart(node, {
title: 'Chart title',
type: 'bar',
locale,
});// .title and .subtitle are selectors that point to elements within the chart container
chart(node, { title: '.title', subtitle: '.subtitle', type: 'bar', locale });// debug mode
chart(node, {
title: 'Chart title',
subtitle: 'Chart subtitle',
type: 'bar',
locale,
debug: true,
});
```**Options:**
- `title` **(required)**: chart title, either the title itself or a selector that points to an element within the chart container
- `type` (**required**; `'line'`, `'bar'`, `'scatter'`, `'slope'` or `'area'`): chart type
- `locale` **(required)**: locale, usually imported from Friendly Charts, but you can bring your own
- `subtitle`: chart subtitle, either the subtitle itself or a selector that points to an element within the chart container
- `summary`: brief summary of the chart, either the summary itself or a selector that points to an element within the chart container
- `purpose`: an explanation of the chart's purpose, either the explanation itself or a selector that points to an element within the chart container
- `description`: long description of the chart, either the description itself or a selector that points to an element within the chart container
- `axes`: list of axis descriptions (see Section [axis](#axisnode-options)), only needed if an axis is not visually present in the chart
- `debug` (default: `false`): display an overlay that shows what a screen reader would announce on interaction with the chart### `axis(node, options)`
_Declares an axis_
**Examples:**
```js
import { axis } from 'friendly-charts';// minimal configuration
axis(node, { label: 'Axis label' });// .label is a selector that points to a descendant of `node`
axis(node, { label: '.label' });// specify a direction
axis(node, { label: 'Axis label', direction: 'x' });// infer ticks from the DOM by specifying a selector (by default, this is a continuous axis)
axis(node, { label: 'Axis label', direction: 'y', ticks: '.tick text' });// set the axis to be categorical
axis(node, {
label: 'Axis label',
direction: 'x',
type: 'categorical',
ticks: '.tick text',
});// specify ticks manually
axis(node, { label: 'Axis label', direction: 'y', ticks: [0, 2, 4, 6] });
axis(node, {
label: 'Axis label',
direction: 'x',
type: 'categorical',
ticks: ['Spain', 'Italy', 'France'],
});
```**Options:**
- `label` **(required)**: axis label, either the label itself or a selector that points to a descendant of `node`
- `direction` (`'x'` or `'y'`): axis direction
- `type` (`'continuous'` or `'categorical'`; default: `'continuous'`): axis type
- `ticks`: either a list of ticks or a selector that points to the tick labels (must be descendants of `node`)### `symbol(node, options)`
_Declares a symbol (e.g. a single bar)_
**Examples:**
```js
import { symbol } from 'friendly-charts';// line
symbol(node, { label: 'Symbol label', type: 'line' });// bar
symbol(node, { label: 'Symbol label', type: 'bar' });// symbol contained within a group with id `some-unique-group-id`
// (only necessary if the symbol is not nested within that group)
symbol(node, {
label: 'Symbol label',
type: 'point',
parentId: 'some-unique-group-id',
});
```**Options:**
- `label` **(required)**: symbol label, either the label itself or a selector that points to the label element
- `type` (**required**; `'line'`, `'bar'`, `'point'` or `'area'`): symbol type
- `id`: symbol id (automatically generated if not given)
- `parentId`: id of the group that contains the symbol, only needed if the symbol is not a descendant of the group element### `group(node, options)`
_Declares a group of symbols (e.g. bars of the same category)_
**Examples:**
```js
import { group } from 'friendly-charts';// minimal configuration
group(node, { label: 'Group label' });// a group that also represents a symbol of type line (e.g. a line that contains the points it is made of)
group(node, {
label: 'Group label',
id: 'unique-group-id',
type: 'line',
});
```**Options:**
- `label` **(required)**: group label, either the label itself or a selector that points to a descendant of `node`
- `id`: group id (automatically generated if not given)
- `type` (`'line'`, `'bar'` or `'point'`): some groups also represent a symbol of some type (e.g. a line that contains the points it is made of)### `focus(node)`
_Focus ring to highlight active elements on navigation (only needed to override default styles)_
**Examples:**
```js
import { focus } from 'friendly-charts';// the given element will be used as focus ring
focus(node);
```