Skip to content

Commit 25bfc35

Browse files
hyochanclaude
andcommitted
fix(docs): unmount mobile sidebar toggle while drawer is open
The portaled toggle stayed in the DOM with `.hidden { opacity: 0; pointer-events: none }` while the drawer was open, but on iOS Safari the fixed button at top: 70px still absorbed taps that landed on the drawer's first menu items ("APIs" header at y≈88-120px). Returning null from the conditional removes the element entirely so drawer items underneath get every tap. Also bumps baseline-browser-mapping to ^2.10.22 to silence the "data is over two months old" warning from browserslist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e24297e commit 25bfc35

3 files changed

Lines changed: 43 additions & 35 deletions

File tree

bun.lock

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@typescript-eslint/parser": "^8.39.1",
3737
"@vitejs/plugin-react": "^4.3.1",
3838
"babel-plugin-react-compiler": "^19.1.0-rc.2",
39+
"baseline-browser-mapping": "^2.10.22",
3940
"eslint": "^9.21.0",
4041
"eslint-plugin-react-hooks": "^5.1.0",
4142
"eslint-plugin-react-refresh": "^0.4.7",

packages/docs/src/pages/docs/index.tsx

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -153,40 +153,44 @@ function Docs() {
153153
}, []);
154154

155155
// Portal the sidebar toggle to document.body so it sits OUTSIDE any
156-
// ancestor's stacking context. Several earlier rounds of "z-index 9001
157-
// should beat the top nav's 100" still left the docs Menu button
158-
// un-tappable on mobile WebKit because some ancestor of
159-
// `.docs-container` (.main-content / .layout) was apparently painting
160-
// its own stacking layer below the navigation. Rendering at body root
161-
// makes the toggle a true top-level fixed element, immune to that.
162-
const sidebarToggle = createPortal(
163-
<button
164-
type="button"
165-
className={`docs-sidebar-toggle ${isSidebarOpen ? 'hidden' : ''} ${isScrolled ? 'scrolled' : ''}`}
166-
onClick={(event) => {
167-
event.stopPropagation();
168-
setIsSidebarOpen((open) => !open);
169-
}}
170-
aria-label="Toggle sidebar"
171-
>
172-
<svg
173-
width="20"
174-
height="20"
175-
viewBox="0 0 20 20"
176-
fill="none"
177-
xmlns="http://www.w3.org/2000/svg"
178-
>
179-
<path
180-
d="M3 5h14M3 10h14M3 15h14"
181-
stroke="currentColor"
182-
strokeWidth="2"
183-
strokeLinecap="round"
184-
/>
185-
</svg>
186-
<span>Menu</span>
187-
</button>,
188-
document.body
189-
);
156+
// ancestor's stacking context, AND fully unmount it while the drawer
157+
// is open. Earlier rounds left the toggle in the DOM with
158+
// `.hidden { opacity: 0; pointer-events: none }` while the drawer was
159+
// open, which on iOS Safari still let the toggle absorb taps that
160+
// landed on the drawer's first menu item ("APIs" header sits at
161+
// y≈88-120px, exactly where the fixed toggle at top: 70px lives).
162+
// Removing the element from the DOM entirely guarantees the drawer
163+
// items underneath get every tap they should.
164+
const sidebarToggle = isSidebarOpen
165+
? null
166+
: createPortal(
167+
<button
168+
type="button"
169+
className={`docs-sidebar-toggle ${isScrolled ? 'scrolled' : ''}`}
170+
onClick={(event) => {
171+
event.stopPropagation();
172+
setIsSidebarOpen(true);
173+
}}
174+
aria-label="Toggle sidebar"
175+
>
176+
<svg
177+
width="20"
178+
height="20"
179+
viewBox="0 0 20 20"
180+
fill="none"
181+
xmlns="http://www.w3.org/2000/svg"
182+
>
183+
<path
184+
d="M3 5h14M3 10h14M3 15h14"
185+
stroke="currentColor"
186+
strokeWidth="2"
187+
strokeLinecap="round"
188+
/>
189+
</svg>
190+
<span>Menu</span>
191+
</button>,
192+
document.body
193+
);
190194

191195
return (
192196
<div className="docs-container">

0 commit comments

Comments
 (0)