fx-compat: Make color picker CE accessible via keyboard and VoiceOver (#2933)

This commit is contained in:
Abe Jellinek 2023-06-17 02:43:24 -04:00 committed by GitHub
parent ffdfc73d47
commit 0a94e8fdf0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 32 deletions

View file

@ -67,6 +67,38 @@
set colors(colors) {
this.setAttribute('colors', colors.join(','));
}
get colorLabels() {
if (this.hasAttribute('color-labels')) {
return this.getAttribute('color-labels').split(',').map((label) => {
let localized;
try {
localized = Zotero.getString(label);
}
catch (e) {}
if (!localized || localized == label) {
return label;
}
else {
return localized;
}
});
}
else {
if (this.hasAttribute('colors')) {
Zotero.debug('WARNING: <color-picker> CE: Set color-labels when setting colors');
}
return [
'general.red', 'general.orange', 'general.gray',
'general.green', 'general.teal', 'general.blue',
'general.purple', 'general.violet', 'general.maroon'
].map(label => Zotero.getString(label));
}
}
set colorLabels(colorLabels) {
this.setAttribute('color-labels', colorLabels.join(','));
}
get cols() {
return this.getAttribute('cols') || 3;
@ -75,6 +107,10 @@
set cols(cols) {
this.setAttribute('cols', cols);
}
get rows() {
return Math.ceil(this.colors.length / this.cols);
}
get tileWidth() {
return this.getAttribute('tileWidth') || 24;
@ -102,13 +138,78 @@
init() {
let button = this.querySelector('.button');
let panel = this.querySelector('.panel');
let grid = this.querySelector('.grid');
button.addEventListener('keydown', (event) => {
if (event.key == ' ' || event.key == 'Enter' || event.key == 'ArrowDown') {
event.preventDefault();
this.openPopup(true);
}
});
button.addEventListener('click', () => {
grid.style.gridTemplateColumns = `repeat(${this.cols}, ${this.tileWidth}px)`;
grid.style.gridAutoRows = `${this.tileHeight}px`;
panel.openPopup(button, 'after_start', 0, 0, false, false);
this.openPopup(false);
});
}
openPopup(focus = false) {
this.buildGrid();
let button = this.querySelector('.button');
let panel = this.querySelector('.panel');
let grid = this.querySelector('.grid');
grid.style.gridTemplateColumns = `repeat(${this.cols}, ${this.tileWidth}px)`;
grid.style.gridAutoRows = `${this.tileHeight}px`;
if (focus) {
panel.addEventListener('popupshown', () => {
grid.querySelector('.grid-tile').focus();
}, { once: true });
}
panel.openPopup(button, 'after_start', 0, 0, false, false);
}
buildGrid() {
let grid = this.querySelector('.grid');
grid.innerHTML = '';
let colors = this.colors;
let colorLabels = this.colorLabels;
colors.forEach((color, i) => {
let tile = document.createElement('button');
tile.setAttribute('aria-label', colorLabels[i]);
tile.classList.add('grid-tile');
tile.style.backgroundColor = color;
tile.addEventListener('click', () => {
this.color = color;
this.querySelector('.panel').hidePopup();
});
tile.addEventListener('keydown', (event) => {
switch (event.key) {
case 'ArrowLeft':
(tile.previousElementSibling || tile.parentElement.lastElementChild).focus();
break;
case 'ArrowRight':
(tile.nextElementSibling || tile.parentElement.firstElementChild).focus();
break;
case 'ArrowUp': {
let upIndex = (Array.from(tile.parentElement.children).indexOf(tile) - this.cols)
% (this.rows * this.cols);
if (upIndex < 0) {
upIndex += this.rows * this.cols;
}
tile.parentElement.children[upIndex].focus();
break;
}
case 'ArrowDown': {
let downIndex = (Array.from(tile.parentElement.children).indexOf(tile) + this.cols)
% (this.rows * this.cols);
tile.parentElement.children[downIndex].focus();
break;
}
}
});
grid.append(tile);
});
}
@ -120,20 +221,6 @@
if (attrName == 'color') {
this.querySelector('.button-tile').style.backgroundColor = newVal;
}
else if (attrName == 'colors') {
let grid = this.querySelector('.grid');
grid.innerHTML = '';
for (let color of newVal.split(',')) {
let tile = document.createElement('div');
tile.classList.add('grid-tile');
tile.style.backgroundColor = color;
tile.addEventListener('click', () => {
this.color = color;
this.querySelector('.panel').hidePopup();
});
grid.append(tile);
}
}
else if (attrName == 'disabled') {
this.querySelector('.button').disabled = !!newVal;
}

View file

@ -52,15 +52,6 @@ var Zotero_Tag_Color_Chooser = new function() {
var colorPicker = document.getElementById('color-picker');
var tagPosition = document.getElementById('tag-position');
colorPicker.setAttribute('cols', 3);
colorPicker.setAttribute('tileWidth', 24);
colorPicker.setAttribute('tileHeight', 24);
colorPicker.colors = [
'#FF6666', '#FF8C19', '#999999',
'#5FB236', '#009980', '#2EA8E5',
'#576DD9', '#A28AE5', '#A6507B'
];
var maxTags = document.getElementById('max-tags');
maxTags.value = Zotero.getString('tagColorChooser.maxTags', Zotero.Tags.MAX_COLORED_TAGS);

View file

@ -97,13 +97,16 @@ general.insert = Insert
general.username = Username
general.password = Password
general.yellow = Yellow
general.red = Red
general.orange = Orange
general.yellow = Yellow
general.green = Green
general.teal = Teal
general.blue = Blue
general.purple = Purple
general.magenta = Magenta
general.orange = Orange
general.violet = Violet
general.maroon = Maroon
general.gray = Gray
general.operationInProgress = A Zotero operation is currently in progress.

View file

@ -1,5 +1,5 @@
color-picker {
button {
.button {
width: 38px;
height: 24px;
appearance: none;
@ -25,7 +25,8 @@ color-picker {
gap: 2px;
}
.grid-tile:hover {
.grid-tile, .grid-tile:hover {
appearance: none;
border: 0;
}