Skip to content

Commit d456652

Browse files
authored
Merge pull request #12226 from ethereum/menu-number-shortcut
Keyboard nav: nav menu number shortcuts
2 parents 149dc97 + 6c616c7 commit d456652

File tree

3 files changed

+34
-7
lines changed

3 files changed

+34
-7
lines changed

src/components/Nav/Menu/index.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import * as NavigationMenu from "@radix-ui/react-navigation-menu"
44

55
import { Button } from "@/components/Buttons"
66

7-
import { NAV_PY, SECTION_LABELS } from "@/lib/constants"
7+
import { MAIN_NAV_ID, NAV_PY, SECTION_LABELS } from "@/lib/constants"
88

99
import type { NavSections } from "../types"
1010

@@ -35,7 +35,12 @@ const Menu = ({ sections, ...props }: NavMenuProps) => {
3535
delayDuration={0}
3636
>
3737
<NavigationMenu.List asChild>
38-
<UnorderedList display="flex" listStyleType="none" m="0">
38+
<UnorderedList
39+
id={MAIN_NAV_ID}
40+
display="flex"
41+
listStyleType="none"
42+
m="0"
43+
>
3944
{SECTION_LABELS.map((sectionKey) => {
4045
const { label, items } = sections[sectionKey]
4146
const isActive = activeSection === sectionKey

src/components/Nav/Menu/useNavMenu.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { useState } from "react"
22
import type { MotionProps } from "framer-motion"
3+
import { useEventListener } from "@chakra-ui/react"
4+
5+
import { MAIN_NAV_ID, SECTION_LABELS } from "@/lib/constants"
36

47
import type { NavSectionKey, NavSections } from "../types"
58

@@ -11,6 +14,25 @@ export const useNavMenu = (sections: NavSections) => {
1114
const menuColors = useNavMenuColors()
1215
const [activeSection, setActiveSection] = useState<NavSectionKey | null>(null)
1316

17+
// Focus corresponding nav section when number keys pressed
18+
useEventListener("keydown", (event) => {
19+
if (!document || !event.key.match(/[1-9]/)) return
20+
if (event.target instanceof HTMLInputElement) return
21+
if (event.target instanceof HTMLTextAreaElement) return
22+
if (event.target instanceof HTMLSelectElement) return
23+
24+
const sectionIdx = parseInt(event.key) - 1
25+
if (sectionIdx >= SECTION_LABELS.length) return
26+
27+
const button = document.querySelector(
28+
`#${MAIN_NAV_ID} li:nth-of-type(${sectionIdx + 1}) button`
29+
)
30+
if (!button) return
31+
32+
event.preventDefault()
33+
;(button as HTMLButtonElement).focus()
34+
})
35+
1436
const getEnglishSectionName = (
1537
activeSection: string
1638
): NavSectionKey | null => {

src/lib/constants.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,6 @@ export const RANGES = ["30d", "90d"] as const
7272
export const BEACONCHA_IN_URL = "https://beaconcha.in/"
7373
export const ETHERSCAN_API_URL = "https://api.etherscan.io"
7474

75-
export const NAV_BAR_PX_HEIGHT = "75px"
76-
export const FROM_QUERY = "from"
77-
7875
// Wallets
7976
export const NUMBER_OF_SUPPORTED_LANGUAGES_SHOWN = 5
8077

@@ -130,6 +127,11 @@ export const DEVELOPER_FEATURES = [
130127
* Navigation
131128
*/
132129

130+
export const MAIN_NAV_ID = "main-navigation"
131+
export const NAV_BAR_PX_HEIGHT = "75px"
132+
export const FROM_QUERY = "from"
133+
export const NAV_PY = 4
134+
133135
// Determines the order of sections in the menu
134136
export const SECTION_LABELS: NavSectionKey[] = [
135137
"learn",
@@ -141,5 +143,3 @@ export const SECTION_LABELS: NavSectionKey[] = [
141143

142144
// Glossary Definition Component
143145
export const DEFAULT_GLOSSARY_NS = "glossary"
144-
145-
export const NAV_PY = 4

0 commit comments

Comments
 (0)