context notes list focus handling followup (#4847)

- remember the last focused note-row in the contextPane
and, if possible, refocus it on shift-tab from sidenav, on
tab from the reader into notes pane, or on tab into the
notes list from the collapsible-section. Otherwise, focus the search input.
Per: https://github.com/zotero/zotero/pull/4837#issuecomment-2478108186

- when a note is opened in the context pane, let shift-tab
from sidenav place focus on the links-box. That way,
it is not skipped during tab navigation.

- fix focus not entering note-editor on Tab from the "Go back"
button and instead wrapping around to the current tab
This commit is contained in:
abaevbog 2024-11-20 23:37:19 -08:00 committed by GitHub
parent 8c5a863aaf
commit a195750f31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 39 additions and 18 deletions

View file

@ -51,6 +51,8 @@
_numVisible = 0;
_hasParent = false;
_lastFocusedNote = null;
get notes() {
return [...this._itemNotes, ...this._allNotes];
@ -118,6 +120,7 @@
this.addEventListener('click', this._handleClick);
this.addEventListener('contextmenu', this._handleContextMenu);
this.addEventListener('keydown', this._handleKeyDown);
this.addEventListener("focusin", this._handleFocusIn);
this.render();
}
@ -152,6 +155,14 @@
}
}
refocusLastFocusedNote() {
if (this._lastFocusedNote) {
this._lastFocusedNote.focus();
return document.activeElement == this._lastFocusedNote;
}
return false;
}
_makeRow(note) {
let row = document.createXULElement('note-row');
row.note = note;
@ -184,9 +195,23 @@
}
};
// Remember which note row was last focused to be able to return focus to it
_handleFocusIn = (event) => {
if (event.target.tagName !== "note-row" && !event.target.classList.contains("more")) return;
this._lastFocusedNote = event.target;
};
// ArrowUp/Down navigation between notes
// Tab from a note-row focuses sidenav, Shift-Tab from a note focuses the section header
// Tab from twisty icon into the notes list will try to refocus the last focused note
_handleKeyDown = (event) => {
if (event.key == "Tab" && event.target.classList.contains("twisty")) {
let section = event.target.closest("collapsible-section");
if (this._lastFocusedNote && section.contains(this._lastFocusedNote)) {
this.refocusLastFocusedNote();
event.preventDefault();
}
}
if (event.target.tagName !== "note-row" && !event.target.classList.contains("more")) return;
if (event.key == "ArrowDown") {
event.target.nextElementSibling?.focus();

View file

@ -333,9 +333,7 @@
return true;
}
else if (this.mode == "notes") {
// Tab into the notes pane
Services.focus.moveFocus(window, this._getCurrentNotesContext(), Services.focus.MOVEFOCUS_FORWARD, 0);
return true;
return this._getCurrentNotesContext().focus();
}
}
return false;

View file

@ -386,19 +386,17 @@
handleKeyDown = (event) => {
if (event.key == "Tab" && !event.shiftKey) {
// Wrap focus around to the tab bar
Services.focus.moveFocus(window, document.getElementById("zotero-title-bar"), Services.focus.MOVEFOCUS_FORWARD, 0);
Zotero_Tabs.moveFocus("current");
event.preventDefault();
}
if (event.key == "Tab" && event.shiftKey) {
if (this._contextNotesPaneVisible) {
// Tab into notes pane to focus search bar
Services.focus.moveFocus(window, this._contextNotesPane, Services.focus.MOVEFOCUS_FORWARD, 0);
}
else {
// Shift-Tab out of sidenav to itemPane
Services.focus.moveFocus(window, this, Services.focus.MOVEFOCUS_BACKWARD, 0);
}
event.preventDefault();
if (this._contextNotesPaneVisible && this._contextNotesPane.selectedPanel.mode == "notesList") {
let focusHandled = this._contextNotesPane.selectedPanel.focus();
if (focusHandled) return;
}
// Shift-Tab out of sidenav to itemPane
Services.focus.moveFocus(window, this, Services.focus.MOVEFOCUS_BACKWARD, 0);
}
if (["ArrowUp", "ArrowDown"].includes(event.key)) {
// Up/Down arrow navigation

View file

@ -152,7 +152,10 @@
focus() {
if (this.mode == "notesList") {
this.input.focus();
let refocused = this.notesList.refocusLastFocusedNote();
if (!refocused) {
this.input.focus();
}
return true;
}
else {

View file

@ -1138,14 +1138,11 @@ var ZoteroPane = new function()
// Shift-tab from the header into the itemsView.
if (Services.focus.activeWindow === window && this.lastKeyPress === "Tab"
&& (itemPaneLostFocus || contextPaneLostFocus)) {
// event.relatedTarget is null when moving focus in or out of <iframe> or <browser>
// so make sure to not refocus tabs when focusing inside of note-editor or reader
if (receivingFocus) {
Zotero_Tabs.moveFocus("current");
}
// event.relatedTarget is null when the reader is opened and we need a small
// delay otherwise the focus lands within the reader
else {
setTimeout(() => Zotero_Tabs.moveFocus("current"));
}
this.lastKeyPress = null;
}
// When focus shifts, unless we are inside of a panel, save