Jayne Mast
Senior Software Engineer at Confrere
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
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store