Commit ee07f7ae authored by John Lee's avatar John Lee Committed by Commit Bot

Settings WebUI: Move focus of cr-radio-buttons to inner radio button

When focusing into a cr-radio-button, the focus should be moved to the
actual button where the paper-ripple focus indicator is visible. The
host element still needs disabled/checked attributes so that parent
cr-radio-groups can still access and modify them.

Bug: 949456
Change-Id: I972065e3c5c6ce4344e34971c1d7d0e542a63262
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1564536Reviewed-by: default avatarEsmael El-Moslimany <aee@chromium.org>
Commit-Queue: John Lee <johntlee@chromium.org>
Cr-Commit-Position: refs/heads/master@{#650435}
parent 3f3a2142
......@@ -29,14 +29,25 @@
}
</style>
<div class="disc-wrapper">
<div
aria-checked$="[[getAriaChecked_(checked)]]"
aria-describedby="slotted-content"
aria-disabled$="[[getAriaDisabled_(disabled)]]"
aria-labelledby="label"
class="disc-wrapper"
id="button"
role="radio"
tabindex="0"
on-keydown="onInputKeydown_">
<div class="disc-border"></div>
<div class="disc"></div>
</div>
<div id="labelWrapper">
<span id="label" hidden$="[[!label]]">[[label]]</span>
<slot></slot>
<span id="slotted-content">
<slot></slot>
</span>
</div>
<template is="dom-if" if="[[showIndicator_(disabled, name, pref.*)]]">
......
......@@ -16,7 +16,7 @@ suite('cr-radio-button', function() {
function assertChecked() {
assertTrue(radioButton.hasAttribute('checked'));
assertEquals('true', radioButton.getAttribute('aria-checked'));
assertEquals('true', radioButton.$.button.getAttribute('aria-checked'));
assertTrue(
getComputedStyle(radioButton.$$('.disc')).backgroundColor !=
'rgba(0, 0, 0, 0)');
......@@ -24,7 +24,7 @@ suite('cr-radio-button', function() {
function assertNotChecked() {
assertFalse(radioButton.hasAttribute('checked'));
assertEquals('false', radioButton.getAttribute('aria-checked'));
assertEquals('false', radioButton.$.button.getAttribute('aria-checked'));
assertEquals(
'rgba(0, 0, 0, 0)',
getComputedStyle(radioButton.$$('.disc')).backgroundColor);
......@@ -32,14 +32,14 @@ suite('cr-radio-button', function() {
function assertDisabled() {
assertTrue(radioButton.hasAttribute('disabled'));
assertEquals('true', radioButton.getAttribute('aria-disabled'));
assertEquals('true', radioButton.$.button.getAttribute('aria-disabled'));
assertEquals('none', getComputedStyle(radioButton).pointerEvents);
assertTrue('1' != getComputedStyle(radioButton).opacity);
}
function assertNotDisabled() {
assertFalse(radioButton.hasAttribute('disabled'));
assertEquals('false', radioButton.getAttribute('aria-disabled'));
assertEquals('false', radioButton.$.button.getAttribute('aria-disabled'));
assertEquals('1', getComputedStyle(radioButton).opacity);
}
......
......@@ -10,14 +10,25 @@
<template>
<style include="cr-radio-button-style cr-hidden-style"></style>
<div class="disc-wrapper">
<div
aria-checked$="[[getAriaChecked_(checked)]]"
aria-describedby="slotted-content"
aria-disabled$="[[getAriaDisabled_(disabled)]]"
aria-labelledby="label"
class="disc-wrapper"
id="button"
role="radio"
tabindex="0"
on-keydown="onInputKeydown_">
<div class="disc-border"></div>
<div class="disc"></div>
</div>
<div id="labelWrapper">
<span id="label" hidden$="[[!label]]">[[label]]</span>
<slot></slot>
<span id="slotted-content">
<slot></slot>
</span>
</div>
</template>
<script src="cr_radio_button.js"></script>
......
......@@ -13,7 +13,6 @@ const CrRadioButtonBehaviorImpl = {
type: Boolean,
value: false,
reflectToAttribute: true,
observer: 'checkedChanged_',
},
disabled: {
......@@ -21,7 +20,6 @@ const CrRadioButtonBehaviorImpl = {
value: false,
reflectToAttribute: true,
notify: true,
observer: 'disabledChanged_',
},
label: {
......@@ -42,34 +40,11 @@ const CrRadioButtonBehaviorImpl = {
pointerup: 'cancelRipple_',
},
hostAttributes: {
'aria-disabled': 'false',
'aria-checked': 'false',
role: 'radio',
},
/** @private */
checkedChanged_: function() {
this.setAttribute('aria-checked', this.checked ? 'true' : 'false');
},
/**
* @param {boolean} current
* @param {boolean} previous
* @private
*/
disabledChanged_: function(current, previous) {
if (previous === undefined && !this.disabled) {
return;
}
this.setAttribute('aria-disabled', this.disabled ? 'true' : 'false');
},
/** @private */
onFocus_: function() {
this.ensureRipple();
this.$$('paper-ripple').holdDown = true;
this.$.button.focus();
},
/** @private */
......@@ -78,10 +53,35 @@ const CrRadioButtonBehaviorImpl = {
this.$$('paper-ripple').holdDown = false;
},
/** @private */
getAriaChecked_: function() {
return this.checked ? 'true' : 'false';
},
/** @private */
getAriaDisabled_: function() {
return this.disabled ? 'true' : 'false';
},
/**
* When shift-tab is pressed, first bring the focus to the host element.
* This accomplishes 2 things:
* 1) Host doesn't get focused when the browser moves the focus backward.
* 2) focus now escaped the shadow-dom of this element, so that it'll
* correctly obey non-zero tabindex ordering of the containing document.
* @param {!Event} e
* @private
*/
onInputKeydown_: function(e) {
if (e.shiftKey && e.key === 'Tab') {
this.focus();
}
},
// customize the element's ripple
_createRipple: function() {
this._rippleContainer = this.$$('.disc-wrapper');
let ripple = Polymer.PaperRippleBehavior._createRipple();
const ripple = Polymer.PaperRippleBehavior._createRipple();
ripple.id = 'ink';
ripple.setAttribute('recenters', '');
ripple.classList.add('circle', 'toggle-ink');
......@@ -94,4 +94,4 @@ const CrRadioButtonBehaviorImpl = {
const CrRadioButtonBehavior = [
Polymer.PaperRippleBehavior,
CrRadioButtonBehaviorImpl,
];
\ No newline at end of file
];
......@@ -86,6 +86,10 @@
border-color: var(--cr-radio-button-checked-color);
}
#button:focus {
outline: none;
}
.disc {
background-color: transparent;
position: absolute;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment