HorizontalPercentageBarChart Developer Guide
Overview
HorizontalPercentageBarChart is a Tui component that renders a stacked horizontal bar chart where each bar represents percentage breakdowns of data items. It is built on top of ChartJs and provides:
Stacked horizontal bars with automatic percentage calculation
An optional target line overlay
Custom tooltips with a breakdown of the datasets
Clickable bars and labels
A legend with dataset labels
Import path
import HorizontalPercentageBarChart from 'tui_charts/components/HorizontalPercentageBarChart';Props
Prop | Type | Required | Default | Description |
|---|---|---|---|---|
ariaLabel | String | Yes | — | Accessible label for the chart canvas. |
chartData | Array | Yes | — | Array of data items. See Data structure. |
datasets | Array | Yes | — | Dataset definitions (labels and optional colours). See Datasets. |
maxBars | Number | Yes | — | Maximum bars to display. Controls container height. |
targetLineValue | Number\|String | No |
| Percentage value (0–100) for the vertical target line. |
targetLineLabel | String | No |
| Legend label for the target line. |
canvasId | String | No | Auto-generated | HTML id for the <canvas> element. |
canvasDescId | String | Yes | — | ID of an element that describes the chart (for |
tooltipFooter | String | No |
| Text displayed in the tooltip footer (e.g. "Click for details"). |
Events
Event | Payload | Description |
|---|---|---|
bar-clicked | id (from chartData item) | Emitted when a user clicks a bar segment. |
label-clicked | id (from chartData item) | Emitted when a user clicks a bar label |
Slots
Slot | Description |
|---|---|
| Rendered instead of the chart when chartData is empty. |
Data structure
chartData
An array of objects, one per bar.
{
id: number | string, // Unique identifier — returned in click events
name: string, // Label displayed to the left of the bar
values: number[], // Raw counts for each dataset (NOT percentages)
}The component automatically calculates percentages from the raw values. For example, values: [150, 50] produces a bar showing 75% / 25%. Likewise values: [3, 1] also produces a bar showing 75% / 27%. The values array length must match the datasets array length.
datasets
An array of dataset definitions, one per segment in each stacked bar
{
label: string, // Legend label
backgroundColor?: string, // CSS colour (e.g. '#4CAF50')
hoverBackgroundColor?: string, // Colour on hover
}
Basic usage example
<template>
<HorizontalPercentageBarChart
aria-label="Course completion by department"
canvas-desc-id="chart-description"
:chart-data="chartData"
:datasets="datasets"
:max-bars="5"
:target-line-value="80"
target-line-label="Target"
tooltip-footer="Click for details"
@bar-clicked="onBarClicked"
@label-clicked="onLabelClicked"
>
<template v-slot:empty-state>
<p>No data available.</p>
</template>
</HorizontalPercentageBarChart>
</template>
<script setup>
import HorizontalPercentageBarChart from 'tui_charts/components/HorizontalPercentageBarChart';
const datasets = [
{ label: 'Completed', backgroundColor: '#4CAF50' },
{ label: 'In progress', backgroundColor: '#2196F3' },
{ label: 'Not started', backgroundColor: '#9E9E9E' },
];
const chartData = [
{ id: 1, name: 'Engineering', values: [120, 30, 10] },
{ id: 2, name: 'Marketing', values: [85, 45, 20] },
{ id: 3, name: 'Sales', values: [60, 50, 40] },
{ id: 4, name: 'HR', values: [95, 5, 0] },
{ id: 5, name: 'Finance', values: [40, 30, 30] },
];
function onBarClicked(id) {
// id corresponds to the chartData item's id
console.log('Bar clicked for item:', id);
}
function onLabelClicked(id) {
console.log('Label clicked for item:', id);
}
</script>Using the chart in a block or plugin
Server-side: passing props via totara_tui\output\component
In your plugin's PHP, pass data as props to a Tui component that wraps the chart.
<?php
use totara_tui\output\component;
$props = [
'chart-data' => $chart_data, // Array of items
'datasets' => $datasets, // Dataset definitions
'max-bars' => 5,
'target-line-value' => 80,
];
$component = new component('your_plugin/components/YourChartWrapper', $props);Your wrapper Vue component should receive these props and pass them down to HorizontalPercentageBarChart
Configuration options
Styling
Theme colours: If you omit backgroundColor from your datasets, the chart automatically uses Totara's theme variables (color-chart-background-1 through color-chart-background-7), cycling through them.
Custom colours: Provide backgroundColor (and optionally hoverBackgroundColor) per dataset:
const datasets = [
{ label: 'Pass', backgroundColor: '#2E7D32' },
{ label: 'Fail', backgroundColor: '#C62828', hoverBackgroundColor: '#E53935' },
];Target line: Set targetLineValue prop to a percentage (1–100) to render a solid vertical reference line. Set it to 0 to hide. Provide targetLineLabel to add a corresponding legend entry.
Chart sizing
The chart height is calculated automatically. Set maxBars to the number of items you expect to display per page. The chart pre-allocates space so that adding or removing items doesn’t cause jarring layout shifts.
Accessibility
Chart.js renders to a <canvas> element, which is not accessible to screen readers. You should:
Provide a meaningful
ariaLabelProvide a
canvasDescIdpointing to a hidden element that describes the chart content.Ensure the same data is available elsewhere on the page in an accessible way (table, list, etc.).