Commit 51196908 authored by Roman Aleksandrov's avatar Roman Aleksandrov Committed by Commit Bot

oobe-carousel: Improve UX and A11y of dots navigation.

Make dots clickable and add proper aria-labels and role.
Add aria-label to slides for better spoken feedback.

Bug: 1125620
Change-Id: I6f20d4b1e3293aa89c81d4a6da960b6fd0fb0b6d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2396084
Commit-Queue: Roman Aleksandrov <raleksandrov@google.com>
Reviewed-by: default avatarDenis Kuznetsov [CET] <antrim@chromium.org>
Cr-Commit-Position: refs/heads/master@{#805876}
parent 1d54b27d
...@@ -440,6 +440,15 @@ ...@@ -440,6 +440,15 @@
<message name="IDS_UPDATE_BATTERY_WARNING_TEXT" desc="Text of battery warning which is shown during update process if battery is running out."> <message name="IDS_UPDATE_BATTERY_WARNING_TEXT" desc="Text of battery warning which is shown during update process if battery is running out.">
Looks like your Chromebook will run out of power before the update is complete. Make sure it's charging correctly to avoid interruption. Looks like your Chromebook will run out of power before the update is complete. Make sure it's charging correctly to avoid interruption.
</message> </message>
<message name="IDS_UPDATE_SLIDE_LABEL" desc="Text of slide label for accessibility.">
Extra content <ph name="CURRENT_ELEMENT">$1<ex>1</ex></ph> out of <ph name="TOTAL_ELEMENTS">$2<ex>2</ex></ph>
</message>
<message name="IDS_UPDATE_SELECTED_BUTTON_LABEL" desc="Text of carousel selected button label for accessibility.">
Selected, extra content <ph name="CURRENT_ELEMENT">$1<ex>1</ex></ph> out of <ph name="TOTAL_ELEMENTS">$2<ex>2</ex></ph>
</message>
<message name="IDS_UPDATE_UNSELECTED_BUTTON_LABEL" desc="Text of carousel unselected button label for accessibility.">
Navigate to extra content <ph name="CURRENT_ELEMENT">$1<ex>1</ex></ph> out of <ph name="TOTAL_ELEMENTS">$2<ex>2</ex></ph>
</message>
<message name="IDS_UPDATE_COMPLETED" desc="Notification for update completed"> <message name="IDS_UPDATE_COMPLETED" desc="Notification for update completed">
System update complete. Please restart the system. System update complete. Please restart the system.
</message> </message>
......
ca0462d1b3535a4b491f9f4d6fb0e6761b746100
\ No newline at end of file
ca0462d1b3535a4b491f9f4d6fb0e6761b746100
\ No newline at end of file
81045c3fee552927e2d0a050f0e216158e9a6b31
\ No newline at end of file
...@@ -95,9 +95,9 @@ ...@@ -95,9 +95,9 @@
.slider-dot { .slider-dot {
background: var(--google-grey-200); background: var(--google-grey-200);
border-radius: 5px; border-radius: 5px;
cursor: pointer;
height: 10px; height: 10px;
margin: 5px; margin: 5px;
pointer-events: none;
transition: background 200ms; transition: background 200ms;
transition-delay: 100ms; transition-delay: 100ms;
width: 10px; width: 10px;
...@@ -105,6 +105,10 @@ ...@@ -105,6 +105,10 @@
.slider-dot[active] { .slider-dot[active] {
background: var(--google-blue-600); background: var(--google-blue-600);
} }
.slider-dot:focus {
box-shadow: 0 0 7px 1px rgba(var(--google-blue-600-rgb), .75);
outline: none;
}
.arrow-button { .arrow-button {
--cr-icon-button-fill-color: var(--google-grey-400); --cr-icon-button-fill-color: var(--google-grey-400);
...@@ -117,10 +121,13 @@ ...@@ -117,10 +121,13 @@
<div id="navigationContainer"> <div id="navigationContainer">
<cr-icon-button id="left" class="buttons" iron-icon="cr:chevron-left" <cr-icon-button id="left" class="buttons" iron-icon="cr:chevron-left"
class="arrow-button" on-click="movePrev"></cr-icon-button> class="arrow-button" on-click="movePrev"></cr-icon-button>
<div id="dotsContainer"> <div id="dotsContainer" role="radiogroup">
<template is="dom-repeat" items="[[dots]]"> <template is="dom-repeat" items="[[dots]]">
<span class="slider-dot" aria-hidden="true" <span class="slider-dot" tabindex="0" on-keypress="onKeypress_"
tabindex="-1" active$="[[isActive_(index, slideIndex)]]"></span> on-click="onClick_" active$="[[isActive_(index, slideIndex)]]"
aria-label="[[getDotLabel_(index, slideIndex)]]" aria-live="off"
aria-checked="[[isActive_(index, slideIndex)]]"
role="radio"></span>
</template> </template>
</div> </div>
<cr-icon-button id="right" class="buttons" iron-icon="cr:chevron-right" <cr-icon-button id="right" class="buttons" iron-icon="cr:chevron-right"
......
...@@ -35,6 +35,21 @@ Polymer({ ...@@ -35,6 +35,21 @@ Polymer({
value: 10, value: 10,
observer: 'restartAutoTransition_', observer: 'restartAutoTransition_',
}, },
/**
* Slide aria-label.
*/
slideLabel: String,
/**
* Selected button aria-label.
*/
selectedButtonLabel: String,
/**
* Unselected button aria-label.
*/
unselectedButtonLabel: String,
}, },
/** /**
...@@ -70,25 +85,37 @@ Polymer({ ...@@ -70,25 +85,37 @@ Polymer({
attached() { attached() {
this.removeAnimateToHandler = this.removeAnimateTo_.bind(this); this.removeAnimateToHandler = this.removeAnimateTo_.bind(this);
this.removeAnimateFromHandler = this.removeAnimateFrom_.bind(this); this.removeAnimateFromHandler = this.removeAnimateFrom_.bind(this);
this.countSlides_(); this.prepareCarousel_();
this.restartAutoTransition_(); this.restartAutoTransition_();
this.hideNonActiveSlides_(); this.hideNonActiveSlides_();
}, },
/** /**
* @private * @private
* Count slides and create dots. * Count slides and create dots. Set a11y label on slides.
*/ */
countSlides_() { prepareCarousel_() {
this.slides = this.$.slot.assignedElements(); this.slides = this.$.slot.assignedElements();
this.totalSlides = this.slides.length; this.totalSlides = this.slides.length;
let array = []; let array = [];
for (let i = 0; i < this.totalSlides; ++i) { for (let i = 0; i < this.totalSlides; ++i) {
this.slides[i].setAttribute('aria-label', this.getSlideLabel_(i));
this.slides[i].setAttribute('role', 'group');
array.push(i); array.push(i);
} }
this.dots = array; this.dots = array;
}, },
/**
* @private
* @param {number} index Index of slide.
* Returns string label for slide.
*/
getSlideLabel_(index) {
return loadTimeData.getStringF(
this.slideLabel, index + 1, this.totalSlides);
},
/** /**
* @private * @private
*/ */
...@@ -171,7 +198,6 @@ Polymer({ ...@@ -171,7 +198,6 @@ Polymer({
} }
}, },
/** /**
* @private * @private
* @param {EventTarget|null} slide * @param {EventTarget|null} slide
...@@ -276,6 +302,26 @@ Polymer({ ...@@ -276,6 +302,26 @@ Polymer({
'transitionend', this.removeAnimateFromHandler); 'transitionend', this.removeAnimateFromHandler);
}, },
/**
* @private
* @param {Event} e keypress event.
* On key press function.
*/
onKeypress_(e) {
// Space (32) and enter (13) key codes.
if (e.keyCode == 32 || e.keyCode == 13)
this.slideIndex = e.model.item;
},
/**
* @private
* @param {Event} e click event.
* On dot click function.
*/
onClick_(e) {
this.slideIndex = e.model.item;
},
/** /**
* @private * @private
* @param {number} index Index of dot. * @param {number} index Index of dot.
...@@ -285,6 +331,20 @@ Polymer({ ...@@ -285,6 +331,20 @@ Polymer({
return index == this.slideIndex; return index == this.slideIndex;
}, },
/**
* @private
* @param {number} index Index of slide.
* Returns string label for dot.
*/
getDotLabel_(index) {
if (index == this.slideIndex) {
return loadTimeData.getStringF(
this.selectedButtonLabel, index + 1, this.totalSlides);
}
return loadTimeData.getStringF(
this.unselectedButtonLabel, index + 1, this.totalSlides);
},
/** /**
* @private * @private
* @param {number} toIndex Index of slide which should be shown. * @param {number} toIndex Index of slide which should be shown.
......
...@@ -97,7 +97,10 @@ ...@@ -97,7 +97,10 @@
<div hidden="[[showLowBatteryWarning]]" id="carousel" class="slide-view" <div hidden="[[showLowBatteryWarning]]" id="carousel" class="slide-view"
slot="footer"> slot="footer">
<oobe-carousel slide-duration-in-seconds=3 <oobe-carousel slide-duration-in-seconds=3
auto-transition="[[getAutoTransition_(uiState, autoTransition)]]"> auto-transition="[[getAutoTransition_(uiState, autoTransition)]]"
slide-label="slideLabel"
selected-button-label="slideSelectedButtonLabel"
unselected-button-label="slideUnselectedButtonLabel">
<oobe-slide slot="slides"> <oobe-slide slot="slides">
<img slot="slide-img" <img slot="slide-img"
class="update-illustration oobe-illustration" class="update-illustration oobe-illustration"
......
...@@ -151,6 +151,11 @@ void UpdateScreenHandler::DeclareLocalizedValues( ...@@ -151,6 +151,11 @@ void UpdateScreenHandler::DeclareLocalizedValues(
builder->Add("batteryWarningTitle", IDS_UPDATE_BATTERY_WARNING_TITLE); builder->Add("batteryWarningTitle", IDS_UPDATE_BATTERY_WARNING_TITLE);
builder->Add("batteryWarningText", IDS_UPDATE_BATTERY_WARNING_TEXT); builder->Add("batteryWarningText", IDS_UPDATE_BATTERY_WARNING_TEXT);
builder->Add("slideLabel", IDS_UPDATE_SLIDE_LABEL);
builder->Add("slideSelectedButtonLabel", IDS_UPDATE_SELECTED_BUTTON_LABEL);
builder->Add("slideUnselectedButtonLabel",
IDS_UPDATE_UNSELECTED_BUTTON_LABEL);
#if !BUILDFLAG(GOOGLE_CHROME_BRANDING) #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
builder->Add("cancelUpdateHint", IDS_UPDATE_CANCEL); builder->Add("cancelUpdateHint", IDS_UPDATE_CANCEL);
builder->Add("cancelledUpdateMessage", IDS_UPDATE_CANCELLED); builder->Add("cancelledUpdateMessage", IDS_UPDATE_CANCELLED);
......
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