personalization: accessibility in image grids
Add role=listbox to iron-list elements, and role=option to image containers. Add aria-posinset and aria-setsize attributes so screen readers report correct size of image grids. Add aria-label for back button. Add container with role=main and aria-label of current page - "Wallpaper Collections" on main page or localized name of collection. BUG=b/192975897 TEST=use Chromevox to navigate through new wallpaper app Cq-Include-Trybots: luci.chrome.try:linux-chromeos-chrome Change-Id: If7796d4405fb41eb8910da8934b912511bbbff72 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3010318 Commit-Queue: Jeffrey Young <cowmoo@chromium.org> Reviewed-by: Tao Wu <wutao@chromium.org> Cr-Commit-Position: refs/heads/master@{#900177}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
e6ffb0cf42
commit
52af24caec
chromeos
@ -1513,6 +1513,9 @@ Try tapping the mic to ask me anything.
|
||||
<message name="IDS_PERSONALIZATION_APP_BACK_BUTTON" desc="Aria label for the back button to return to a prior page">
|
||||
Back to <ph name="PAGE_NAME">$1<ex>Wallpaper</ex></ph>
|
||||
</message>
|
||||
<message name="IDS_PERSONALIZATION_APP_WALLPAPER_COLLECTIONS" desc="Aria label for the wallpaper collections grid">
|
||||
Wallpaper Collections
|
||||
</message>
|
||||
<message name="IDS_PERSONALIZATION_APP_CURRENTLY_SET" desc="Label for the currently set user wallpaper section.">
|
||||
Currently set
|
||||
</message>
|
||||
|
@ -0,0 +1 @@
|
||||
9886a8cbb0984357b1fc02e21d4962e63972b364
|
@ -60,7 +60,8 @@ void AddStrings(content::WebUIDataSource* source) {
|
||||
{"title", IDS_PERSONALIZATION_APP_TITLE},
|
||||
{"back", IDS_PERSONALIZATION_APP_BACK_BUTTON},
|
||||
{"currentlySet", IDS_PERSONALIZATION_APP_CURRENTLY_SET},
|
||||
{"myImagesLabel", IDS_PERSONALIZATION_APP_MY_IMAGES}};
|
||||
{"myImagesLabel", IDS_PERSONALIZATION_APP_MY_IMAGES},
|
||||
{"wallpaperCollections", IDS_PERSONALIZATION_APP_WALLPAPER_COLLECTIONS}};
|
||||
source->AddLocalizedStrings(kLocalizedStrings);
|
||||
source->UseStringsJs();
|
||||
}
|
||||
|
@ -2,23 +2,34 @@
|
||||
:host {
|
||||
overflow: hidden;
|
||||
}
|
||||
#main {
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
<paper-spinner-lite active="[[imagesLoading_]]">
|
||||
</paper-spinner-lite>
|
||||
<!-- TODO(b/181697575) handle error cases and update error string to UI spec -->
|
||||
<p hidden$="[[!hasError_]]" id="error">error</p>
|
||||
<template is="dom-if" if="[[showImages_]]">
|
||||
<iron-list items="[[getImages_(hidden, images_)]]" grid>
|
||||
<template>
|
||||
<div class="photo-container">
|
||||
<div class="padding-fix">
|
||||
<template is="dom-if"
|
||||
if="[[shouldShowImage_(item, imageData_, imageDataLoading_)]]">
|
||||
<img on-click="onClickImage_" data-id$="[[getImageKey_(item)]]"
|
||||
src="[[getImageData_(item, imageData_)]]">
|
||||
</template>
|
||||
<div id="main" role="main" aria-label="[[i18n('myImagesLabel')]]">
|
||||
<iron-list items="[[getImages_(hidden, images_)]]" grid role="listbox"
|
||||
scroll-target="main"
|
||||
aria-setsize$="[[getImageCount_(hidden, images_)]]">
|
||||
<template>
|
||||
<div class="photo-container" role="option" tabindex$="[[tabIndex]]"
|
||||
aria-posinset$="[[getAriaIndex_(index)]]"
|
||||
aria-selected$="[[getAriaSelected_(item)]]">
|
||||
<div class="padding-fix">
|
||||
<template is="dom-if"
|
||||
if="[[shouldShowImage_(item, imageData_, imageDataLoading_)]]">
|
||||
<img on-click="onClickImage_" data-id$="[[getImageKey_(item)]]"
|
||||
src="[[getImageData_(item, imageData_)]]" alt="[[item.name]]">
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</iron-list>
|
||||
</template>
|
||||
</iron-list>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -124,6 +124,25 @@ export class LocalImages extends WithPersonalizationStore {
|
||||
return hidden ? [] : images;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} hidden
|
||||
* @param {!Array<!chromeos.personalizationApp.mojom.LocalImage>} images
|
||||
* @return {number}
|
||||
*/
|
||||
getImageCount_(hidden, images) {
|
||||
return this.getImages_(hidden, images).length;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO(b/192975897) compare with currently selected image to return correct
|
||||
* aria-selected attribute.
|
||||
* @param {!chromeos.personalizationApp.mojom.LocalImage} image
|
||||
* @return {string}
|
||||
*/
|
||||
getAriaSelected_(image) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {chromeos.personalizationApp.mojom.LocalImage} image
|
||||
@ -172,6 +191,16 @@ export class LocalImages extends WithPersonalizationStore {
|
||||
/** @type {!chromeos.personalizationApp.mojom.LocalImage} */ (image),
|
||||
getWallpaperProvider(), this.getStore());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} i
|
||||
* @return {number}
|
||||
*/
|
||||
getAriaIndex_(i) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(LocalImages.is, LocalImages);
|
||||
|
@ -4,5 +4,6 @@
|
||||
<!-- TODO(b/181697575) handle error cases and update error string to UI spec -->
|
||||
<p hidden$="[[!hasError_]]" id="error">error</p>
|
||||
<iframe id="collections-iframe" frameBorder="0" hidden$="[[!showCollections_]]"
|
||||
src="chrome-untrusted://personalization/untrusted/collections.html">
|
||||
src="chrome-untrusted://personalization/untrusted/collections.html"
|
||||
role="main" aria-label$="[[i18n('wallpaperCollections')]]">
|
||||
</iframe>
|
||||
|
@ -6,5 +6,6 @@
|
||||
<!-- TODO(b/181697575) handle error cases and update error string to UI spec -->
|
||||
<p hidden$="[[!hasError_]]" id="error">error</p>
|
||||
<iframe frameBorder="0" id="images-iframe" hidden$="[[!showImages_]]"
|
||||
src="chrome-untrusted://personalization/untrusted/images.html">
|
||||
src="chrome-untrusted://personalization/untrusted/images.html" role="main"
|
||||
aria-label="[[getMainAriaLabel_(collectionId, collections_)]]">
|
||||
</iframe>
|
||||
|
@ -44,6 +44,13 @@ export class WallpaperImages extends WithPersonalizationStore {
|
||||
type: String,
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {?Array<!chromeos.personalizationApp.mojom.WallpaperCollection>}
|
||||
*/
|
||||
collections_: {
|
||||
type: Array,
|
||||
},
|
||||
|
||||
/**
|
||||
* @type {!Object<string,
|
||||
* ?Array<!chromeos.personalizationApp.mojom.WallpaperImage>>}
|
||||
@ -92,6 +99,7 @@ export class WallpaperImages extends WithPersonalizationStore {
|
||||
super.connectedCallback();
|
||||
this.watch('images_', state => state.backdrop.images);
|
||||
this.watch('imagesLoading_', state => state.loading.images);
|
||||
this.watch('collections_', state => state.backdrop.collections);
|
||||
this.updateFromStore();
|
||||
}
|
||||
|
||||
@ -145,6 +153,28 @@ export class WallpaperImages extends WithPersonalizationStore {
|
||||
sendImagesFunction(iframe.contentWindow, this.images_[collectionId]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {string} collectionId
|
||||
* @param {?Array<!chromeos.personalizationApp.mojom.WallpaperCollection>}
|
||||
* collections
|
||||
* @return {string}
|
||||
*/
|
||||
getMainAriaLabel_(collectionId, collections) {
|
||||
if (!collectionId || !Array.isArray(collections)) {
|
||||
return '';
|
||||
}
|
||||
const collection =
|
||||
collections.find(collection => collection.id === collectionId);
|
||||
|
||||
if (!collection) {
|
||||
console.warn('Did not find collection matching collectionId');
|
||||
return '';
|
||||
}
|
||||
|
||||
return collection.name;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(WallpaperImages.is, WallpaperImages);
|
||||
|
@ -3,10 +3,12 @@
|
||||
margin: 12px 0;
|
||||
}
|
||||
</style>
|
||||
<iron-list items="[[tiles_]]" grid scroll-target="document">
|
||||
<iron-list items="[[tiles_]]" grid scroll-target="document" role="listbox"
|
||||
aria-setsize$="[[tiles_.length]]">
|
||||
<template>
|
||||
<div class="photo-container" data-id$="[[item.id]]"
|
||||
on-click="onCollectionClicked_">
|
||||
on-click="onCollectionClicked_" tabindex$="[[tabIndex]]" role="option"
|
||||
aria-posinset$="[[getAriaIndex_(index)]]" aria-selected="false">
|
||||
<div class="padding-fix">
|
||||
<template is="dom-if" if="[[item.preview]]">
|
||||
<img src="[[item.preview.url]]">
|
||||
|
@ -232,6 +232,15 @@ class CollectionsGrid extends PolymerElement {
|
||||
}
|
||||
selectCollection(window.parent, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} i
|
||||
* @return {number}
|
||||
*/
|
||||
getAriaIndex_(i) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(CollectionsGrid.is, CollectionsGrid);
|
||||
|
@ -3,12 +3,15 @@
|
||||
margin: 12px 0;
|
||||
}
|
||||
</style>
|
||||
<iron-list scroll-target="document" grid items="[[images_]]">
|
||||
<iron-list scroll-target="document" grid items="[[images_]]" role="listbox"
|
||||
aria-setsize$="[[images_.length]]">
|
||||
<template>
|
||||
<div class="photo-container">
|
||||
<div class="photo-container" tabindex$="[[tabIndex]]" role="option"
|
||||
aria-posinset$="[[getAriaIndex_(index)]]"
|
||||
aria-selected$="[[getAriaSelected_(item)]]">
|
||||
<div class="padding-fix">
|
||||
<img data-id$="[[item.assetId]]" src="[[item.url.url]]"
|
||||
on-click="onImageClicked_">
|
||||
on-click="onImageClicked_" alt$="[[getImgAlt_(item)]]">
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -68,6 +68,16 @@ class ImagesGrid extends PolymerElement {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO(b/192975897) compare with currently selected image to return correct
|
||||
* aria-selected attribute.
|
||||
* @param {!chromeos.personalizationApp.mojom.LocalImage} image
|
||||
* @return {string}
|
||||
*/
|
||||
getAriaSelected_(image) {
|
||||
return 'false';
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify trusted code that a user clicked on an image.
|
||||
* @private
|
||||
@ -77,6 +87,24 @@ class ImagesGrid extends PolymerElement {
|
||||
const img = e.currentTarget;
|
||||
selectImage(window.parent, BigInt(img.dataset.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {!chromeos.personalizationApp.mojom.WallpaperImage} image
|
||||
* @return {string}
|
||||
*/
|
||||
getImgAlt_(image) {
|
||||
return image.attribution.join(' ');
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param {number} i
|
||||
* @return {number}
|
||||
*/
|
||||
getAriaIndex_(i) {
|
||||
return i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define(ImagesGrid.is, ImagesGrid);
|
||||
|
Reference in New Issue
Block a user