v0.0.55: 모바일 슬라이드 메뉴·우측 사이드 하단 배치
lg 미만에서 좌측 내비를 오버레이 슬라이드로 전환하고, 본문 아래에 우측 사이드를 두며 헤더·패널 여백을 보정했다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,22 +1,61 @@
|
||||
<script setup>
|
||||
const { menuOpen } = useMenuState()
|
||||
const { menuOpen, closeMenu } = useMenuState()
|
||||
|
||||
/**
|
||||
* 모바일에서 좌측 슬라이드 메뉴가 열려 있을 때 문서 스크롤을 잠근다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const syncMobileNavScrollLock = () => {
|
||||
if (!import.meta.client) {
|
||||
return
|
||||
}
|
||||
const isNarrow = window.matchMedia('(max-width: 1023px)').matches
|
||||
document.documentElement.classList.toggle('site-mobile-nav-open', Boolean(menuOpen.value && isNarrow))
|
||||
}
|
||||
|
||||
watch(menuOpen, syncMobileNavScrollLock)
|
||||
|
||||
onMounted(() => {
|
||||
syncMobileNavScrollLock()
|
||||
window.addEventListener('resize', syncMobileNavScrollLock)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', syncMobileNavScrollLock)
|
||||
if (import.meta.client) {
|
||||
document.documentElement.classList.remove('site-mobile-nav-open')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="site-shell public-layout">
|
||||
<SiteHeader class="shrink-0" />
|
||||
<div
|
||||
class="public-layout__grid mx-auto grid w-full max-w-[1294px] flex-1 grid-cols-1 bg-[var(--site-bg)] px-4 transition-[grid-template-columns,max-width] duration-300 ease-out lg:grid lg:items-start lg:px-0 lg:[grid-template-columns:287px_minmax(0,720px)_287px]"
|
||||
:class="menuOpen ? '' : 'max-w-[1007px] lg:[grid-template-columns:0_minmax(0,720px)_287px]'"
|
||||
<Transition
|
||||
enter-active-class="transition-opacity duration-200 ease-out"
|
||||
leave-active-class="transition-opacity duration-200 ease-in"
|
||||
enter-from-class="opacity-0"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<div
|
||||
v-show="menuOpen"
|
||||
class="public-layout__nav-backdrop fixed inset-x-0 top-[57px] bottom-0 z-40 bg-black/35 backdrop-blur-[2px] lg:hidden"
|
||||
aria-hidden="true"
|
||||
@click="closeMenu"
|
||||
/>
|
||||
</Transition>
|
||||
<div
|
||||
class="public-layout__grid mx-auto flex w-full max-w-[1294px] flex-1 flex-col bg-[var(--site-bg)] px-4 lg:grid lg:grid-cols-[287px_minmax(0,720px)_287px] lg:items-start lg:px-0 lg:transition-[grid-template-columns,max-width] lg:duration-300 lg:ease-out"
|
||||
:class="menuOpen ? '' : 'lg:max-w-[1007px] lg:[grid-template-columns:0_minmax(0,720px)_287px]'"
|
||||
>
|
||||
<LeftSidebar :menu-open="menuOpen" />
|
||||
<main
|
||||
class="site-main w-full overflow-x-hidden lg:w-[720px]"
|
||||
class="site-main min-w-0 w-full overflow-x-hidden lg:col-start-2 lg:row-start-1 lg:w-[720px]"
|
||||
:class="{ 'site-main--menu-closed': !menuOpen }"
|
||||
>
|
||||
<slot />
|
||||
</main>
|
||||
<RightSidebar />
|
||||
<RightSidebar class="lg:col-start-3 lg:row-start-1" />
|
||||
<LeftSidebar :menu-open="menuOpen" class="lg:col-start-1 lg:row-start-1" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,22 +1,61 @@
|
||||
<script setup>
|
||||
const { menuOpen } = useMenuState()
|
||||
const { menuOpen, closeMenu } = useMenuState()
|
||||
|
||||
/**
|
||||
* 모바일에서 좌측 슬라이드 메뉴가 열려 있을 때 문서 스크롤을 잠근다.
|
||||
* @returns {void}
|
||||
*/
|
||||
const syncMobileNavScrollLock = () => {
|
||||
if (!import.meta.client) {
|
||||
return
|
||||
}
|
||||
const isNarrow = window.matchMedia('(max-width: 1023px)').matches
|
||||
document.documentElement.classList.toggle('site-mobile-nav-open', Boolean(menuOpen.value && isNarrow))
|
||||
}
|
||||
|
||||
watch(menuOpen, syncMobileNavScrollLock)
|
||||
|
||||
onMounted(() => {
|
||||
syncMobileNavScrollLock()
|
||||
window.addEventListener('resize', syncMobileNavScrollLock)
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.removeEventListener('resize', syncMobileNavScrollLock)
|
||||
if (import.meta.client) {
|
||||
document.documentElement.classList.remove('site-mobile-nav-open')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="site-shell post-layout">
|
||||
<SiteHeader class="shrink-0" />
|
||||
<div
|
||||
class="post-layout__grid mx-auto grid w-full max-w-[1294px] flex-1 grid-cols-1 bg-[var(--site-bg)] px-4 transition-[grid-template-columns,max-width] duration-300 ease-out lg:grid lg:items-start lg:px-0 lg:[grid-template-columns:287px_minmax(0,720px)_287px]"
|
||||
:class="menuOpen ? '' : 'max-w-[1007px] lg:[grid-template-columns:0_minmax(0,720px)_287px]'"
|
||||
<Transition
|
||||
enter-active-class="transition-opacity duration-200 ease-out"
|
||||
leave-active-class="transition-opacity duration-200 ease-in"
|
||||
enter-from-class="opacity-0"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<div
|
||||
v-show="menuOpen"
|
||||
class="post-layout__nav-backdrop fixed inset-x-0 top-[57px] bottom-0 z-40 bg-black/35 backdrop-blur-[2px] lg:hidden"
|
||||
aria-hidden="true"
|
||||
@click="closeMenu"
|
||||
/>
|
||||
</Transition>
|
||||
<div
|
||||
class="post-layout__grid mx-auto flex w-full max-w-[1294px] flex-1 flex-col bg-[var(--site-bg)] px-4 lg:grid lg:grid-cols-[287px_minmax(0,720px)_287px] lg:items-start lg:px-0 lg:transition-[grid-template-columns,max-width] lg:duration-300 lg:ease-out"
|
||||
:class="menuOpen ? '' : 'lg:max-w-[1007px] lg:[grid-template-columns:0_minmax(0,720px)_287px]'"
|
||||
>
|
||||
<LeftSidebar :menu-open="menuOpen" />
|
||||
<main
|
||||
class="site-main w-full overflow-x-hidden lg:w-[720px]"
|
||||
class="site-main min-w-0 w-full overflow-x-hidden lg:col-start-2 lg:row-start-1 lg:w-[720px]"
|
||||
:class="{ 'site-main--menu-closed': !menuOpen }"
|
||||
>
|
||||
<slot />
|
||||
</main>
|
||||
<RightSidebar />
|
||||
<RightSidebar class="lg:col-start-3 lg:row-start-1" />
|
||||
<LeftSidebar :menu-open="menuOpen" class="lg:col-start-1 lg:row-start-1" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user