v0.0.55: 모바일 슬라이드 메뉴·우측 사이드 하단 배치

lg 미만에서 좌측 내비를 오버레이 슬라이드로 전환하고, 본문 아래에 우측 사이드를 두며 헤더·패널 여백을 보정했다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-11 11:38:03 +09:00
parent 3916bcb284
commit 94a37f451d
13 changed files with 177 additions and 39 deletions

View File

@@ -1,5 +1,5 @@
<script setup>
const { menuOpen, toggleMenu } = useMenuState()
const { menuOpen, toggleMenu, closeMenu } = useMenuState()
const menuUserOpen = ref(false)
const userMenuRef = ref(null)
const userMenuToggleRef = ref(null)
@@ -46,19 +46,42 @@ const onDocumentClick = (event) => {
}
}
/**
* Escape로 열린 패널을 닫는다(사용자 메뉴 우선, 이어서 모바일 좌측 메뉴).
* @param {KeyboardEvent} event - 키보드 이벤트
* @returns {void}
*/
const onGlobalKeydown = (event) => {
if (event.key !== 'Escape') {
return
}
if (menuUserOpen.value) {
closeUserMenu()
return
}
if (!menuOpen.value) {
return
}
if (typeof window !== 'undefined' && window.matchMedia('(max-width: 1023px)').matches) {
closeMenu()
}
}
onMounted(() => {
document.addEventListener('click', onDocumentClick)
document.addEventListener('keydown', onGlobalKeydown)
})
onBeforeUnmount(() => {
document.removeEventListener('click', onDocumentClick)
document.removeEventListener('keydown', onGlobalKeydown)
})
</script>
<template>
<header class="site-header sticky top-0 z-20 backdrop-blur">
<div class="site-header__inner mx-auto flex h-full max-w-[1294px] items-center justify-between px-4 lg:px-0">
<NuxtLink class="site-header__brand flex items-center gap-2 text-[18px] font-semibold tracking-normal" to="/">
<div class="site-header__inner mx-auto flex h-full max-w-[1294px] items-center justify-between gap-2 px-4 sm:gap-3 lg:px-0">
<NuxtLink class="site-header__brand flex min-w-0 flex-1 items-center gap-2 text-[15px] font-semibold tracking-normal sm:text-[18px]" to="/">
<button
class="site-header__menu-toggle group flex h-7 w-7 items-center justify-center rounded-full transition-transform"
type="button"
@@ -89,15 +112,15 @@ onBeforeUnmount(() => {
</svg>
</span>
</button>
{{ siteSettings.title }}
<span class="min-w-0 truncate">{{ siteSettings.title }}</span>
</NuxtLink>
<div class="site-header__search hidden h-9 w-[470px] items-center rounded-lg px-3 text-sm md:flex site-input">
<span class="site-header__search-icon mr-2 text-lg leading-none"></span>
<span class="site-header__search-text site-soft">Search</span>
<span class="site-header__search-key ml-auto rounded-md px-2 text-xs site-soft site-input">/</span>
</div>
<nav class="site-header__nav flex items-center gap-3 text-sm">
<NuxtLink class="site-header__buy site-accent-button rounded-lg px-4 py-2 font-semibold" to="/pages/about">
<nav class="site-header__nav flex shrink-0 items-center gap-2 text-sm sm:gap-3">
<NuxtLink class="site-header__buy site-accent-button shrink-0 rounded-lg px-3 py-1.5 text-xs font-semibold sm:px-4 sm:py-2 sm:text-sm" to="/pages/about">
Subscribe
</NuxtLink>
<div class="site-header__user-menu relative">
@@ -127,7 +150,7 @@ onBeforeUnmount(() => {
<div
v-if="menuUserOpen"
ref="userMenuRef"
class="site-header__user-dropdown absolute top-12 right-0 z-30 flex min-w-[200px] max-w-xs flex-col overflow-hidden rounded-[10px] border border-[var(--site-line)] bg-[var(--site-bg)] p-3 pb-2 text-sm font-medium shadow-[0_12px_30px_rgba(0,0,0,0.12)]"
class="site-header__user-dropdown absolute top-12 right-2 z-30 flex min-w-[200px] max-w-[calc(100vw-2rem)] flex-col overflow-hidden rounded-[10px] border border-[var(--site-line)] bg-[var(--site-bg)] p-3 pb-2 text-sm font-medium shadow-[0_12px_30px_rgba(0,0,0,0.12)] sm:right-0 sm:max-w-xs"
>
<div class="mb-2 flex items-center gap-2 border-b border-[var(--site-line)] pb-3">
<div class="site-header__avatar-wrap flex h-8 w-8 items-center justify-center overflow-hidden rounded-full bg-[var(--site-panel)] md:h-10 md:w-10">