feat. lnb컴포넌트
This commit is contained in:
@@ -6,6 +6,9 @@ import type {
|
||||
|
||||
const { locale } = useI18n()
|
||||
const gameDomain = useGetGameDomain()
|
||||
const scrollStore = useScrollStore()
|
||||
|
||||
const { isPassedStoveGnb } = storeToRefs(scrollStore)
|
||||
|
||||
const isEventNavigationOpen = ref(true)
|
||||
const eventNavigationList = ref<Record<string, EventNavigation>>({})
|
||||
@@ -51,6 +54,7 @@ onMounted(async () => {
|
||||
class="event-navigation"
|
||||
:class="{
|
||||
'is-closed': !isEventNavigationOpen,
|
||||
'is-fixed': isPassedStoveGnb,
|
||||
}"
|
||||
>
|
||||
<div class="navigation-wrapper">
|
||||
@@ -91,7 +95,10 @@ onMounted(async () => {
|
||||
|
||||
<style scoped>
|
||||
.event-navigation {
|
||||
@apply fixed top-0 left-0 bottom-0 mt-[var(--scroll-position,48px)] pt-[48px] md:pt-[64px] z-[100] transition-transform duration-300 ease-in-out;
|
||||
@apply absolute top-0 left-0 bottom-0 pt-[48px] md:pt-[64px] z-[100] transition-transform duration-300 ease-in-out;
|
||||
}
|
||||
.event-navigation.is-fixed {
|
||||
@apply fixed;
|
||||
}
|
||||
.navigation-wrapper {
|
||||
@apply relative h-full p-3 sm:p-5 sm:pr-3
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
import { onClickOutside, useWindowSize } from '@vueuse/core'
|
||||
import { useGameDataStore } from '#layers/stores/useGameDataStore'
|
||||
import type {
|
||||
GameDataValue,
|
||||
GameDataMenu,
|
||||
GameDataMenuChildren,
|
||||
GameDataResourceGroup,
|
||||
@@ -12,12 +11,15 @@ import type {
|
||||
const route = useRoute()
|
||||
const { width } = useWindowSize()
|
||||
const gameDataStore = useGameDataStore()
|
||||
const scrollStore = useScrollStore()
|
||||
|
||||
const { gameData } = storeToRefs(gameDataStore)
|
||||
const { isPassedStoveGnb } = storeToRefs(scrollStore)
|
||||
|
||||
const navAreaRef = ref<HTMLElement>()
|
||||
const startRef = ref<HTMLElement>()
|
||||
|
||||
const gameData = gameDataStore.gameData as GameDataValue
|
||||
const gnbData = gameData?.gnb
|
||||
const gnbData = gameData.value?.gnb
|
||||
const isMenuOpen = ref(false)
|
||||
const navWidth = ref(0)
|
||||
const startWidth = ref(0)
|
||||
@@ -57,9 +59,6 @@ const isNavItemActive = (gnbItem: GameDataMenu): boolean => {
|
||||
return selfActive || hasActiveChild(gnbItem.children)
|
||||
}
|
||||
|
||||
const handleMenuOpen = () => (isMenuOpen.value = true)
|
||||
const handleMenuClose = () => (isMenuOpen.value = false)
|
||||
|
||||
// navAreaRef의 넓이를 구하는 함수
|
||||
const calculateNavWidth = () => {
|
||||
if (!navAreaRef.value || !gnbData) return 0
|
||||
@@ -132,15 +131,26 @@ const calculateOverflow = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const stopClickOutside = onClickOutside(
|
||||
navAreaRef,
|
||||
() => (isMenuOpen.value = false)
|
||||
)
|
||||
const handleMenuOpen = () => {
|
||||
isMenuOpen.value = true
|
||||
scrollStore.controlScrollLock(true)
|
||||
}
|
||||
|
||||
const handleMenuClose = () => {
|
||||
isMenuOpen.value = false
|
||||
scrollStore.controlScrollLock(false)
|
||||
}
|
||||
|
||||
const isNotClickable = (gnbItem: GameDataMenu) => {
|
||||
return gnbItem.click_action_type === 0
|
||||
}
|
||||
|
||||
const has2depthButton = (gnbItem: GameDataMenu) => {
|
||||
return gnbItem.children && Object.keys(gnbItem.children).length > 0
|
||||
}
|
||||
|
||||
const stopClickOutside = onClickOutside(navAreaRef, () => handleMenuClose())
|
||||
|
||||
// 화면 크기 변경 시 오버플로우 재계산
|
||||
watch(width, () => {
|
||||
calculateOverflow()
|
||||
@@ -168,7 +178,7 @@ onBeforeUnmount(() => {
|
||||
<template>
|
||||
<header class="header">
|
||||
<BlocksStoveGnbNew class="h-[48px]" />
|
||||
<div class="game-wrap">
|
||||
<div :class="['game-wrap', { 'is-fixed': isPassedStoveGnb }]">
|
||||
<AtomsLocaleLink to="/brand" class="mx-auto md:hidden">
|
||||
<img
|
||||
:src="getImageHost(gnbData?.bi_path)"
|
||||
@@ -205,11 +215,11 @@ onBeforeUnmount(() => {
|
||||
}"
|
||||
>
|
||||
<AtomsLocaleLink
|
||||
:to="gnbItem.url_path"
|
||||
:to="isNotClickable(gnbItem) ? '#' : gnbItem.url_path"
|
||||
:target="gnbItem.link_target"
|
||||
:class="[
|
||||
'nav-1depth',
|
||||
{ 'has-link': !!gnbItem.url_path },
|
||||
{ 'has-link': !isNotClickable(gnbItem) },
|
||||
{ active: isNavItemActive(gnbItem) },
|
||||
]"
|
||||
>
|
||||
@@ -354,9 +364,13 @@ onBeforeUnmount(() => {
|
||||
@apply bg-theme-foreground text-theme-foreground-reversal relative z-[110];
|
||||
}
|
||||
.game-wrap {
|
||||
@apply fixed top-0 flex w-full h-[48px] items-center whitespace-nowrap mt-[var(--scroll-position,48px)] px-[52px] bg-theme-foreground sm:px-[72px] md:h-16 md:pl-0 md:pr-[40px]
|
||||
@apply absolute flex w-full h-[48px] items-center whitespace-nowrap px-[52px] bg-theme-foreground sm:px-[72px] md:h-16 md:pl-0 md:pr-[40px]
|
||||
before:content-[''] before:absolute before:top-0 before:left-0 before:right-0 before:h-px before:bg-theme-foreground-reversal-6;
|
||||
}
|
||||
.game-wrap.is-fixed {
|
||||
@apply fixed top-0;
|
||||
}
|
||||
|
||||
.game-logo {
|
||||
@apply mx-auto shrink-0 md:mx-0;
|
||||
}
|
||||
@@ -426,7 +440,7 @@ onBeforeUnmount(() => {
|
||||
@apply bg-theme-foreground-reversal-8 md:bg-transparent;
|
||||
}
|
||||
.nav-1depth.has-link {
|
||||
@apply hover:bg-theme-foreground-reversal-4 active:bg-theme-foreground-reversal-10 md:hover:bg-transparent md:active:bg-transparent;
|
||||
@apply cursor-pointer hover:bg-theme-foreground-reversal-4 active:bg-theme-foreground-reversal-10 md:hover:bg-transparent md:active:bg-transparent;
|
||||
}
|
||||
|
||||
.nav-2depth {
|
||||
|
||||
@@ -15,6 +15,8 @@ const props = defineProps<Props>()
|
||||
const { locale } = useI18n()
|
||||
const { getTemplateComponent } = useTemplateRegistry()
|
||||
|
||||
const pinToMain = inject('pinToMain')
|
||||
|
||||
// 개별 메타 태그 표시 여부 확인
|
||||
const shouldShowMetaTag = computed(() => props.pageData?.meta_tag_type === 2)
|
||||
|
||||
@@ -30,6 +32,9 @@ const isTemplateVisible = (template: PageDataTemplate): boolean => {
|
||||
const visibleTemplates = computed(() =>
|
||||
Object.values(props.pageData?.templates).filter(isTemplateVisible)
|
||||
)
|
||||
const isShowTopBtn = computed(() => props.pageData?.use_top_btn ?? false)
|
||||
const isShowSnsBtn = computed(() => props.pageData?.use_sns_btn ?? false)
|
||||
const isShowLnb = computed(() => props.pageData?.use_lnb ?? false)
|
||||
|
||||
// SEO 메타 태그 설정
|
||||
const setupSeoMeta = (metaTag: PageDataMetaTag) => {
|
||||
@@ -66,14 +71,21 @@ watchEffect(() => {
|
||||
>
|
||||
<component
|
||||
:is="getTemplateComponent(template.template_code)"
|
||||
:id="template.page_ver_tmpl_name_en"
|
||||
:components="template.page_ver_tmpl_json"
|
||||
:page-ver-tmpl-seq="template.page_ver_tmpl_seq"
|
||||
/>
|
||||
</template>
|
||||
<BlocksUtileContainer
|
||||
:is-show-top-btn="pageData.use_top_btn ?? false"
|
||||
:is-show-sns-btn="pageData.use_sns_btn ?? false"
|
||||
/>
|
||||
<ClientOnly>
|
||||
<BlocksLnb v-if="isShowLnb" />
|
||||
<div
|
||||
v-if="isShowTopBtn || isShowSnsBtn"
|
||||
:class="['utile-wrap', { 'is-stop': pinToMain }]"
|
||||
>
|
||||
<AtomsButtonScrollTop v-if="isShowTopBtn" />
|
||||
<AtomsButtonSns v-if="isShowSnsBtn" />
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -81,6 +93,13 @@ watchEffect(() => {
|
||||
.main-content {
|
||||
@apply relative min-h-[200px] pt-[48px] md:min-h-[800px] md:pt-[64px];
|
||||
}
|
||||
.utile-wrap {
|
||||
@apply fixed flex flex-col z-[100]
|
||||
bottom-[12px] right-[12px] gap-2 md:bottom-[40px] md:right-[40px] md:gap-3;
|
||||
}
|
||||
.utile-wrap.is-stop {
|
||||
@apply absolute;
|
||||
}
|
||||
|
||||
[data-theme='light'] {
|
||||
.main-content {
|
||||
|
||||
Reference in New Issue
Block a user