Skip to the content.

Inline charts

The articles (and other examples of Sanity Portable Text) used to only be able to display images. And when the communication team needed to show charts or KPI’s the design team would create images for them. Obviously those images were pinned to a certain moment in time and were not interactive.

Thus, the need became clear for charts to be inserted into Portable Text.

This section describes how this was implemented.

Overview

All of the charts on the dashboard are configuration driven. So, a set of props is assembled and passed into a chart component that will interpret these settings and render the appropriate chart.

This made it relatively easy to copy this same configuration structure into a Sanity schema and let this configuration be filled there, instead of being hard-coded in a page.

So, when an article (a Portable Text object) gets pulled from Sanity, the chart configurations will be part of that data stream in the same way an image URL is.

Each chart type has a unique identifier that is recognized by the RichContent component and this will then render the appropriate chart component populated with the configuration that is in the Portable Text data.

Currently the following chart types are supported in Portable Text:

Sanity

In Sanity the the schema’s for the different chart configurations can all be found in the src/schemas/documents folder. In the Sanity desk menu they can all be found under ‘Grafieken’.

The idea here is that a developer can configure a chart which can subsequently be used by an editor inside an article as a reference. This is because configuring a chart will require some developer/domain knowledge that simply cannot be expected from an editor.

Inside the portable text editor an editor can insert the different types of charts in the same way that they insert an image.

The charts are configured to be ‘insertable’ in src/schemas/objects/block-fields. This configuration allows an editor to add a specific title and optional date selections to the instance of the chart that they insert in their article. So in one article they can insert a time series chart that shows the data, for example, from 1st of January 2020 until the 30th of May 2020, while another article shows the 5th of January 2021 until the 3rd of February 2021.

A number of custom input components are created to for the data configurations and icon and color selection. These all live in src/components/portable-text. The components in src/components/portable-text/shared all have to do with the data configuration. So, choosing which JSON data is fed to a chart. All these components import src/data/data-structure, this data structure describes the hierarchy of the JSON files and the data contained in them. The file src/data/data-structure.ts is generated by packages/cli/src/scripts/generate-data-structures.ts, and this script is automatically triggered before running yarn dev or yarn deploy in the cms package.

Dashboard

The RichContent component consumes the portable text data and will render out the inlined charts when encountered. Each chart component is wrapped in an inline version of it. So, the Choropleth is wrapped in InlineChoropleth, the TimeSeriesChart in InlineTimeSeriesChart, etc.

Normally, the chart data is included in the getStaticProps phase of rendering, but since the chart configuration is part of the portable text this data is loaded client-side. (This is something that could be optimized further, the portable text could be parsed for chart configurations and the data be loaded during getStaticProps but this iteration of the inline charts doesn’t do that yet).

So, once the chart gets initialized it will load the data from an API route. These routes all live under app/src/pages/api/data, the names will speak for themselves.

Limitations

Most of the charts will be able to be added to a Portable Text, but some exceptions exist.

If there is any specialized client-side data shaping before the data is fed to the chart, this won’t be able to be configured in the Sanity document. So, for example, if we want to display the nl.hospital_nice data but for some reason this data needs to be merged with some other data to properly display, it won’t be possible to describe that in a Sanity document, since a document like that can only hold primitive values like strings, numbers and booleans.

Custom tooltips can’t be configured either, since this would require the RichContent component to include every available custom tooltip, which would unnecessarily bloat the bundle sizes.

Back to index