Skip to content

Commit 999c9d6

Browse files
Adds a v shortcut to open/focus the version select (#1916)
1 parent 5a38916 commit 999c9d6

File tree

3 files changed

+61
-12
lines changed

3 files changed

+61
-12
lines changed

assets/js/keyboard-shortcuts.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { isAppleOS, qs } from './helpers'
2-
import { toggleSidebar } from './sidebar/sidebar-drawer'
2+
import { isSidebarOpened, openSidebar, toggleSidebar } from './sidebar/sidebar-drawer'
3+
import { openVersionSelect } from './sidebar/sidebar-version-select'
34
import { focusSearchInput } from './search-bar'
45
import { cycleTheme } from './theme'
56
import { openQuickSwitchModal } from './quick-switch'
@@ -34,6 +35,11 @@ export const keyboardShortcuts = [
3435
hasModifier: true,
3536
action: searchKeyAction
3637
},
38+
{
39+
key: 'v',
40+
description: 'Open/focus version select',
41+
action: versionKeyAction
42+
},
3743
{
3844
key: 'g',
3945
description: 'Search HexDocs package',
@@ -68,7 +74,7 @@ function addEventListeners () {
6874

6975
function handleKeyDown (event) {
7076
if (state.shortcutBeingPressed) { return }
71-
if (event.target.matches('input, textarea')) { return }
77+
if (event.target.matches('input, select, textarea')) { return }
7278

7379
const matchingShortcut = keyboardShortcuts.find(shortcut => {
7480
if (shortcut.hasModifier) {
@@ -101,6 +107,16 @@ function searchKeyAction (event) {
101107
focusSearchInput()
102108
}
103109

110+
function versionKeyAction () {
111+
closeModal()
112+
113+
if (isSidebarOpened()) {
114+
openVersionSelect()
115+
} else {
116+
openSidebar().then(openVersionSelect)
117+
}
118+
}
119+
104120
function toggleHelpModal () {
105121
if (isHelpModalOpen()) {
106122
closeModal()

assets/js/sidebar/sidebar-drawer.js

+17-10
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ function isSidebarOpen () {
126126
)
127127
}
128128

129+
/**
130+
* Returns if sidebar is fully open.
131+
*/
132+
export function isSidebarOpened () {
133+
return document.body.classList.contains(SIDEBAR_CLASS.opened)
134+
}
135+
129136
/**
130137
* Opens the sidebar by applying an animation.
131138
*
@@ -136,13 +143,13 @@ export function openSidebar () {
136143
sessionStorage.setItem('sidebar_state', 'opened')
137144
qs(SIDEBAR_TOGGLE_SELECTOR).setAttribute('aria-expanded', 'true')
138145

139-
requestAnimationFrame(() => {
140-
setClass(SIDEBAR_CLASS.openingStart)
141-
146+
return new Promise((resolve, reject) => {
142147
requestAnimationFrame(() => {
143-
setClass(SIDEBAR_CLASS.opening)
148+
setClass(SIDEBAR_CLASS.openingStart)
149+
150+
requestAnimationFrame(() => {
151+
setClass(SIDEBAR_CLASS.opening)
144152

145-
return new Promise((resolve, reject) => {
146153
state.togglingTimeout = setTimeout(() => {
147154
setClass(SIDEBAR_CLASS.opened)
148155
resolve()
@@ -162,13 +169,13 @@ export function closeSidebar () {
162169
sessionStorage.setItem('sidebar_state', 'closed')
163170
qs(SIDEBAR_TOGGLE_SELECTOR).setAttribute('aria-expanded', 'false')
164171

165-
requestAnimationFrame(() => {
166-
setClass(SIDEBAR_CLASS.closingStart)
167-
172+
return new Promise((resolve, reject) => {
168173
requestAnimationFrame(() => {
169-
setClass(SIDEBAR_CLASS.closing)
174+
setClass(SIDEBAR_CLASS.closingStart)
175+
176+
requestAnimationFrame(() => {
177+
setClass(SIDEBAR_CLASS.closing)
170178

171-
return new Promise((resolve, reject) => {
172179
state.togglingTimeout = setTimeout(() => {
173180
setClass(SIDEBAR_CLASS.closed)
174181
resolve()

assets/js/sidebar/sidebar-version-select.js

+26
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,29 @@ function handleVersionSelected (event) {
7070
}
7171
})
7272
}
73+
74+
/**
75+
* Opens the version select if available.
76+
* Only focuses the version select if
77+
* - the browser's HTMLSelectElement lacks the showPicker method
78+
* - there has been transient user interaction
79+
*/
80+
export function openVersionSelect () {
81+
const select = qs(VERSIONS_DROPDOWN_SELECTOR)
82+
83+
if (select) {
84+
select.focus()
85+
86+
// Prevent subsequent 'v' press from submitting form
87+
select.addEventListener('keydown', event => {
88+
if (event.key === 'Escape' || event.key === 'v') {
89+
event.preventDefault()
90+
select.blur()
91+
}
92+
})
93+
94+
if (navigator.userActivation.isActive && 'showPicker' in HTMLSelectElement.prototype) {
95+
select.showPicker()
96+
}
97+
}
98+
}

0 commit comments

Comments
 (0)