NUI-Widgets documentation has moved to Storybook hosted on Github Pages.

DonutChart

This component is currently in a Beta Release.
Although the component is available and supported, there is a chance there may be breaking changes that are not released as such.
import { DonutChart } from '@concur/nui-charts';

A donut chart is essentially a PieChart with an area of the center cut out. In a donut chart, the arc length of each sector is proportional to the quantity it represents.

Best Practices

  • Visualize no more than 5 categories per chart. It is difficult to differentiate between small values; depicting too many sectors decreases the impact of the visualization. If needed, you can group smaller values into an “other” or “miscellaneous” category, but make sure it does not hide interesting or significant information.
  • Don’t use multiple donut charts for comparison. Sector sizes are very difficult to compare side-by-side. Use a stacked bar chart instead.
  • Make sure all data adds up to 100%. Verify that values total 100% and that donut sectors are sized proportionately to their corresponding value.
  • Order sectors correctly. There are two ways to order sections, both of which are meant to aid comprehension:
    • Option 1: Place the largest section at 12 o’clock, going clockwise. Place the second largest section at 12 o’clock, going counterclockwise. The remaining sections can be placed below, continuing counterclockwise.
    • Option 2: Start the largest section at 12 o’clock, going clockwise. Place remaining sections in descending order, going clockwise.

Example

For DonutChart, each data point will be defined by a DonutChart.Donut child component.

const data = [
    { name: 'Project A', code: 'ABCD-123-XYZ', value: 250 },
    { name: 'Project B', code: 'EFGH-001-XYZ', value: 125 },
    { name: 'Project C', code: '7781-220-010-A', value: 89 },
    { name: 'Project D', code: 'LMNO-664-STU', value: 160 },
    { name: 'Project E', code: '5562-008-030-E', value: 20 }
];

<DonutChart
    textNoData='No data'
    title='Project Allocations'>
    <DonutChart.Donut
        data={data}
        dataKey='value'
        dataKeyLabel='Amount'
        nameKey='name'
        nameKeyLabel='Project'
        valueFormatter={formatCurrencyNoDecimal} />
</DonutChart>

Keys: Data Table vs Legend

Data Table

By default, a Data Table is automatically generated in conjunction with the chart. While visually similar to a traditional legend, the data table provides colorblind users and users of screen readers with crucial content and data that they may not be able to gain from the chart itself. (See Accessibility for more details.)

The data table can be positioned in different locations relative to the chart. Use the tableLegendPosition property to set the position.

const dataReports = [
    { status: 'No Exceptions', count: 74 },
    { status: 'With Exceptions', count: 13 }
];

const dataBudgetPie = [
    { name: 'Spend', value: 2521.43 },
    { name: 'Pending', value: 597.5 },
    { name: 'Available', value: 907.07 }
];

<DonutChart
    tableLegendPosition={{
        placement: 'bottom',
        justify: 'center'
    }}
    textNoData='No data'
    title='Report Summary'>
    <DonutChart.Donut
        data={dataReports}
        dataKey='count'
        dataKeyLabel='Number of Reports'
        nameKey='status'
        nameKeyLabel='Status' />
</DonutChart>

<DonutChart
    tableLegendPosition={{
        placement: 'left',
        justify: 'start'
    }}
    textNoData='No data'
    title='Budget'>
    <DonutChart.Donut
        data={dataBudgetPie}
        dataKey='value'
        dataKeyLabel='Amount'
        innerRadius='70%'
        nameKey='name'
        nameKeyLabel='Type'
        outerRadius='100%'
        valueFormatter={formatCurrency} />
</DonutChart>

Legend

If there is already a data table on the page, or if you intend to display a data table when a user clicks a trigger (link), you may use the traditional Legend that only displays category labels and associated colors.

The traditional legend can also be positioned in different locations relative to the chart. Use the imageLegendPosition property to set the position.

Customizations

NUI Charts is intended to give consumers a simple, easy-to-use API for generating default charts. However, there are a number of customizations that consumers can use to access the full capability of the underlying chart library.

The example below shows a number of customizations:

  • Showing the chart’s legend (Not the data table. See Keys: Data Table vs Legend for the difference) with custom positioning and icon shapes
  • Showing the tooltip with custom styling
  • Using a separate data table in place of the auto-generated companion data table

See Recharts.org for more information about customizations.

const data = [
    { name: 'Project A', code: 'ABCD-123-XYZ', value: 250 },
    { name: 'Project B', code: 'EFGH-001-XYZ', value: 125 },
    { name: 'Project C', code: '7781-220-010-A', value: 89 },
    { name: 'Project D', code: 'LMNO-664-STU', value: 160 },
    { name: 'Project E', code: '5562-008-030-E', value: 20 }
];

<DonutChart
    imageLegendPosition={{
        verticalAlign: 'bottom',
        align: 'center'
    }}
    imageLegendProps={{
        iconType: 'triangle',
        layout: 'horizontal'
    }}
    showImageLegend
    showTooltip
    tableLegendExternalId='custom-table'
    textNoData='No data'
    title='Project Allocations'
    tooltipProps={{
        separator: ' = ',
        wrapperStyle: {
            backgroundColor: '#333',
            borderRadius: '4px'
        },
        labelStyle: {
            color: '#ccc',
            fontSize: '18px',
            fontWeight: 'bold'
        },
        itemStyle: {
            color: '#fff'
        }
    }}>
    <DonutChart.Donut
        data={data}
        dataKey='value'
        dataKeyLabel='Amount'
        nameKey='name'
        nameKeyLabel='Project'
        valueFormatter={formatCurrencyNoDecimal} />
</DonutChart>

<DataGrid
    columns={[
        { propertyName: 'name', headerContent: 'Project Name' },
        { propertyName: 'code', headerContent: 'Project Code' },
        {
            propertyName: 'value', align: 'right', headerContent: 'Amount', bodyContent: (row) => {
                return formatCurrencyNoDecimal(row.value);
            }
        }
    ]}
    data={data}
    empty={{
        title: 'No data'
    }}
    id='custom-table' />

Usage

DonutChart

Properties

Property Type Default Description
children Any Required One DonutChart.Donut component to be rendered in the chart.
textNoData String Required Localized text for the associated data table if no data exists.
title String Required The title of the chart. Will be offscreen, but still read by screen readers.
containerProps Object   Passthrough properties for the ResponsiveContainer component in the underlying chart library. See Recharts.org for more information.
height Number 300 Height of the chart container (in pixels).
imageLegendPosition Object   The position of the chart legend relative to the chart. See imageLegendPosition for details about the available properties. NOTE: showImageLegend must be set to true for these properties to have any effect.
imageLegendProps Object   Passthrough properties for the Legend component in the underlying chart library. See Recharts.org for more information.
showImageLegend Boolean false When true, the chart legend will be drawn. NOTE: The chart legend itself is not accessible so it is typically only used when the associated table data is either in a linked table or is not immediately visible.
showTooltip Boolean false When true, the chart tooltip feature will be enabled. NOTE: The chart tooltip is not accessible so it is only used to augment functionality for users without sight or motor skill impairments.
tableLegendExternalId String   The DOM ID of a data table on the page that contains the data found in the chart. Setting this property will not render the companion data table, but rather link the chart to the table with this ID.
tableLegendPosition Object   The position of the companion data table relative to the chart. See tableLegendPosition for details about the available properties.
tableLegendWidth String 'auto' Will be set as an inline width style on the companion data table. Make sure to include the unit with any value (e.g. ‘400px’ or ‘100%’).
tooltipProps Object   Passthrough properties for the Tooltip component in the underlying chart library. See Recharts.org for more information.

Shape: tableLegendPosition

Properties
Property Type Default Description
justify String 'center' Justification of the table within the data table container. Available values are 'start', 'center', 'end'. If using a placement of top or bottom, these values will go from left to right, otherwise they will go from top to bottom.
placement String 'right' Placement of the data table container relative to the chart. Available values are 'top', 'bottom', 'left', 'right'.

Shape: imageLegendPosition

Properties
Property Type Default Description
align String 'center' Horizontal alignment of the legend relative to the chart. Available values are 'left', 'center', 'right'.
verticalAlign String 'bottom' Vertical alignment of the legend relative to the chart. Available values are 'top', 'middle', 'bottom'.

DonutChart.Donut

Properties

Property Type Default Description
dataKey String, Number or Function Required The key of each sector’s value (in the data property).
data Array   Source data for the chart and associated data table.
dataKeyLabel String   Localized text label for the collection of data keys (values).
nameKey String, Number or Function 'name' The key of each sector’s name (in the data property).
nameKeyLabel String   Localized text label for the collection of name keys (names).

Callbacks

Property Parameters Description
valueFormatter value (Number), name (String), payload (Object) Function to format values on the companion data table and the tooltip, if used.

See Recharts.org for more information.

Accessibility

Consumers of donut charts must:

  • Provide a relevant title for all charts and graphs
  • Utilize the default data table to ensure that all non-text content that is presented to the user has a text alternative that serves the equivalent purpose

By default, CoreUI components help assistive technology read a donut chart’s content by building the following into the default component:

  • When utilizing charts and graphs, keep in mind that all non-text content that is presented to the user has a text alternative that serves the equivalent purpose. Additionally, tables of data must not be turned into images. Utilize the default data table to ensure this guideline is met.
  • Colors are provided to ensure that color not only meets proper color contrast requirements, but that they aren’t used as the only visual means of conveying information, indicating an action, prompting a response, or distinguishing a visual element.

Resources