Skip to content

Commit

Permalink
Radiogroup Examples: Improve High Contrast Support and Conformance wi…
Browse files Browse the repository at this point in the history
…th APG Coding Practices (pull #1485)


Co-authored-by: Matt King <[email protected]>
Co-authored-by: Valerie Young <[email protected]>
  • Loading branch information
3 people authored Sep 1, 2020
1 parent 145097b commit adb0de5
Show file tree
Hide file tree
Showing 12 changed files with 408 additions and 538 deletions.
8 changes: 4 additions & 4 deletions aria-practices.html
Original file line number Diff line number Diff line change
Expand Up @@ -2216,8 +2216,8 @@ <h3>Radio Group</h3>
<section class="notoc">
<h4>Examples</h4>
<ul>
<li><a href="examples/radio/radio-1/radio-1.html">Radio Group Example Using Roving tabindex</a></li>
<li><a href="examples/radio/radio-2/radio-2.html">Radio Group Example Using aria-activedescendant</a></li>
<li><a href="examples/radio/radio.html">Radio Group Example Using Roving tabindex</a></li>
<li><a href="examples/radio/radio-activedescendant.html">Radio Group Example Using aria-activedescendant</a></li>
</ul>
</section>

Expand Down Expand Up @@ -6637,7 +6637,7 @@ <h3>Range properties with progress bars</h3>
<pre><code>&lt;label for="loadstatus"&gt;Loading:&lt;/label&gt;
&lt;progress id="loadstatus" max="100" value="33"&gt;&lt;/progress&gt;
</code></pre>

<p>To represent an indeterminate progress bar where the value range is unknown, omit the <code>aria-valuenow</code> attribute.</p>

<pre><code>&lt;img role="progressbar" src="spinner.gif" alt="Loading..."&gt;</code></pre>
Expand Down Expand Up @@ -6732,7 +6732,7 @@ <h3>Range properties with spin buttons</h3>
&lt;/div&gt;</code></pre>

<p>The spin button example above can be made using the native HTML <code>&lt;input type="number"></code> element.</p>

<pre><code>&lt;label&gt;Price per paperclip: $&lt;input type="number" min="0.01" value="0.5" max="2" step="0.01"&gt;&lt;/label&gt;</code></pre>
</section>
</section>
Expand Down
41 changes: 26 additions & 15 deletions examples/radio/css/radio.css
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
}

[role="radio"] {
border: 2px solid transparent;
padding: 4px;
padding-left: 30px;
padding-right: 8px;
border: 0px solid transparent;
border-radius: 5px;
display: inline-block;
position: relative;
padding: 0.125em;
padding-left: 1.5em;
padding-right: 0.5em;
cursor: default;
outline: none;
}
Expand All @@ -28,21 +28,16 @@
[role="radio"]::after {
position: absolute;
top: 50%;
left: 7px;
left: 11px;
transform: translate(-20%, -50%);
content: '';
}

[role="radio"]::before {
width: 14px;
height: 14px;
border: 1px solid hsl(0, 0%, 66%);
border: 2px solid hsl(0, 0%, 40%);
border-radius: 100%;
background-image: linear-gradient(to bottom, hsl(300, 3%, 93%), #fff 60%);
}

[role="radio"]:active::before {
background-image: linear-gradient(to bottom, hsl(300, 3%, 73%), hsl(300, 3%, 93%));
}

[role="radio"][aria-checked="true"]::before {
Expand All @@ -53,12 +48,11 @@

[role="radio"][aria-checked="true"]::after {
display: block;
border: 0.1875em solid #fff;
border: 4px solid #fff;
border-radius: 100%;
transform: translate(25%, -50%);
transform: translate(20%, -50%);
}

[role="radio"][aria-checked="mixed"]:active::before,
[role="radio"][aria-checked="true"]:active::before {
background-image: linear-gradient(to bottom, hsl(216, 80%, 57%), hsl(217, 95%, 68%) 60%);
}
Expand All @@ -68,10 +62,27 @@
}

[role="radio"].focus {
border-color: hsl(216, 94%, 73%);
padding: 2px;
padding-left: 28px;
padding-right: 6px;
border: 2px solid hsl(216, 94%, 73%);
background-color: hsl(216, 80%, 97%);
}

[role="radio"]:hover {
padding: 2px;
padding-left: 28px;
padding-right: 6px;
border: 2px solid hsl(216, 94%, 73%);
background-color: hsl(216, 80%, 92%);
}

[role="radio"].focus::before,
[role="radio"]:hover::before {
left: 9px;
}

[role="radio"][aria-checked="true"].focus::after,
[role="radio"][aria-checked="true"]:hover::after {
transform: translate(-6%, -50%);
}
157 changes: 157 additions & 0 deletions examples/radio/js/radio-activedescendant.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* This content is licensed according to the W3C Software License at
* https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
*
* File: radio-activedescendant.js
*
* Desc: Radio group widget using aria-activedescendant that implements ARIA Authoring Practices
*/

'use strict';

var RadioGroupActiveDescendant = function (groupNode) {

this.groupNode = groupNode;

this.radioButtons = [];

this.firstRadioButton = null;
this.lastRadioButton = null;

this.groupNode.addEventListener('keydown', this.handleKeydown.bind(this));
this.groupNode.addEventListener('focus', this.handleFocus.bind(this));
this.groupNode.addEventListener('blur', this.handleBlur.bind(this));

// initialize
if (!this.groupNode.getAttribute('role')) {
this.groupNode.setAttribute('role', 'radiogroup');
}

var rbs = this.groupNode.querySelectorAll('[role=radio]');

for (var i = 0; i < rbs.length; i++) {
var rb = rbs[i];
rb.addEventListener('click', this.handleClick.bind(this));
this.radioButtons.push(rb);
if (!this.firstRadioButton) {
this.firstRadioButton = rb;
}
this.lastRadioButton = rb;
}
this.groupNode.tabIndex = 0;
};

RadioGroupActiveDescendant.prototype.setChecked = function (currentItem) {
for (var i = 0; i < this.radioButtons.length; i++) {
var rb = this.radioButtons[i];
rb.setAttribute('aria-checked', 'false');
rb.classList.remove('focus');
}
currentItem.setAttribute('aria-checked', 'true');
currentItem.classList.add('focus');
this.groupNode.setAttribute('aria-activedescendant', currentItem.id);
this.groupNode.focus();
};

RadioGroupActiveDescendant.prototype.setCheckedToPreviousItem = function (currentItem) {
var index;

if (currentItem === this.firstRadioButton) {
this.setChecked(this.lastRadioButton);
}
else {
index = this.radioButtons.indexOf(currentItem);
this.setChecked(this.radioButtons[index - 1]);
}
};

RadioGroupActiveDescendant.prototype.setCheckedToNextItem = function (currentItem) {
var index;

if (currentItem === this.lastRadioButton) {
this.setChecked(this.firstRadioButton);
}
else {
index = this.radioButtons.indexOf(currentItem);
this.setChecked(this.radioButtons[index + 1]);
}
};

RadioGroupActiveDescendant.prototype.getCurrentRadioButton = function () {
var id = this.groupNode.getAttribute('aria-activedescendant');
if (!id) {
this.groupNode.setAttribute('aria-activedescendant', this.firstRadioButton.id);
return this.firstRadioButton;
}
for (var i = 0; i < this.radioButtons.length; i++) {
var rb = this.radioButtons[i];
if (rb.id === id) {
return rb;
}
}
this.groupNode.setAttribute('aria-activedescendant', this.firstRadioButton.id);
return this.firstRadioButton;
};

// Event Handlers

RadioGroupActiveDescendant.prototype.handleKeydown = function (event) {
var flag = false;

var currentItem = this.getCurrentRadioButton();
switch (event.key) {
case ' ':
case 'Enter':
this.setChecked(currentItem);
flag = true;
break;

case 'Up':
case 'ArrowUp':
case 'Left':
case 'ArrowLeft':
this.setCheckedToPreviousItem(currentItem);
flag = true;
break;

case 'Down':
case 'ArrowDown':
case 'Right':
case 'ArrowRight':
this.setCheckedToNextItem(currentItem);
flag = true;
break;

default:
break;
}

if (flag) {
event.stopPropagation();
event.preventDefault();
}
};

RadioGroupActiveDescendant.prototype.handleClick = function (event) {
this.setChecked(event.currentTarget);
};

RadioGroupActiveDescendant.prototype.handleFocus = function () {
var currentItem = this.getCurrentRadioButton();
currentItem.classList.add('focus');
};

RadioGroupActiveDescendant.prototype.handleBlur = function () {
var currentItem = this.getCurrentRadioButton();
currentItem.classList.remove('focus');
};


// Initialize radio button group using aria-activedescendant

window.addEventListener('load', function () {
var rgs = document.querySelectorAll('.radiogroup-activedescendant');
for(var i=0; i < rgs.length; i++) {
new RadioGroupActiveDescendant(rgs[i]);
}
});
Loading

0 comments on commit adb0de5

Please sign in to comment.