additional focus management for popups
When a menupopup is opened, the active element does not change, so their focus-ring will be hidden until the menupopup closes for it to be less distracting. When a panel popup is opened, the focus will be moved inside of the panel, so we keep track of whichever element was previously focused, and re-focus it when the panel goes away. Minor reorganization of focus-ring mixin to use variables instead of parameters to make hiding of focus-ring easier.
This commit is contained in:
parent
1427e3e324
commit
b6d5a52417
5 changed files with 46 additions and 6 deletions
|
@ -37,6 +37,7 @@ var ZoteroPane = new function()
|
||||||
this._listeners = {};
|
this._listeners = {};
|
||||||
this.__defineGetter__('loaded', function () { return _loaded; });
|
this.__defineGetter__('loaded', function () { return _loaded; });
|
||||||
var _lastSelectedItems = [];
|
var _lastSelectedItems = [];
|
||||||
|
var lastFocusedElement = null;
|
||||||
|
|
||||||
//Privileged methods
|
//Privileged methods
|
||||||
this.destroy = destroy;
|
this.destroy = destroy;
|
||||||
|
@ -434,6 +435,28 @@ var ZoteroPane = new function()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addFocusHandlers() {
|
||||||
|
// When a menupopup shows, hide the focus ring around the currently focused element
|
||||||
|
document.addEventListener("popupshowing", (e) => {
|
||||||
|
if (e.target.tagName == "menupopup") {
|
||||||
|
document.activeElement.style.setProperty('--width-focus-border', '0');
|
||||||
|
document.activeElement.classList.add("hidden-focus");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// When a panel popup hides, refocus the previous element
|
||||||
|
// When a menupopup hides, stop hiding the focus-ring
|
||||||
|
document.addEventListener("popuphiding", e => {
|
||||||
|
if (e.target.tagName == "panel") {
|
||||||
|
ZoteroPane.lastFocusedElement.focus();
|
||||||
|
}
|
||||||
|
let noFocus = [...document.querySelectorAll(".hidden-focus")];
|
||||||
|
for (let node of noFocus) {
|
||||||
|
node.style.removeProperty('--width-focus-border');
|
||||||
|
node.classList.remove("hidden-focus");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called on window load or when pane has been reloaded after switching into or out of connector
|
* Called on window load or when pane has been reloaded after switching into or out of connector
|
||||||
|
@ -589,6 +612,7 @@ var ZoteroPane = new function()
|
||||||
catch (e) {
|
catch (e) {
|
||||||
Zotero.logError(e);
|
Zotero.logError(e);
|
||||||
}
|
}
|
||||||
|
addFocusHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1042,6 +1066,15 @@ var ZoteroPane = new function()
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handleBlur = (event) => {
|
this.handleBlur = (event) => {
|
||||||
|
// When focus shifts, unless we are inside of a panel, save
|
||||||
|
// the last focused element to be able to return focus to it when the panel closes
|
||||||
|
if (!event.target.closest("panel")) {
|
||||||
|
this.lastFocusedElement = event.target;
|
||||||
|
// Special treatment to focus on quick-search dropmarker inside of the shadow DOM
|
||||||
|
if (this.lastFocusedElement.id == "zotero-tb-search-dropmarker") {
|
||||||
|
this.lastFocusedElement = document.getElementById("zotero-tb-search")._searchModePopup.parentElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (this.highlightTimer) {
|
if (this.highlightTimer) {
|
||||||
this.highlightTimer.cancel();
|
this.highlightTimer.cancel();
|
||||||
this.highlightTimer = null;
|
this.highlightTimer = null;
|
||||||
|
|
|
@ -233,10 +233,10 @@
|
||||||
components (e.g. toolbarbutton) and sometimes are too wide (e.g. around textfield on macOS).
|
components (e.g. toolbarbutton) and sometimes are too wide (e.g. around textfield on macOS).
|
||||||
Box-shadow is used to be able to set the radius.
|
Box-shadow is used to be able to set the radius.
|
||||||
*/
|
*/
|
||||||
@mixin focus-ring($width: 1px, $radius: 5px) {
|
@mixin focus-ring {
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: none;
|
outline: none;
|
||||||
box-shadow: 0 0 0 $width -moz-accent-color;
|
box-shadow: 0 0 0 var(--width-focus-border) -moz-accent-color;
|
||||||
border-radius: $radius;
|
border-radius: var(--radius-focus-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
background: var(--material-sidepane);
|
background: var(--material-sidepane);
|
||||||
padding: 7px;
|
padding: 7px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
--width-focus-border: 3px;
|
||||||
|
--radius-focus-border: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-tabs-menu-filter {
|
#zotero-tabs-menu-filter {
|
||||||
|
@ -10,7 +12,7 @@
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
padding-inline-start: 5px !important;
|
padding-inline-start: 5px !important;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
@include focus-ring(3px, 5px);
|
@include focus-ring;
|
||||||
}
|
}
|
||||||
|
|
||||||
#zotero-tabs-menu-list {
|
#zotero-tabs-menu-list {
|
||||||
|
@ -18,7 +20,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
.zotero-tabs-menu-entry {
|
.zotero-tabs-menu-entry {
|
||||||
@include focus-ring(3px, 5px);
|
@include focus-ring;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
height: 22px;
|
height: 22px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
|
@ -65,6 +65,9 @@ editable-text {
|
||||||
}
|
}
|
||||||
|
|
||||||
.input {
|
.input {
|
||||||
|
--width-focus-border: 1px;
|
||||||
|
--radius-focus-border: 5px;
|
||||||
|
|
||||||
@include focus-ring;
|
@include focus-ring;
|
||||||
// Necessary for consistent padding, even if it's actually an <input>
|
// Necessary for consistent padding, even if it's actually an <input>
|
||||||
-moz-default-appearance: textarea;
|
-moz-default-appearance: textarea;
|
||||||
|
|
|
@ -7,6 +7,8 @@ item-box {
|
||||||
&[hidden] {
|
&[hidden] {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
--width-focus-border: 1px;
|
||||||
|
--radius-focus-border: 5px;
|
||||||
|
|
||||||
#item-box {
|
#item-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
Loading…
Reference in a new issue