Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Using the ARIA progressbar role with a status message</title>
</head>
<body>
<h1>Using the ARIA <code>progressbar</code> role with a status message</h1>
<section id="description">
<h2>Description</h2>
<p>This technique demonstrates how to use the <a href="https://www.w3.org/TR/wai-aria/#progressbar">ARIA <code>progressbar</code> role</a> with an <a href="https://www.w3.org/TR/wai-aria-1.2/#live_region_roles">ARIA live region</a> to provide progress information for a file upload.</p>
</section>

<section id="example">
<h2>Example</h2>
<p>This example simulates the progress of uploading a document. The progress of the upload is communicated to the user with an ARIA <code>progressbar</code> and visible text underneath the progress bar. The visible text is contained in an element with an <code>aria-live="polite"</code> attribute. This attribute tells screen readers to announce updates made to the content of the element.</p>
<p>The following example can be seen as a <a href="../../working-examples/aria-role-status-progressbar/">working example</a>.</p>

<pre><code class="language-html">&lt;p id=&quot;upload-progress-label&quot;&gt;Uploading document: &lt;strong&gt;report.pdf&lt;/strong&gt;&lt;/p&gt;
&lt;div
aria-describedby=&quot;progress-text&quot;
aria-labelledby=&quot;upload-progress-label&quot;
aria-valuemax=&quot;100&quot;
aria-valuemin=&quot;0&quot;
aria-valuenow=&quot;0&quot;
id=&quot;upload-progress&quot;
role=&quot;progressbar&quot;&gt;
&lt;/div&gt;
&lt;p id=&quot;progress-text&quot; aria-live=&quot;polite&quot;&gt;0% complete&lt;/p&gt;</code></pre>
</section>

<section id="tests">
<h2>Tests</h2>
<section class="test-procedure">
<h3>Procedure</h3>
<ol>
<li>Check that the visual progress bar element has a <code>role="progressbar"</code> attribute.</li>
<li>Check that there is a suitable ARIA live region in the code.</li>
<li>Using a screen reader, check that announcements are made that communicate the progress of the task.</li>
</ol>
</section>
<section class="test-results">
<h3>Expected Results</h3>
<ul>
<li>#1, #2, and #3 are true.</li>
</ul>
</section>
</section>
</body>
</html>
4 changes: 1 addition & 3 deletions understanding/understanding.11tydata.js
Original file line number Diff line number Diff line change
Expand Up @@ -1368,7 +1368,7 @@ export default function (data) {
"Situation C: If a status message conveys information on the progress of a process:",
techniques: [
"ARIA23",
'Using <code>role="progressbar"</code> (future link)',
'<a href="../techniques/aria/technique-using-progressbar-role-with-a-status-message.html">Using the ARIA progressbar role with a status message</a>',
{
and: ["ARIA22", "G193"],
andConjunction: "in combination with",
Expand All @@ -1377,9 +1377,7 @@ export default function (data) {
},
],
advisory: [
"Using aria-live regions with chat clients (future link)",
'Using aria-live regions to support <a href="content-on-hover-or-focus">1.4.13 Content on Hover or Focus</a> (future link)',
'Using <code>role="marquee"</code> (future link)',
'Using <code>role="timer"</code> (future link)',
{
id: "ARIA18",
Expand Down
162 changes: 162 additions & 0 deletions working-examples/aria-role-status-progressbar/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Working example - Using the ARIA progressbar role with a status message</title>
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<style>
:root{
background: #fff;
color:#000;
font:100% / 1.5 system-ui;
}

button{
background: #0054AE;
border:1px solid transparent;
color:#fff;
font:inherit;
&[aria-disabled=true]{
background: #E9E9E9;
color: #696969;
cursor: not-allowed;
}
&:focus-visible{
outline:2px solid #0054AE;
outline-offset: 2px;
}
}

.upload-container {
max-width: 400px;
margin: 20px 0;
}

#upload-progress {
background-color: #f0f0f0;
border: 1px solid #808080;
border-radius: 4px;
height: 20px;
max-width: 500px;
overflow: hidden;
position: relative;
--width: 0%;
}

#upload-progress::before {
background-color: #653171;
content: '';
height: 100%;
left: 0;
position: absolute;
top: 0;
transition: width 0.8s ease-in-out;
width: var(--width);
}

@media (prefers-reduced-motion: reduce) {
#upload-progress::before {
transition: none;
}
}

#upload-progress-label{
margin-block-end:0;
}

#progress-text {
font-size: 0.875em;
margin:0;
}

#start-upload {
padding: 8px 16px;
margin-top: 10px;
}
</style>
</head>
<body>
<h1>Working example - Using the ARIA <code>progressbar</code> role with a status message</h1>
<p>This working example relates to technique XXXXXX</p>

<div class="upload-container">
<p id="upload-progress-label">Uploading document: <strong>report.pdf</strong></p>
<div
aria-labelledby="upload-progress-label"
role="progressbar"
aria-describedby="progress-text"
aria-valuemin="0"
aria-valuemax="100"
aria-valuenow="0"
id="upload-progress">
</div>
<p id="progress-text" aria-live="polite">0% complete</p>
<button id="start-upload" type="button">Start Upload</button>
</div>

<script>
function startUpload() {
const progressBar = document.getElementById('upload-progress');
const progressText = document.getElementById('progress-text');
const startButton = document.getElementById('start-upload');

// Non-uniform progress intervals: 0 → 15 → 35 → 70 → 90 → 100
const progressSteps = [0, 15, 35, 70, 90, 100];
const timeIntervals = [0, 800, 2000, 1500, 800, 1800]; // Different timing for each step

let currentStep = 0;
startButton.setAttribute('aria-disabled', 'true');

function updateProgress() {
if (currentStep < progressSteps.length) {
const progress = progressSteps[currentStep];

// Update ARIA attributes
progressBar.setAttribute('aria-valuenow', progress);

// Update visual progress using CSS custom property for smooth animation
progressBar.style.setProperty('--width', progress + '%');

// Update text after animation completes (only if motion is preferred)
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const delay = prefersReducedMotion ? 0 : 800; // No delay if reduced motion is preferred

if (progress === 100) {
// Wait for the animation to complete before showing final text
setTimeout(() => {
progressText.textContent = 'Upload complete!';
}, delay);
} else {
// Wait for the animation to complete before showing progress text
setTimeout(() => {
progressText.textContent = progress + '%';
}, delay);
}

currentStep++;

if (currentStep < progressSteps.length) {
setTimeout(updateProgress, timeIntervals[currentStep]);
}
}
}

// Start the progress simulation
updateProgress();
}

// Add event listener instead of onclick
document.addEventListener('DOMContentLoaded', function() {
const startButton = document.getElementById('start-upload');
startButton.addEventListener('click', function(event) {
// Ignore click events when button is aria-disabled
if (startButton.getAttribute('aria-disabled') === 'true') {
event.preventDefault();
return;
}
startUpload();
});
});
</script>
</body>
</html>
Loading