+
+ Press hto list commands
+
+ hhide commands
+
+
+ ←move backwards
+
+
+ →move forwards
+
+
+ ↑zoom in
+
+
+ ↓zoom out
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/website/tutorials/a11y/conclusion.mdx b/website/tutorials/a11y/conclusion.mdx
new file mode 100644
index 0000000000..d910e884f2
--- /dev/null
+++ b/website/tutorials/a11y/conclusion.mdx
@@ -0,0 +1,76 @@
+---
+sidebar_position: 4
+title: Conclusion
+pagination_title: Conclusion
+sidebar_label: Conclusion
+description: Conclusion to the accessibility tutorial
+keywords:
+ - a11y
+ - accessibility
+ - screenreaders
+ - keyboard
+ - assistive
+pagination_prev: a11y/readability
+pagination_next: null
+---
+
+# Conclusion
+
+This tutorial demonstrated a wide array of accessibility improvements that can
+be introduced to line charts, making them usable for a broader spectrum of
+users. The considerations and methods presented illustrate the importance of
+creating inclusive web applications.
+
+Among the discussed topics were:
+
+1. **Keyboard navigation:** The implementation of
+keyboard-only navigation on our chart, allowing for interaction exclusively
+through keystrokes.
+2. **ARIA roles and descriptive content:** The additions of ARIA
+labels, live regions, and the hiding of non-consequential elements to enhance
+the usefulness of assistive technologies and to communicate context better to
+all users.
+3. **High contrast and scalable font size:** The detection of the user's
+preference for higher contrast and the inclusion of customizable text sizes for
+better readability.
+
+The example provided has even more improvements not directly discussed during the
+the tutorial. One such enhancement is an informative tooltip that lists available
+commands, adding another helpful layer of user instruction.
+
+:::tip
+
+The complete example code provides further insights, and reviewing it is
+recommended for a comprehensive understanding of the accessibility improvements
+discussed in this tutorial.
+
+:::
+
+This tutorial aimed to foster a better understanding of these practices,
+promoting an inclusive web where applications are made with everyone in mind.
+Thank you for following along and continue putting accessibility at the
+forefront of your web development endeavors.
+
+## Complete example
+
+You can view the example in a new window, or download the source file below:
+
+
diff --git a/website/tutorials/a11y/intro.mdx b/website/tutorials/a11y/intro.mdx
new file mode 100644
index 0000000000..ef08a655d5
--- /dev/null
+++ b/website/tutorials/a11y/intro.mdx
@@ -0,0 +1,132 @@
+---
+sidebar_position: 0
+sidebar_label: Introduction
+pagination_title: Introduction
+title: Improving accessibility
+description:
+ This tutorial provides an introduction to making a Lightweight Charts™' chart
+ more accessible.
+keywords:
+ - a11y
+ - accessibility
+ - screenreaders
+ - keyboard
+ - assistive
+pagination_prev: null
+pagination_next: a11y/keyboard
+---
+
+# Improving accessibility
+
+## Introduction
+
+This tutorial introduces how to make charts with Lightweight Charts™ more
+accessible. Lightweight Charts™ does not have built-in accessibility attributes
+and behaviors. This gives you the flexibility to customize and implement them on
+your own, seamlessly integrating the charts into your site's existing
+accessibility policy.
+
+:::info
+
+The tutorial serves as a starting point and provides ideas
+for creating a fully accessible chart based on your users' needs. **It is not
+intended to be a comprehensive tutorial.**
+
+:::
+
+Graphical data representation, although visually appealing and informative, can
+sometimes pose challenges to individuals with varying abilities and needs. In
+line with the principles of inclusivity and universal design, we aim to
+demonstrate how to make your charts more accessible to a broader audience.
+
+## What we will be building
+
+Before we get started, let us have a look at what we will be building in this
+tutorial.
+
+
+
+
+
+
+## Topics to be covered
+
+The following topics will be covered within the tutorial:
+
+- **Enabling Keyboard Navigation:** Keyboard users predominantly interact with
+ web content using only their keyboard. We will guide you on setting up
+ keyboard navigation for our charts, thereby providing a seamless user
+ experience.
+- **Implementing ARIA (Accessible Rich Internet Applications) Suite:** We'll
+ delve into how to integrate ARIA attributes which aid in improving the access
+ and understanding of our charts for users with disabilities.
+- **Generating Descriptive Content for Charts:** Often, providing a textual
+ description for charts becomes invaluable for certain users, especially for
+ those using screen reading technology. We demonstrate how to automate this
+ process and facilitate a more comprehensive understanding of data being
+ represented.
+
+## Prerequisite knowledge
+
+To fully benefit from this guide, we assume that you are already familiar with:
+
+- Basic HTML structure and elements.
+- JavaScript fundamentals, especially event handling.
+- The basics of using the Lightweight Charts™ JavaScript library, including chart
+ creation and providing data.
+
+:::tip
+
+The tutorial will assume that you've already read the [Getting Started](/docs)
+section. Additionally it is recommended that you read the
+[Customization tutorial](/tutorials/customization/intro)
+
+:::
+
+## Terminology
+
+- **Accessibility:** The practice of making your websites usable by as many
+ people as possible, including individuals with disabilities or special needs.
+- **ARIA (Accessible Rich Internet Applications):** A set of attributes that
+ define ways to make web content and web applications more accessible to people
+ with disabilities.
+- **Assistive technologies:** Software or devices that people with disabilities
+ use to improve interaction with the web, such as screen readers, alternative
+ keyboards, or speech recognition software.
+- **Keyboard Navigation:** The ability to navigate through a website using only
+ the keyboard, which is important for those who cannot use a mouse.
+- **High Contrast Mode:** A version of a webpage that has been designed to be
+ easy on the eyes and readable, typically with black text on a white
+ background, used by people with visual impairments.
+- **Media Queries:** A CSS technique used to apply different style rules to
+ different devices based on their characteristics, such as color scheme
+ preference (such as high contrast), display type, height, width, etc.
+- **Screen Reader:** A type of software that interprets and reads aloud the
+ information displayed on a screen, such as text, images, buttons, and menus.
+ It's primarily used by people with visual impairments or those who have
+ difficulties reading text on a screen. Examples include JAWS, NVDA, and
+ VoiceOver.
diff --git a/website/tutorials/a11y/keyboard.mdx b/website/tutorials/a11y/keyboard.mdx
new file mode 100644
index 0000000000..57b19e77c5
--- /dev/null
+++ b/website/tutorials/a11y/keyboard.mdx
@@ -0,0 +1,160 @@
+---
+sidebar_position: 1
+sidebar_label: Keyboard navigation
+pagination_title: Keyboard navigation
+title: Keyboard navigation
+description: In this section we will add keyboard navigation to the chart.
+keywords:
+ - a11y
+ - accessibility
+ - screenreaders
+ - keyboard
+ - assistive
+pagination_prev: a11y/intro
+pagination_next: a11y/screenreader
+---
+
+# Keyboard navigation
+
+## Purpose of keyboard navigation
+
+One cornerstone of web accessibility is ensuring that sites and applications are
+fully operable via keyboard alone. This navigation method benefits a wide range
+of users, especially those who are unable to use a mouse or have visual
+impairments.
+
+Screen readers and other assistive technologies rely heavily on keyboard
+interaction, and some users choose this method due to an acquired skill set or
+personal preference. By including keyboard navigation in our charts, we make the
+tool more accessible and user-friendly, living up to the principles of inclusive
+design.
+
+## Implementing keyboard actions with Lightweight Charts™
+
+The Lightweight Charts™ API provides numerous methods that enable handling chart
+actions programmatically, making it possible to tie these actions to keyboard
+events.
+
+Here's a walk-through of how to add keyboard navigation to the chart.
+
+### Setting focus on the chart
+
+Firstly, we must ensure the chart is programmatically focusable for keyboard
+interaction. We can achieve this by placing a `tabindex` attribute to the
+chart's container div:
+
+```html
+
+```
+
+This can also be achieved via JavaScript:
+
+```js
+const containerEl = chart.chartElement().parentElement;
+containerEl.tabIndex = 0;
+```
+
+### Adding event listener for keyboard actions
+
+Following that, we will tie specific chart interactions to keypress events using
+JavaScript's `addEventListener` method. This will allow us to control the chart
+using specific keystrokes:
+
+```js
+const chartContainer = document.getElementById('chart');
+chartContainer.addEventListener('keydown', event => {
+ switch (event.key) {
+ case 'ArrowLeft':
+ // Action for ArrowLeft key
+ break;
+ case 'ArrowRight':
+ // Action for ArrowRight key
+ break;
+ // ... more cases
+ }
+});
+```
+
+The `addEventListener` function lets us listen to `keydown` events that occur
+when the user presses a key.
+
+### Utilizing Lightweight Chart's API for actions
+
+Next, for each case, we use Lightweight Chart's API for desired actions.
+
+Let's assume we want the left arrow key to scroll the chart to the left, and the
+right arrow key to scroll it to the right:
+
+```js
+function shiftChart(diff) {
+ const currentPos = chart.timeScale().scrollPosition();
+ chart.timeScale().scrollToPosition(currentPos + diff, false);
+}
+
+chartContainer.addEventListener('keydown', event => {
+ switch (event.key) {
+ case 'ArrowLeft':
+ shiftChart(-10);
+ break;
+ case 'ArrowRight':
+ shiftChart(10);
+ break;
+ }
+});
+```
+
+In the above JavaScript code, the `timeScale().scrollToPosition()` method from
+Lightweight Charts™ API is used inside the event listener to scroll the chart
+whenever the left or right arrow key is pressed.
+
+Additionally, we can assign the up and down arrow keys to adjust the zoom level
+of the chart:
+
+```js
+function scaleChart(pct, zoomIn) {
+ const currentRange = chart.timeScale().getVisibleLogicalRange();
+ if (currentRange) {
+ const bars = currentRange.to - currentRange.from;
+ const direction = zoomIn ? -1 : 1;
+ const newRangeBars = bars * pct * direction + bars;
+ chart.timeScale().setVisibleLogicalRange({
+ to: currentRange.to,
+ from: currentRange.to - newRangeBars,
+ });
+ }
+}
+
+chartContainer.addEventListener('keydown', event => {
+ switch (event.key) {
+ // ...
+ case 'ArrowUp':
+ scaleChart(1 / 8, true);
+ break;
+ case 'ArrowDown':
+ scaleChart(1 / 8, false);
+ break;
+ }
+});
+```
+
+We are scaling the chart by adjusting the `visibleLogicalRange` instead of
+changing the `barSpacing` option on the time scale. In this example, we are
+keeping the right data point fixed when zooming in or out by retaining the `to`
+value and only modifying the `from` value.
+
+---
+
+This keyboard navigation inclusion makes the chart's underlying data more
+accessible to a wider audience, ensuring a diverse user base can fully interact
+with the chart's functions.
+
+:::tip
+
+Note that more keyboard actions can be added according to
+project-specific requirements, thereby further enhancing the navigation controls
+and accessibility.
+
+:::
+
+In the next section, we'll continue enhancing our accessible charts by
+integrating ARIA (Accessible Rich Internet Applications) roles and properties and generating descriptive content.
diff --git a/website/tutorials/a11y/readability.mdx b/website/tutorials/a11y/readability.mdx
new file mode 100644
index 0000000000..1302c4bbe5
--- /dev/null
+++ b/website/tutorials/a11y/readability.mdx
@@ -0,0 +1,141 @@
+---
+sidebar_position: 3
+sidebar_label: Readability
+pagination_title: Readability
+title: Readability
+description: Improving the readability of the chart for visually impaired users.
+keywords:
+ - a11y
+ - accessibility
+ - screenreaders
+ - keyboard
+ - assistive
+pagination_prev: a11y/screenreader
+pagination_next: a11y/conclusion
+---
+
+## High contrast and scalable font size
+
+Ensuring accessibility in web development means accommodating various user
+preferences and physical abilities. High contrast mode and scalable font size
+are two such distinct features that have been included in our chart, catering to
+diverse user needs.
+
+### High contrast mode
+
+Certain users with specific visual impairments may struggle to distinguish
+between colors or interpret text and image details in low contrast. For these
+users, a high-contrast mode can be immensely helpful.
+
+In our chart application, we leverage the built-in browser feature
+`window.matchMedia()` to ascertain if the user has indicated a preference for
+higher contrast in their system settings.
+
+Here's how we determine if the user prefers a high-contrast mode:
+
+```js
+// Check if user prefers high contrast mode
+function checkHighContrast() {
+ // Use window.matchMedia to check 'prefers-contrast' media feature
+ const highContrast = window.matchMedia('(prefers-contrast: high)').matches;
+ return highContrast; // Returns true if high contrast is enabled, false otherwise
+}
+
+// Subscribe to changes
+const highContrastMediaQuery = window.matchMedia('(prefers-contrast: high)');
+highContrastMediaQuery.addListener(() => {
+ setHighContrast(highContrastMediaQuery.matches);
+});
+```
+
+A `setHighContrast` function could be implemented as follows:
+
+```js
+const seriesBaseContrastSettings = {
+ color: 'rgb(41, 98, 255)',
+ lineWidth: 2,
+};
+const chartBaseContrastSettings = {
+ layout: {
+ textColor: '#191919',
+ },
+ grid: {
+ vertLines: {
+ color: '#D6DCDE',
+ },
+ horzLines: {
+ color: '#D6DCDE',
+ },
+ },
+};
+const seriesHighContrastSettings = {
+ color: 'rgb(0, 0, 0)',
+ lineWidth: 4,
+};
+const chartHighContrastSettings = {
+ layout: {
+ textColor: '#000000',
+ },
+ grid: {
+ vertLines: {
+ color: '#777777',
+ },
+ horzLines: {
+ color: '#777777',
+ },
+ },
+};
+
+function setHighContrast(enabled) {
+ mainSeries.applyOptions(
+ enabled ? seriesHighContrastSettings : seriesBaseContrastSettings
+ );
+ chart.applyOptions(
+ enabled ? chartHighContrastSettings : chartBaseContrastSettings
+ );
+}
+```
+
+Our `setHighContrast(highContrast)` function updates the chart's colors based on
+the user's preference. If the user prefers high contrast, a higher contrast
+color scheme is applied. If not, the colors switch back to the default, low-contrast scheme.
+
+### Scalable font size
+
+Another key aspect of web accessibility is the option to scale font sizes.
+Users with visual impairments may benefit from larger text sizes, improving
+readability.
+
+We provide an option for these users to adjust the text size through a checkbox,
+which changes text size in the chart:
+
+```html
+
+
+```
+
+Then, we create an event listener in JavaScript for this checkbox input, which increases
+the text size:
+
+```js
+function setFontSize(large) {
+ chart.applyOptions({
+ layout: {
+ fontSize: large ? 16 : 12,
+ },
+ });
+}
+
+document
+ .querySelector('#large-font-checkbox')
+ .addEventListener('change', event => {
+ setFontSize(event.target.checked);
+ });
+```
+
+In this example, when the 'Increase Font Size' input is checked, the font size
+in the chart increases to 16px.
+
+Including these additional accessibility features adheres to the principles of
+creating an inclusive web, where design embraces all user types, abilities, and
+preferences. Note that you should conduct rigorous accessibility testing before deployment.
diff --git a/website/tutorials/a11y/screenreader.mdx b/website/tutorials/a11y/screenreader.mdx
new file mode 100644
index 0000000000..696fb3acb7
--- /dev/null
+++ b/website/tutorials/a11y/screenreader.mdx
@@ -0,0 +1,259 @@
+---
+sidebar_position: 2
+sidebar_label: Screen Readers
+pagination_title: Screen Readers
+title: Screen Readers
+description: In this section we will add screen reader support to the chart.
+keywords:
+ - a11y
+ - accessibility
+ - screenreaders
+ - keyboard
+ - assistive
+pagination_prev: a11y/keyboard
+pagination_next: a11y/readability
+---
+
+# Integrating ARIA roles and descriptive content for enhanced accessibility
+
+Accessibility in web development extends beyond just accommodating keyboard-only
+users. Many users with varying abilities make use of assistive technologies like
+screen readers to effectively interact with web applications.
+[ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA)
+(Accessible Rich Internet Applications) roles and states offer a powerful
+toolkit to improve this interaction by conveying information about the behavior
+and purpose of interface components.
+
+In the context of our line chart, we'll be looking at how to implement ARIA
+attributes to further enhance its accessibility in addition to generating
+descriptive content for our graph.
+
+:::info
+
+In this tutorial we will only make use of
+the `aria-live`, `aria-label`, and `aria-hidden` attributes. You can explore
+a [more comprehensive list of attributes on this MDN page]
+(https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes).
+
+:::
+
+## Use of ARIA attributes in the chart
+
+### aria-live
+
+To provide real-time updates about the chart to assistive technologies, we use
+the `aria-live` attribute. It accepts a few potential values, although
+`"polite"` and `"assertive"` are the most common.
+
+With `aria-live="polite"`, updates are presented at the user's next convenient
+opportunity, such as when they stop typing or when a task is completed. With
+`aria-live="assertive"`, updates are presented immediately.
+
+Our chart uses the `"assertive"` value because the description should be read
+out based on a user action (keyboard action):
+
+```html
+
+```
+
+### aria-label
+
+The `aria-label` attribute is used to specify a string that labels the current
+element. It's useful when there isn't any text content that describes this
+element.
+
+On our chart, it could read something like this:
+
+```html
+
+```
+
+### aria-hidden
+
+The `aria-hidden` attribute is used to hide irrelevant or redundant
+information from assistive technologies. Its value is either "true" or "false".
+
+For example, if our chart contained a decorative element with no semantic
+meaning, we could use `aria-hidden="true"` to hide it from screen readers:
+
+```html
+
+```
+
+### Adding the ARIA attributes to an existing chart via JavaScript
+
+```html
+
+
+
+
+
+
+```
+
+## Generating a description of the chart
+
+In addition to ARIA roles, providing a textual description for our charts helps
+all users, especially those relying on screen readers or other assistive
+technologies.
+
+You may generate a description of a chart by applying domain-specific knowledge.
+It's beneficial to outline the general trend or patterns of the data, highlight
+any notable points or anomalies, and summarize the implications of the data.
+
+You can add a descriptive section to the chart:
+
+```html
+
+
+
+```
+
+You can use JavaScript to change the content inside this div whenever the chart
+data is updated:
+
+```js
+const descriptionElement = document.getElementById('chart-description');
+descriptionElement.textContent = generateDescription(mainSeries.data());
+```
+
+Here, `generateDescription(data)` would be a function that you write to
+translate the chart's data into human-readable insights. The function would vary
+greatly based on what the charts represent and how much detail you wish to
+provide.
+
+The example describes the chart based on its first and last visible data
+points in addition to the highest and lowest points displayed. This is used to
+generate a description like this:
+
+> The first price is $679.10 at Wed Sep 19 2018. The last price is $555.37 at
+> Wed May 15 2019. The actual change in price was -$123.73, corresponding to a
+> percentage change of -18.22%. The lowest price was $32.76 at Fri Dec 21 2018.
+> The highest price was $951.33 at Sun Mar 24 2019.
+
+The following code could be used as a starting point for generating chart
+descriptions:
+
+```js
+function formatDate(time) {
+ return new Date(time * 1000).toDateString();
+}
+
+function formatValue(value) {
+ return `${value < 0 ? '-' : ''}$${Math.abs(value).toFixed(2)}`;
+}
+
+function getStats(data) {
+ const stats = {
+ start: data[0],
+ close: data[data.length - 1],
+ low: data[0],
+ high: data[0],
+ };
+
+ for (const point of data) {
+ if (point.value > stats.high.value) {
+ stats.high = point;
+ }
+ if (point.value < stats.low.value) {
+ stats.low = point;
+ }
+ }
+
+ return stats;
+}
+
+function getVisibleSeriesData(chart, series) {
+ const timeScale = chart.timeScale();
+ const visibleRange = timeScale.getVisibleLogicalRange();
+ const data = [];
+ for (let i = Math.round(visibleRange.from); i <= visibleRange.to; i++) {
+ const d = series.dataByIndex(i, 0);
+ if (d !== null) {
+ data.push(d);
+ }
+ }
+ return data;
+}
+
+function describeFinanceChart(data) {
+ if (!data || data.length === 0) {
+ return 'The data set is empty.';
+ }
+
+ const stats = getStats(data);
+
+ const firstPrice = `The first price is ${formatValue(
+ stats.start.value
+ )} at ${formatDate(stats.start.time)}.`;
+ const lastPrice = `The last price is ${formatValue(
+ stats.close.value
+ )} at ${formatDate(stats.close.time)}.`;
+
+ const actualChange = stats.close.value - stats.start.value;
+ const percentChange = (actualChange / stats.start.value) * 100;
+
+ const changeDescription = `The actual change in price was ${formatValue(
+ actualChange
+ )}, corresponding to a percentage change of ${percentChange.toFixed(2)}%.`;
+
+ let lowHigh = '';
+ if (
+ stats.low.time !== stats.start.time &&
+ stats.low.time !== stats.close.time
+ ) {
+ lowHigh += `The lowest price was ${formatValue(
+ stats.low.value
+ )} at ${formatDate(stats.low.time)}.`;
+ }
+ if (
+ stats.high.time !== stats.start.time &&
+ stats.high.time !== stats.close.time
+ ) {
+ lowHigh += ` The highest price was ${formatValue(
+ stats.high.value
+ )} at ${formatDate(stats.high.time)}.`;
+ }
+
+ return `${firstPrice} ${lastPrice} ${changeDescription} ${lowHigh}`.trim();
+}
+```
+
+## Semantic HTML
+
+Using
+[Semantic HTML](https://developer.mozilla.org/en-US/docs/Glossary/Semantics#semantics_in_html)
+elements offers several benefits. Firstly, they enhance the accessibility of web
+content as they provide specific meaning to the browser and assistive technology
+like screen readers, helping them understand the content's structure and
+purpose. This is crucial for users with disabilities.
+
+It is suggested that the container provided to the `createChart` method should
+use a semantic element such as `` instead of a generic element like
+`div`.
+
+```html
+
+```
+
+In the next part, we'll discuss contrast control and font scaling.
diff --git a/website/tutorials/index.mdx b/website/tutorials/index.mdx
index 7705d3f25f..270b7ced96 100644
--- a/website/tutorials/index.mdx
+++ b/website/tutorials/index.mdx
@@ -8,6 +8,7 @@ import Shapes from "@site/src/img/shapes.svg";
import ReactLogo from "@site/src/img/react.svg";
import VuejsLogo from "@site/src/img/vuejs.svg";
import WebComponentsLogo from "@site/src/img/webcomponents.svg";
+import A11y from "@site/src/img/a11y.svg";
# Tutorials
@@ -32,6 +33,12 @@ import VersionWarningAdmonition from "@site/src/components/VersionWarningAdmonit
image: ,
description: "Customizing appearance & features",
},
+ {
+ href: "/tutorials/a11y/intro",
+ title: "Accessibility",
+ image: ,
+ description: "How to improve A11y support",
+ },
]}
/>