Skip to content

Commit ba860a9

Browse files
fix(ui): add close functionality for search input
Adds multiple ways to dismiss the expanded mobile search on subpages: - Click outside the header to close - Press Escape key to close - Click the X close button Fixes #1881
1 parent 87f3aaf commit ba860a9

3 files changed

Lines changed: 47 additions & 11 deletions

File tree

app/components/AppHeader.vue

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import { onClickOutside } from '@vueuse/core'
23
import { LinkBase } from '#components'
34
import type { NavigationConfig, NavigationConfigWithGroups } from '~/types'
45
import { isEditableElement } from '~/utils/input'
@@ -143,6 +144,7 @@ const route = useRoute()
143144
const isMobile = useIsMobile()
144145
const isSearchExpandedManually = shallowRef(false)
145146
const searchBoxRef = useTemplateRef('searchBoxRef')
147+
const headerRef = useTemplateRef('headerRef')
146148
147149
// On search page, always show search expanded on mobile
148150
const isOnHomePage = computed(() => route.name === 'index')
@@ -156,6 +158,21 @@ function expandMobileSearch() {
156158
})
157159
}
158160
161+
function collapseMobileSearch() {
162+
if (!isMobile.value) return
163+
if (isOnSearchPage.value) return
164+
isSearchExpandedManually.value = false
165+
if (document.activeElement instanceof HTMLElement) {
166+
document.activeElement.blur()
167+
}
168+
}
169+
170+
onClickOutside(headerRef, () => {
171+
if (isMobile.value && isSearchExpanded.value && !isOnSearchPage.value) {
172+
collapseMobileSearch()
173+
}
174+
})
175+
159176
watch(
160177
isOnSearchPage,
161178
visible => {
@@ -171,13 +188,6 @@ watch(
171188
172189
function handleSearchBlur() {
173190
showFullSearch.value = false
174-
// Collapse expanded search on mobile after blur (with delay for click handling)
175-
// But don't collapse if we're on the search page
176-
if (isMobile.value && !isOnSearchPage.value) {
177-
setTimeout(() => {
178-
isSearchExpandedManually.value = false
179-
}, 150)
180-
}
181191
}
182192
183193
function handleSearchFocus() {
@@ -200,10 +210,22 @@ onKeyStroke(
200210
},
201211
{ dedupe: true },
202212
)
213+
214+
onKeyStroke(
215+
e =>
216+
isKeyWithoutModifiers(e, 'Escape') &&
217+
isMobile.value &&
218+
isSearchExpanded.value &&
219+
!isOnSearchPage.value,
220+
e => {
221+
e.preventDefault()
222+
collapseMobileSearch()
223+
},
224+
)
203225
</script>
204226

205227
<template>
206-
<header class="sticky top-0 z-50 border-b border-border">
228+
<header ref="headerRef" class="sticky top-0 z-50 border-b border-border">
207229
<div class="absolute inset-0 bg-bg/80 backdrop-blur-md" />
208230
<nav
209231
:aria-label="$t('nav.main_navigation')"
@@ -301,15 +323,25 @@ onKeyStroke(
301323

302324
<!-- Mobile: Search button (expands search) -->
303325
<ButtonBase
326+
v-if="!isSearchExpanded && !isOnHomePage"
304327
type="button"
305328
class="sm:hidden ms-auto"
306329
:aria-label="$t('nav.tap_to_search')"
307-
:aria-expanded="showMobileMenu"
330+
:aria-expanded="isSearchExpanded"
308331
@click="expandMobileSearch"
309-
v-if="!isSearchExpanded && !isOnHomePage"
310332
classicon="i-lucide:search"
311333
/>
312334

335+
<!-- Mobile: Close search button (collapses search) -->
336+
<ButtonBase
337+
v-if="isSearchExpanded && !isOnSearchPage"
338+
type="button"
339+
class="sm:hidden flex-shrink-0"
340+
:aria-label="$t('nav.close_search')"
341+
@click="collapseMobileSearch"
342+
classicon="i-lucide:x"
343+
/>
344+
313345
<!-- Mobile: Menu button (always visible, click to open menu) -->
314346
<ButtonBase
315347
type="button"

i18n/locales/en.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,8 @@
8383
"mobile_menu": "Navigation menu",
8484
"open_menu": "Open menu",
8585
"links": "Links",
86-
"tap_to_search": "Tap to search"
86+
"tap_to_search": "Tap to search",
87+
"close_search": "Close search"
8788
},
8889
"blog": {
8990
"title": "Blog",

i18n/schema.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@
255255
},
256256
"tap_to_search": {
257257
"type": "string"
258+
},
259+
"close_search": {
260+
"type": "string"
258261
}
259262
},
260263
"additionalProperties": false

0 commit comments

Comments
 (0)