Skip to content

Commit b3bb169

Browse files
sfanahataShannon Anahata
andauthored
bug(search): Restored search on mobile layout (#17123)
## DESCRIBE YOUR PR Search was missing from the mobile layout. This brings it back. ## IS YOUR CHANGE URGENT? Help us prioritize incoming PRs by letting us know when the change needs to go live. - [x] Urgent deadline (GA date, etc.): ASAP - [ ] Other deadline: <!-- ENTER DATE HERE --> - [ ] None: Not urgent, can wait up to 1 week+ ## SLA - Teamwork makes the dream work, so please add a reviewer to your PRs. - Please give the docs team up to 1 week to review your PR unless you've added an urgent due date to it. Thanks in advance for your help! ## PRE-MERGE CHECKLIST *Make sure you've checked the following before merging your changes:* - [ ] Checked Vercel preview for correctness, including links - [ ] PR was reviewed and approved by any necessary SMEs (subject matter experts) - [ ] PR was reviewed and approved by a member of the [Sentry docs team](https://github.com/orgs/getsentry/teams/docs) --------- Co-authored-by: Shannon Anahata <shannonanahata@gmail.com>
1 parent a0c6917 commit b3bb169

File tree

2 files changed

+108
-4
lines changed

2 files changed

+108
-4
lines changed

src/components/header.tsx

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
'use client';
22

3-
import {Cross1Icon, HamburgerMenuIcon} from '@radix-ui/react-icons';
3+
import {Cross1Icon, HamburgerMenuIcon, MagnifyingGlassIcon} from '@radix-ui/react-icons';
44
import {Button} from '@radix-ui/themes';
55
import dynamic from 'next/dynamic';
66
import Image from 'next/image';
@@ -51,6 +51,7 @@ export function Header({
5151
const [homeSearchVisible, setHomeSearchVisible] = useState(true);
5252
const [homeMobileNavOpen, setHomeMobileNavOpen] = useState(false);
5353
const [sidebarOpen, setSidebarOpen] = useState(false);
54+
const [mobileSearchOpen, setMobileSearchOpen] = useState(false);
5455

5556
// Listen for home search visibility changes
5657
useHomeSearchVisibility(
@@ -59,6 +60,48 @@ export function Header({
5960
}, [])
6061
);
6162

63+
// Close mobile search overlay on navigation
64+
useEffect(() => {
65+
setMobileSearchOpen(false);
66+
}, [pathname]);
67+
68+
// Lock body scroll when mobile search overlay is open, close on resize to desktop or escape key
69+
useEffect(() => {
70+
if (mobileSearchOpen) {
71+
document.body.style.overflow = 'hidden';
72+
73+
// Close mobile search if viewport is resized to desktop width
74+
const handleResize = () => {
75+
if (window.innerWidth >= 768) {
76+
setMobileSearchOpen(false);
77+
}
78+
};
79+
80+
// Close mobile search on escape key (only if search input is empty)
81+
const handleKeyDown = (e: KeyboardEvent) => {
82+
if (e.key === 'Escape') {
83+
// Check if search input has a value - if so, let the Search component
84+
// handle the escape key to clear the query first
85+
const searchInput = document.querySelector(
86+
'.mobile-search-overlay input[type="text"]'
87+
) as HTMLInputElement | null;
88+
if (!searchInput?.value) {
89+
setMobileSearchOpen(false);
90+
}
91+
}
92+
};
93+
94+
window.addEventListener('resize', handleResize);
95+
window.addEventListener('keydown', handleKeyDown);
96+
return () => {
97+
document.body.style.overflow = '';
98+
window.removeEventListener('resize', handleResize);
99+
window.removeEventListener('keydown', handleKeyDown);
100+
};
101+
}
102+
return undefined;
103+
}, [mobileSearchOpen]);
104+
62105
// Track sidebar checkbox state for non-home pages
63106
useEffect(() => {
64107
if (isHomePage) {
@@ -109,7 +152,10 @@ export function Header({
109152
{isHomePage ? (
110153
<button
111154
className="md:hidden mr-3 flex items-center"
112-
onClick={() => setHomeMobileNavOpen(!homeMobileNavOpen)}
155+
onClick={() => {
156+
setHomeMobileNavOpen(!homeMobileNavOpen);
157+
setMobileSearchOpen(false);
158+
}}
113159
aria-label={homeMobileNavOpen ? 'Close menu' : 'Open menu'}
114160
>
115161
{homeMobileNavOpen ? (
@@ -171,8 +217,20 @@ export function Header({
171217
<div className="hidden md:block flex-1 min-w-0">
172218
<TopNavClient platforms={platforms} />
173219
</div>
174-
{/* Mobile: show Ask AI button and theme toggle (below md breakpoint) */}
220+
{/* Mobile: show search, Ask AI button and theme toggle (below md breakpoint) */}
175221
<div className="flex items-center md:hidden ml-auto gap-3">
222+
{!noSearch && (
223+
<button
224+
className="flex items-center text-[var(--foreground)] p-1.5 rounded-md hover:bg-[var(--gray-a3)] transition-colors"
225+
onClick={() => {
226+
setMobileSearchOpen(true);
227+
setHomeMobileNavOpen(false);
228+
}}
229+
aria-label="Search"
230+
>
231+
<MagnifyingGlassIcon width="20" height="20" />
232+
</button>
233+
)}
176234
<button
177235
className="kapa-ai-class flex items-center gap-1.5 text-sm font-medium text-[var(--foreground)] px-2 py-1.5 rounded-md hover:bg-[var(--gray-a3)] transition-colors"
178236
aria-label="Ask AI"
@@ -253,6 +311,38 @@ export function Header({
253311
</nav>
254312
</div>
255313
)}
314+
315+
{/* Mobile search overlay */}
316+
{mobileSearchOpen && (
317+
<div
318+
className="mobile-search-overlay md:hidden fixed inset-0 bg-[var(--gray-1)] z-50 overflow-hidden flex flex-col"
319+
style={{top: 'var(--header-height)'}}
320+
// Stop propagation to prevent Search's useOnClickOutside from dismissing results
321+
// when clicking on the overlay header or padding areas
322+
onClick={e => e.stopPropagation()}
323+
>
324+
<div className="flex flex-col flex-1 overflow-hidden px-4">
325+
<div className="flex items-center gap-2 py-4">
326+
<button
327+
onClick={() => setMobileSearchOpen(false)}
328+
className="flex items-center justify-center p-2 rounded-md hover:bg-[var(--gray-a3)] transition-colors"
329+
aria-label="Close search"
330+
>
331+
<Cross1Icon width="20" height="20" />
332+
</button>
333+
<span className="text-sm font-medium text-[var(--foreground)]">Search</span>
334+
</div>
335+
<div className="flex-1 overflow-auto">
336+
<Search
337+
path={pathname}
338+
searchPlatforms={searchPlatforms}
339+
autoFocus
340+
useStoredSearchPlatforms={useStoredSearchPlatforms}
341+
/>
342+
</div>
343+
</div>
344+
</div>
345+
)}
256346
</header>
257347
);
258348
}

src/components/search/search.module.scss

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@
7676
box-shadow 0.15s ease-in-out,
7777
min-width 0.3s ease-in-out;
7878

79+
// Prevent Safari from zooming in on input focus (requires 16px minimum)
80+
@media screen and (max-width: 768px) {
81+
font-size: 16px;
82+
}
83+
7984
&:focus {
8085
outline: 0;
8186
border-color: var(--accent-purple);
@@ -124,10 +129,19 @@
124129
border: 1px solid var(--gray-a3);
125130

126131
@media screen and (max-width: 768px) {
127-
width: calc(100vw - 4 * 1rem);
132+
width: calc(100vw - 2rem);
128133
left: auto;
129134
}
130135

136+
// Scoped styles for mobile search overlay in header
137+
:global(.mobile-search-overlay) & {
138+
position: relative;
139+
width: 100%;
140+
max-height: none;
141+
margin-top: 0.5rem;
142+
border-radius: 0.75rem;
143+
}
144+
131145
:global(.dark) & {
132146
background-color: var(--gray-2);
133147
box-shadow: 0 4px 24px 0 rgba(0, 0, 0, 0.4), 0 2px 8px 0 rgba(0, 0, 0, 0.3);

0 commit comments

Comments
 (0)