From b246462e660d54e850d3587d95114ccbaf1a8e0d Mon Sep 17 00:00:00 2001 From: Ivan Martynau Date: Thu, 23 Oct 2025 14:42:23 +0200 Subject: [PATCH 1/2] Improve a11y for ClusterHUD.jsx and PageTitle.jsx Add proper navigation. Add proper readability for canvas and link --- .../webapp/src/components/ClusterHUD.jsx | 45 +++++++++++++++++++ .../webapp/src/components/PageTitle.jsx | 4 +- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx b/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx index 6a2d650a99ae..1e6f4dc1d86e 100644 --- a/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx +++ b/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx @@ -146,31 +146,61 @@ export class ClusterHUD extends React.Component { this.state.runningQueries, $.extend({}, SPARKLINE_PROPERTIES, { chartRangeMin: 0 }) ) + // Apply ARIA attributes to the generated canvas + $('#running-queries-sparkline canvas').attr({ + 'aria-label': `Running queries over time. Current value: ${this.state.runningQueries[this.state.runningQueries.length - 1]} queries`, + 'role': 'img' + }) $('#blocked-queries-sparkline').sparkline( this.state.blockedQueries, $.extend({}, SPARKLINE_PROPERTIES, { chartRangeMin: 0 }) ) + // Apply ARIA attributes to the generated canvas + $('#blocked-queries-sparkline canvas').attr({ + 'aria-label': `Blocked queries over time. Current value: ${this.state.blockedQueries[this.state.blockedQueries.length - 1]} queries`, + 'role': 'img' + }) $('#queued-queries-sparkline').sparkline( this.state.queuedQueries, $.extend({}, SPARKLINE_PROPERTIES, { chartRangeMin: 0 }) ) + // Apply ARIA attributes to the generated canvas + $('#queued-queries-sparkline canvas').attr({ + 'aria-label': `Queued queries over time. Current value: ${this.state.queuedQueries[this.state.queuedQueries.length - 1]} queries`, + 'role': 'img' + }) $('#active-workers-sparkline').sparkline( this.state.activeWorkers, $.extend({}, SPARKLINE_PROPERTIES, { chartRangeMin: 0 }) ) + // Apply ARIA attributes to the generated canvas + $('#active-workers-sparkline canvas').attr({ + 'aria-label': `Active workers over time. Current value: ${this.state.activeWorkers[this.state.activeWorkers.length - 1]} workers`, + 'role': 'img' + }) $('#running-drivers-sparkline').sparkline( this.state.runningDrivers, $.extend({}, SPARKLINE_PROPERTIES, { numberFormatter: precisionRound, }) ) + // Apply ARIA attributes to the generated canvas + $('#running-drivers-sparkline canvas').attr({ + 'aria-label': `Running drivers over time. Current value: ${formatCount(this.state.runningDrivers[this.state.runningDrivers.length - 1])} drivers`, + 'role': 'img' + }) $('#reserved-memory-sparkline').sparkline( this.state.reservedMemory, $.extend({}, SPARKLINE_PROPERTIES, { numberFormatter: formatDataSizeBytes, }) ) + // Apply ARIA attributes to the generated canvas + $('#reserved-memory-sparkline canvas').attr({ + 'aria-label': `Reserved memory over time. Current value: ${formatDataSizeBytes(this.state.reservedMemory[this.state.reservedMemory.length - 1])}`, + 'role': 'img' + }) $('#row-input-rate-sparkline').sparkline( this.state.rowInputRate, @@ -178,18 +208,33 @@ export class ClusterHUD extends React.Component { numberFormatter: formatCount, }) ) + // Apply ARIA attributes to the generated canvas + $('#row-input-rate-sparkline canvas').attr({ + 'aria-label': `Row input rate over time. Current value: ${formatCount(this.state.rowInputRate[this.state.rowInputRate.length - 1])} rows per second`, + 'role': 'img' + }) $('#byte-input-rate-sparkline').sparkline( this.state.byteInputRate, $.extend({}, SPARKLINE_PROPERTIES, { numberFormatter: formatDataSizeBytes, }) ) + // Apply ARIA attributes to the generated canvas + $('#byte-input-rate-sparkline canvas').attr({ + 'aria-label': `Byte input rate over time. Current value: ${formatDataSizeBytes(this.state.byteInputRate[this.state.byteInputRate.length - 1])} per second`, + 'role': 'img' + }) $('#cpu-time-rate-sparkline').sparkline( this.state.perWorkerCpuTimeRate, $.extend({}, SPARKLINE_PROPERTIES, { numberFormatter: precisionRound, }) ) + // Apply ARIA attributes to the generated canvas + $('#cpu-time-rate-sparkline canvas').attr({ + 'aria-label': `CPU time rate per worker over time. Current value: ${formatCount(this.state.perWorkerCpuTimeRate[this.state.perWorkerCpuTimeRate.length - 1])} CPU seconds per worker per second`, + 'role': 'img' + }) this.setState({ lastRender: renderTimestamp, diff --git a/core/trino-web-ui/src/main/resources/webapp/src/components/PageTitle.jsx b/core/trino-web-ui/src/main/resources/webapp/src/components/PageTitle.jsx index 38714060dadb..5b9b7975dd63 100644 --- a/core/trino-web-ui/src/main/resources/webapp/src/components/PageTitle.jsx +++ b/core/trino-web-ui/src/main/resources/webapp/src/components/PageTitle.jsx @@ -113,8 +113,8 @@ export class PageTitle extends React.Component { - - + + Starburst logo From 28e7366bbcda1640f051b6f1afd3ae5c26a631ec Mon Sep 17 00:00:00 2001 From: Ivan Martynau Date: Mon, 3 Nov 2025 14:42:19 +0100 Subject: [PATCH 2/2] Improve a11y for ClusterHUD.jsx Add propeties for better readability in the voice reader Add proper navigation. Add proper readability for canvas and link --- .../webapp/src/components/ClusterHUD.jsx | 54 +++++++++++++++---- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx b/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx index 1e6f4dc1d86e..479713ee7599 100644 --- a/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx +++ b/core/trino-web-ui/src/main/resources/webapp/src/components/ClusterHUD.jsx @@ -149,7 +149,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#running-queries-sparkline canvas').attr({ 'aria-label': `Running queries over time. Current value: ${this.state.runningQueries[this.state.runningQueries.length - 1]} queries`, - 'role': 'img' + 'role': 'img', + 'id': 'running-queries-chart' }) $('#blocked-queries-sparkline').sparkline( this.state.blockedQueries, @@ -158,7 +159,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#blocked-queries-sparkline canvas').attr({ 'aria-label': `Blocked queries over time. Current value: ${this.state.blockedQueries[this.state.blockedQueries.length - 1]} queries`, - 'role': 'img' + 'role': 'img', + 'id': 'blocked-queries-chart' }) $('#queued-queries-sparkline').sparkline( this.state.queuedQueries, @@ -167,7 +169,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#queued-queries-sparkline canvas').attr({ 'aria-label': `Queued queries over time. Current value: ${this.state.queuedQueries[this.state.queuedQueries.length - 1]} queries`, - 'role': 'img' + 'role': 'img', + 'id': 'queued-queries-chart' }) $('#active-workers-sparkline').sparkline( @@ -177,7 +180,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#active-workers-sparkline canvas').attr({ 'aria-label': `Active workers over time. Current value: ${this.state.activeWorkers[this.state.activeWorkers.length - 1]} workers`, - 'role': 'img' + 'role': 'img', + 'id': 'active-workers-chart' }) $('#running-drivers-sparkline').sparkline( this.state.runningDrivers, @@ -188,7 +192,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#running-drivers-sparkline canvas').attr({ 'aria-label': `Running drivers over time. Current value: ${formatCount(this.state.runningDrivers[this.state.runningDrivers.length - 1])} drivers`, - 'role': 'img' + 'role': 'img', + 'id': 'running-drivers-chart' }) $('#reserved-memory-sparkline').sparkline( this.state.reservedMemory, @@ -199,7 +204,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#reserved-memory-sparkline canvas').attr({ 'aria-label': `Reserved memory over time. Current value: ${formatDataSizeBytes(this.state.reservedMemory[this.state.reservedMemory.length - 1])}`, - 'role': 'img' + 'role': 'img', + 'id': 'reserved-memory-chart' }) $('#row-input-rate-sparkline').sparkline( @@ -211,7 +217,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#row-input-rate-sparkline canvas').attr({ 'aria-label': `Row input rate over time. Current value: ${formatCount(this.state.rowInputRate[this.state.rowInputRate.length - 1])} rows per second`, - 'role': 'img' + 'role': 'img', + 'id': 'row-input-rate-chart' }) $('#byte-input-rate-sparkline').sparkline( this.state.byteInputRate, @@ -222,7 +229,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#byte-input-rate-sparkline canvas').attr({ 'aria-label': `Byte input rate over time. Current value: ${formatDataSizeBytes(this.state.byteInputRate[this.state.byteInputRate.length - 1])} per second`, - 'role': 'img' + 'role': 'img', + 'id': 'byte-input-rate-chart' }) $('#cpu-time-rate-sparkline').sparkline( this.state.perWorkerCpuTimeRate, @@ -233,7 +241,8 @@ export class ClusterHUD extends React.Component { // Apply ARIA attributes to the generated canvas $('#cpu-time-rate-sparkline canvas').attr({ 'aria-label': `CPU time rate per worker over time. Current value: ${formatCount(this.state.perWorkerCpuTimeRate[this.state.perWorkerCpuTimeRate.length - 1])} CPU seconds per worker per second`, - 'role': 'img' + 'role': 'img', + 'id': 'cpu-time-rate-chart' }) this.setState({ @@ -256,6 +265,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Total number of queries currently running" + tabIndex="0" + aria-label="Running queries - Total number of queries currently running" + aria-describedby="running-queries-chart" > Running queries @@ -268,6 +280,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Total number of active worker nodes" + tabIndex="0" + aria-label="Active workers - Total number of active worker nodes" + aria-describedby="active-workers-chart" > Active workers @@ -280,6 +295,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Moving average of input rows processed per second" + tabIndex="0" + aria-label="Rows per second - Moving average of input rows processed per second" + aria-describedby="row-input-rate-chart" > rows/s @@ -328,6 +346,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Total number of queries currently queued and awaiting execution" + tabIndex="0" + aria-label="Queued queries - Total number of queries currently queued and awaiting execution" + aria-describedby="queued-queries-chart" > Queued queries @@ -340,6 +361,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Moving average of total running drivers" + tabIndex="0" + aria-label="Runnable drivers - Moving average of total running drivers" + aria-describedby="running-drivers-chart" > Runnable drivers @@ -352,6 +376,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Moving average of input bytes processed per second" + tabIndex="0" + aria-label="Bytes per second - Moving average of input bytes processed per second" + aria-describedby="byte-input-rate-chart" > bytes/s @@ -398,6 +425,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Total number of queries currently blocked and unable to make progress" + tabIndex="0" + aria-label="Blocked Queries - Total number of queries currently blocked and unable to make progress" + aria-describedby="blocked-queries-chart" > Blocked Queries @@ -410,6 +440,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Total amount of memory reserved by all running queries" + tabIndex="0" + aria-label="Reserved Memory - Total amount of memory reserved by all running queries" + aria-describedby="reserved-memory-chart" > Reserved Memory (B) @@ -422,6 +455,9 @@ export class ClusterHUD extends React.Component { data-toggle="tooltip" data-placement="right" title="Moving average of CPU time utilized per second per worker" + tabIndex="0" + aria-label="Worker Parallelism - Moving average of CPU time utilized per second per worker" + aria-describedby="cpu-time-rate-chart" > Worker Parallelism