Jayne Mast
Senior Software Engineer at Confrere
Jayne is located at The Netherlands
This is a schema we've used to create accessbile bar charts, with human-readable text for each bar.
import React from "react";
import { RiBarChartHorizontalFill } from "react-icons/ri";
const scale = {
name: "horizontalBarChart.scale",
title: "Scale",
type: "object",
fields: [
{
name: "ticks",
title: "Ticks",
type: "array",
of: [{ type: "number" }],
description:
"Each tick is a number on the scale. If you don't add ticks, the scale will not be shown.",
validation: (Rule) => Rule.min(2),
},
{
name: "prefix",
title: "Prefix",
type: "string",
description: "A text that goes in front of each tick (for example, $)",
},
{
name: "suffix",
title: "Suffix",
type: "string",
description: "A text that goes after each tick (for example, %)",
},
],
};
const legendItem = {
name: "horizontalBarChart.legendItem",
title: "Legend item",
type: "object",
fields: [
{
name: "label",
title: "Label",
type: "string",
validation: (Rule) => Rule.required(),
},
{
name: "color",
title: "Color",
type: "brandColor",
validation: (Rule) => Rule.required(),
description:
"The color you set here would also be the color of one of the points (bars) in a series. For example, if this would be the second legend item, then the second point in a series would be this color. You can override the color of a point.",
},
],
preview: {
select: {
title: "label",
color: "color",
},
prepare({ title, color }) {
return {
title,
media: (
<div
style={{ width: "40px", height: "15px", backgroundColor: color }}
></div>
),
};
},
},
};
const point = {
name: "horizontalBarChart.point",
title: "Point",
type: "object",
fields: [
{
name: "value",
title: "Value",
type: "number",
validation: (Rule) => Rule.required(),
},
{
name: "description",
title: "Description",
type: "string",
description:
"This is a tooltip that's shown when you hover over the point.",
},
{
name: "color",
title: "Color",
type: "brandColor",
description:
"This would override the color set in the legend. Or if you don't have a legend, this would be the color of the point.",
},
],
preview: {
select: {
title: "value",
subtitle: "description",
color: "color",
},
prepare({ title, subtitle, color }) {
return {
title,
subtitle,
media: color && (
<div
style={{ width: "40px", height: "15px", backgroundColor: color }}
></div>
),
};
},
},
};
const seriesItem = {
name: "horizontalBarChart.seriesItem",
title: "Series item",
type: "object",
fields: [
{
name: "label",
title: "Label",
type: "string",
description: "The label for the set of columns.",
validation: (Rule) => Rule.required(),
},
{
name: "points",
title: "Points",
type: "array",
of: [{ type: "horizontalBarChart.point" }],
description: "Each point is one of the bars.",
validation: (Rule) => Rule.required(),
},
],
};
const chart = {
name: "horizontalBarChart",
type: "document",
title: "Horizontal bar chart",
icon: RiBarChartHorizontalFill,
fields: [
{
name: "name",
title: "Name",
type: "string",
description:
"This is used so you can easily find it when adding to another document.",
validation: (Rule) => Rule.required(),
},
{
name: "scale",
title: "Scale",
type: "horizontalBarChart.scale",
description:
"The scale are the numbers that show up at the X-axis (the bottom).",
},
{
name: "legend",
title: "Legend",
type: "array",
of: [{ type: "horizontalBarChart.legendItem" }],
description: "The legend shows what each color in the graph means.",
},
{
name: "humanReadableText",
title: "Human-readable text template",
type: "text",
rows: 3,
validation: (Rule) => Rule.required(),
description: (
<>
<p>
This is a generated description of a single point (bar)This is a
full description of the point. What would you tell someone who
cannot see this point?
</p>
<p>
You can use the following replacements:
<br />
{"- {legendLabel}"}
<br />
{"- {valueLabel}"}
<br />
{"- {value}"}
<br />
{"- {description}"}
</p>
<p>
For example, "Among people who did{" "}
<strong>{"{legendLabel}"}</strong>, <strong>{"{value}"}</strong>% (
<strong>{"{description}"}</strong>) said they would use it for '
<strong>{"{valueLabel}"}</strong>'" will become "Among people who
did <strong>0-5 video calls</strong>, <strong>68</strong>% (
<strong>21 respondents</strong>) said they would use it for '
<strong>Follow-ups with patients on sick leave</strong>'".
</p>
</>
),
},
{
name: "series",
title: "Series",
type: "array",
of: [{ type: "horizontalBarChart.seriesItem" }],
description:
"The series is the set of data, each set of columns is a series.",
validation: (Rule) => Rule.required(),
},
],
};
export default { scale, chart, legendItem, seriesItem, point };
// this uses sanity-plugin-color-list
export default {
name: "brandColor",
title: "Brand color",
type: "colors",
options: {
list: [
{ title: "Primary (dark)", value: "#ff9f01" },
{ title: "Primary", value: "#ffbc00" },
{ title: "Primary (light)", value: "#ffefc0" },
{ title: "Secondary (dark)", value: "#00184c" },
{ title: "Secondary", value: "#123196" },
{ title: "Secondary (light)", value: "#a5d5ff" },
{ title: "Warning (dark)", value: "#f45540" },
{ title: "Warning", value: "#f97369" },
{ title: "Warning (light)", value: "#f5c6bc" },
{ title: "Accept (dark)", value: "#00ad94" },
{ title: "Accept", value: "#00d2bb" },
{ title: "Accept (light)", value: "#c6efe7" },
],
},
};
With this you can create a bar chart. We've used this for our horizontal bar charts, hence the name, but you can use it for any charts you'd like.
For colors, you can select from a certain selection of colors that uses the sanity-plugin-color-list
plugin.
There's also a field called humanReadableText
where users can use variables to create a text for each bar. The implementor can use visually hidden fields to add this to their bar charts.
Senior Software Engineer at Confrere