Skip to content

Commit 829031b

Browse files
navya9singhCopilot
andcommitted
fix: prevent keyboard focus on hidden sidebar items
When the sidebar is collapsed on small screens, its interactive elements (links, buttons) could still receive keyboard focus because they were only hidden via margin-left offset. Changes: - Add visibility: hidden to collapsed sidebar state and visibility: visible to the .show state in Sidebar.scss for CSS-level hiding - Use the inert attribute in the JS toggle handler to immediately remove sidebar items from the tab order and accessibility tree on close, eliminating the 300ms transition window where items remain focusable - Move focus back to the toggle button when closing the sidebar - Add a useEffect in the Sidebar component to set inert initially on mobile viewports, with a media query listener for responsive behavior Fixes Bug 2737380 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 32433bc commit 829031b

2 files changed

Lines changed: 23 additions & 0 deletions

File tree

packages/typescriptlang-org/src/components/layout/Sidebar.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ nav#sidebar {
209209
z-index: $z-index-for-handbook-nav;
210210
margin-left: -800px;
211211
width: 90%;
212+
visibility: hidden;
212213

213214
ul {
214215
padding-bottom: 200px;
@@ -223,6 +224,7 @@ nav#sidebar {
223224

224225
&.show {
225226
margin-left: 0px;
227+
visibility: visible;
226228
}
227229

228230
& > ul > li,

packages/typescriptlang-org/src/components/layout/Sidebar.tsx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,15 @@ const toggleNavigationSection: MouseEventHandler = (event) => {
4444
export const SidebarToggleButton = () => {
4545
const toggleClick = () => {
4646
const navSidebar = document.getElementById("sidebar")
47+
const toggleButton = document.getElementById("small-device-button-sidebar")
4748
const isOpen = navSidebar?.classList.contains("show")
4849
if (isOpen) {
4950
navSidebar?.classList.remove("show")
51+
navSidebar?.setAttribute("inert", "")
52+
toggleButton?.focus()
5053
} else {
5154
navSidebar?.classList.add("show")
55+
navSidebar?.removeAttribute("inert")
5256
}
5357
}
5458

@@ -127,6 +131,23 @@ export const Sidebar = (props: Props) => {
127131
}
128132
}
129133

134+
useEffect(() => {
135+
const sidebar = document.getElementById("sidebar")
136+
if (!sidebar) return
137+
138+
const mq = window.matchMedia("(max-width: 800px)")
139+
const sync = () => {
140+
if (mq.matches && !sidebar.classList.contains("show")) {
141+
sidebar.setAttribute("inert", "")
142+
} else {
143+
sidebar.removeAttribute("inert")
144+
}
145+
}
146+
sync()
147+
mq.addEventListener("change", sync)
148+
return () => mq.removeEventListener("change", sync)
149+
}, [])
150+
130151
return (
131152
<nav aria-label="sidebar" id="sidebar">
132153
<ul>

0 commit comments

Comments
 (0)