Widget

The chart widget

The chart widget draws an SVG bar or line chart from a JSON file. One line of markup puts it on a page: the module script and a div with the path of the config. Every chart carries its values, the source of the numbers with the day they were read, and a copy of the data as a real table under a details block.

Updated 2026-10-22 · Author: Mark Burmistrov · 4 minutes

One line

How a chart is put on a page

The widget is a module and a div. The script finds every div with the data-chart attribute, reads the JSON config behind it and draws the chart in place. Nothing is sent anywhere and nothing is asked of the reader: there is no form and no data is collected.

<script type="module" src="assets/chart/chart.js"></script>
<div class="ts-chart" data-chart="assets/chart/data/prices-usd.json"></div>

A page of the factory gets the same chart with one line in its data file:

"chart": "assets/chart/data/prices-usd.json"
The charts

Three charts, three real sets of numbers

The numbers below are the numbers of the research of this repository, read on 21 October 2026: the prices of the market table, the count of the locales of every interface and the price of a minute of audio in the Russian services. Every chart carries its source and a copy of the data as a table.

The config

What a chart file has to carry

The keys of the config of a chart
Key What it is
type "bar" or "line"
orientation "horizontal" (the default) or "vertical"
xScale "linear" (the default) or "log" — a log axis for sizes that grow by times
title, subtitle, description the head of the chart; the description is what a screen reader reads
unit, unitPosition the unit of the values and where it stands: "before" or "after"
decimals, trim how many decimals the values have; trim drops the zeros at the end
locale the language of the numbers: "en-US", "ru-RU"
xLabel, yLabel the names of the two axes
source, accessed where the numbers come from and the day they were read — both are required
table the caption and the columns of the table copy
series the name, the color and the points of every series

A whole config of a bar chart, with the numbers of the first chart of this page:

{
  "type": "bar",
  "orientation": "horizontal",
  "title": "The cheapest paid plan of each service, in dollars a month",
  "unit": "$",
  "unitPosition": "before",
  "decimals": 2,
  "trim": true,
  "locale": "en-US",
  "xLabel": "US dollars per month",
  "yLabel": "Service",
  "source": "the public pricing page of every service",
  "accessed": "2026-10-21",
  "table": {
    "caption": "The cheapest paid plan of each service, paid yearly",
    "columns": ["Service", "Price a month", "Note"]
  },
  "series": [
    {
      "name": "Price a month",
      "points": [
        { "label": "Notta", "value": 8.17, "note": "Pro, paid yearly" }
      ]
    }
  ]
}
Accessibility and motion

What the widget promises

  • The chart is an SVG with role="img", a title and a description; the numbers are written in the drawing and not only in the colors.
  • Every chart has a copy of its data in a real table with a caption, under a details block. The table is in the DOM, so it is read by a screen reader and by the search engines.
  • The source of the numbers and the day they were read are printed under the chart and under the table: "Source: …, accessed 2026-10-21".
  • A chart without a source and without a date is not drawn at all: the widget refuses it and says why.
  • The bars grow when the chart comes into the window, with a transform and an opacity. Nothing else moves.
  • With prefers-reduced-motion: reduce the animation is off and the chart is drawn at once. The widget also listens for the change of the setting while the page is open.
The data

Where the numbers of this page come from

The files of the charts and the research they are built from
File of the config Built from
assets/chart/data/prices-usd.json research/comparison-table.csv — the column price_per_month of every service
assets/chart/data/locales.json research/geo/data/international-players.json — ui_locales_count of every service
assets/chart/data/price-per-minute.json research/competitors/data/players.json — the price plans of the Russian services

The builder reads the research files and stops when a number cannot be found in them: a number that leaves the research without the charts being rebuilt does not reach the page. The files of the research are in the repository of the project, under research/.

FAQ

Questions about the widget

How do I put a chart on a page?

One line of markup: the module script and a div with the path of the JSON config. The widget finds every div with the data-chart attribute on the page and draws it. A page of the factory gets the same chart with one line in its data file.

Where do the numbers of the charts come from?

From the JSON config of the chart. On this page they are built by tools/chart/build_data.py from the research of this repository: the market table, the price plans of the Russian services and the count of the locales of every interface.

Is the chart readable without JavaScript?

The numbers are in the DOM: the table under the details block is a real table with a caption. The drawing needs JavaScript; without it the page keeps the text, the source line and the numbers of the table.

Does the chart move?

The bars grow when the chart comes into the window and the lines draw themselves. With prefers-reduced-motion: reduce there is no movement at all: the chart is drawn at once, in its final shape.