548 lines
22 KiB
Vue
548 lines
22 KiB
Vue
<template>
|
||
<header
|
||
class="relative overflow-hidden"
|
||
:class="headerClasses"
|
||
:style="{ height: `${height}px` }"
|
||
>
|
||
<div class="absolute top-0 left-0 right-0 pointer-events-none glass-topfade" :style="glassStyle" />
|
||
<!-- Single row: Logo + Search + Icons -->
|
||
<div
|
||
class="relative z-10 flex px-4 lg:px-6 gap-4"
|
||
:class="isHeroLayout ? 'items-start pt-4' : 'items-center'"
|
||
:style="rowStyle"
|
||
>
|
||
<!-- Left: Logo + Nav links (top aligned) -->
|
||
<div class="flex items-center flex-shrink-0 rounded-full glass-bright">
|
||
<div class="flex items-center gap-2 px-4 py-2">
|
||
<NuxtLink :to="localePath('/')" class="flex items-center gap-2">
|
||
<span class="font-bold text-xl" :class="useWhiteText ? 'text-white' : 'text-base-content'">Optovia</span>
|
||
</NuxtLink>
|
||
</div>
|
||
|
||
<!-- Service nav links -->
|
||
<div v-if="showModeToggle" class="w-px h-6 bg-white/20 self-center" />
|
||
<div v-if="showModeToggle" class="flex items-center px-3 py-2">
|
||
<nav class="flex items-center gap-1">
|
||
<button
|
||
class="px-3 py-1 text-sm font-medium rounded-full transition-colors"
|
||
:class="showActiveMode && catalogMode === 'explore' && !isClientArea
|
||
? (useWhiteText ? 'bg-white/20 text-white' : 'bg-base-300 text-base-content')
|
||
: (useWhiteText ? 'text-white/70 hover:text-white hover:bg-white/10' : 'text-base-content/70 hover:text-base-content hover:bg-base-200')"
|
||
@click="$emit('set-catalog-mode', 'explore')"
|
||
>
|
||
{{ $t('catalog.modes.explore') }}
|
||
</button>
|
||
<button
|
||
class="px-3 py-1 text-sm font-medium rounded-full transition-colors"
|
||
:class="showActiveMode && catalogMode === 'quote' && !isClientArea
|
||
? (useWhiteText ? 'bg-white/20 text-white' : 'bg-base-300 text-base-content')
|
||
: (useWhiteText ? 'text-white/70 hover:text-white hover:bg-white/10' : 'text-base-content/70 hover:text-base-content hover:bg-base-200')"
|
||
@click="$emit('set-catalog-mode', 'quote')"
|
||
>
|
||
{{ $t('catalog.modes.quote') }}
|
||
</button>
|
||
<!-- Role switcher: Я клиент + dropdown -->
|
||
<div v-if="loggedIn" class="flex items-center">
|
||
<NuxtLink
|
||
:to="localePath(currentRole === 'SELLER' ? '/clientarea/offers' : '/clientarea/orders')"
|
||
class="px-3 py-1 text-sm font-medium rounded-lg transition-colors"
|
||
:class="isClientArea
|
||
? (useWhiteText ? 'bg-white/20 text-white' : 'bg-base-300 text-base-content')
|
||
: (useWhiteText ? 'text-white/70 hover:text-white hover:bg-white/10' : 'text-base-content/70 hover:text-base-content hover:bg-base-200')"
|
||
>
|
||
{{ currentRole === 'SELLER' ? $t('cabinetNav.roles.seller') : $t('cabinetNav.roles.client') }}
|
||
</NuxtLink>
|
||
|
||
<!-- Dropdown для переключения роли (если есть обе роли) -->
|
||
<div v-if="hasMultipleRoles" class="dropdown dropdown-end">
|
||
<button
|
||
tabindex="0"
|
||
class="p-1 ml-0.5 transition-colors"
|
||
:class="useWhiteText ? 'text-white/50 hover:text-white' : 'text-base-content/50 hover:text-base-content'"
|
||
>
|
||
<Icon name="lucide:chevron-down" size="14" />
|
||
</button>
|
||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-50 w-48 p-2 shadow-lg border border-base-300">
|
||
<li>
|
||
<a
|
||
:class="{ active: currentRole === 'BUYER' }"
|
||
@click="$emit('switch-role', 'BUYER')"
|
||
>
|
||
{{ $t('cabinetNav.roles.client') }}
|
||
</a>
|
||
</li>
|
||
<li>
|
||
<a
|
||
:class="{ active: currentRole === 'SELLER' }"
|
||
@click="$emit('switch-role', 'SELLER')"
|
||
>
|
||
{{ $t('cabinetNav.roles.seller') }}
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Center: Search input OR Client Area tabs (vertically centered) -->
|
||
<div
|
||
class="flex-1 flex flex-col items-center max-w-2xl mx-auto gap-2 transition-all"
|
||
:class="isHeroLayout ? 'justify-start' : 'justify-center'"
|
||
:style="centerStyle"
|
||
>
|
||
<!-- Hero slot for home page title -->
|
||
<slot name="hero" />
|
||
|
||
<!-- Client Area tabs -->
|
||
<template v-if="isClientArea">
|
||
<div class="flex items-center gap-1 rounded-full glass-bright p-1">
|
||
<!-- BUYER tabs -->
|
||
<template v-if="currentRole !== 'SELLER'">
|
||
<NuxtLink
|
||
:to="localePath('/clientarea/orders')"
|
||
class="px-4 py-2 rounded-full text-sm font-medium transition-colors whitespace-nowrap"
|
||
:class="isClientAreaTabActive('/clientarea/orders') ? 'bg-primary text-primary-content' : 'text-base-content/70 hover:text-base-content hover:bg-base-200/50'"
|
||
>
|
||
{{ $t('cabinetNav.orders') }}
|
||
</NuxtLink>
|
||
<NuxtLink
|
||
:to="localePath('/clientarea/addresses')"
|
||
class="px-4 py-2 rounded-full text-sm font-medium transition-colors whitespace-nowrap"
|
||
:class="isClientAreaTabActive('/clientarea/addresses') ? 'bg-primary text-primary-content' : 'text-base-content/70 hover:text-base-content hover:bg-base-200/50'"
|
||
>
|
||
{{ $t('cabinetNav.addresses') }}
|
||
</NuxtLink>
|
||
</template>
|
||
|
||
<!-- SELLER tabs -->
|
||
<template v-else>
|
||
<NuxtLink
|
||
:to="localePath('/clientarea/offers')"
|
||
class="px-4 py-2 rounded-full text-sm font-medium transition-colors whitespace-nowrap"
|
||
:class="isClientAreaTabActive('/clientarea/offers') ? 'bg-primary text-primary-content' : 'text-base-content/70 hover:text-base-content hover:bg-base-200/50'"
|
||
>
|
||
{{ $t('cabinetNav.myOffers') }}
|
||
</NuxtLink>
|
||
</template>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- Quote mode: Simple segmented input with search inside (white glass) -->
|
||
<template v-else-if="catalogMode === 'quote'">
|
||
<div class="flex items-center w-full rounded-full glass-bright overflow-hidden">
|
||
<!-- Product segment -->
|
||
<button
|
||
class="flex-1 px-4 py-2 text-left hover:bg-base-200/50 rounded-l-full transition-colors min-w-0"
|
||
@click="$emit('edit-token', 'product')"
|
||
>
|
||
<div class="text-xs text-base-content/60">{{ $t('catalog.filters.product') }}</div>
|
||
<div class="font-medium truncate text-base-content">{{ productLabel || $t('catalog.quote.selectProduct') }}</div>
|
||
</button>
|
||
<div class="w-px h-8 bg-white/20 self-center" />
|
||
<!-- Hub segment -->
|
||
<button
|
||
class="flex-1 px-4 py-2 text-left hover:bg-base-200/50 transition-colors min-w-0"
|
||
@click="$emit('edit-token', 'hub')"
|
||
>
|
||
<div class="text-xs text-base-content/60">{{ $t('catalog.filters.hub') }}</div>
|
||
<div class="font-medium truncate text-base-content">{{ hubLabel || $t('catalog.quote.selectHub') }}</div>
|
||
</button>
|
||
<div class="w-px h-8 bg-white/20 self-center" />
|
||
<!-- Quantity segment (inline input) -->
|
||
<div class="flex-1 px-4 py-2 min-w-0">
|
||
<div class="text-xs text-base-content/60">{{ $t('catalog.filters.quantity') }}</div>
|
||
<div class="flex items-center gap-1">
|
||
<input
|
||
v-model="localQuantity"
|
||
type="number"
|
||
min="0"
|
||
step="0.1"
|
||
placeholder="—"
|
||
class="w-16 font-medium bg-transparent outline-none text-base-content [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
||
@blur="$emit('update-quantity', localQuantity)"
|
||
@keyup.enter="$emit('update-quantity', localQuantity)"
|
||
/>
|
||
<span v-if="localQuantity" class="text-base-content/60 text-sm">{{ $t('units.t') }}</span>
|
||
</div>
|
||
</div>
|
||
<!-- Search button inside -->
|
||
<button
|
||
class="btn btn-primary btn-circle m-1"
|
||
:disabled="!canSearch"
|
||
@click="$emit('search')"
|
||
>
|
||
<Icon name="lucide:search" size="18" />
|
||
</button>
|
||
</div>
|
||
</template>
|
||
|
||
<!-- Explore mode: Regular pill input + chips (white glass) -->
|
||
<template v-else>
|
||
<!-- Big pill input -->
|
||
<div
|
||
class="flex items-center gap-3 w-full px-5 py-3 rounded-full glass-bright focus-within:border-primary focus-within:ring-2 focus-within:ring-primary/20 transition-all cursor-text"
|
||
@click="focusInput"
|
||
>
|
||
<Icon name="lucide:search" size="22" class="text-primary flex-shrink-0" />
|
||
|
||
<!-- Tokens + input inline (no wrap to prevent height change) -->
|
||
<div class="flex items-center gap-2 flex-1 min-w-0 overflow-hidden">
|
||
<!-- Active filter tokens (outline style with icon in circle) -->
|
||
<div
|
||
v-for="token in activeTokens"
|
||
:key="token.type"
|
||
class="flex items-center gap-1.5 px-2.5 py-1.5 rounded-full border-2 cursor-pointer hover:opacity-80 transition-all flex-shrink-0"
|
||
:style="{ borderColor: getTokenColor(token.type), color: getTokenColor(token.type) }"
|
||
@click.stop="$emit('edit-token', token.type)"
|
||
>
|
||
<span
|
||
class="w-5 h-5 rounded-full flex items-center justify-center flex-shrink-0"
|
||
:style="{ backgroundColor: getTokenColor(token.type) }"
|
||
>
|
||
<Icon :name="getTokenIcon(token.type)" size="12" class="text-white" />
|
||
</span>
|
||
<span class="max-w-28 truncate font-medium text-sm">{{ token.label }}</span>
|
||
<button
|
||
class="hover:text-error ml-0.5"
|
||
@click.stop="$emit('remove-token', token.type)"
|
||
>
|
||
<Icon name="lucide:x" size="14" />
|
||
</button>
|
||
</div>
|
||
|
||
<!-- Search input -->
|
||
<input
|
||
ref="inputRef"
|
||
v-model="localSearchQuery"
|
||
type="text"
|
||
:placeholder="placeholder"
|
||
class="flex-1 min-w-32 bg-transparent outline-none text-lg text-base-content placeholder:text-base-content/50"
|
||
@input="$emit('update:search-query', localSearchQuery)"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
</div>
|
||
|
||
<!-- Right: AI + Globe + Team + User (top aligned like logo) -->
|
||
<div class="flex items-center flex-shrink-0 rounded-full glass-bright">
|
||
<div class="flex items-center px-2 py-2">
|
||
<!-- AI Assistant button -->
|
||
<NuxtLink
|
||
:to="localePath('/clientarea/ai')"
|
||
class="w-8 h-8 rounded-full flex items-center justify-center transition-colors"
|
||
:class="useWhiteText ? 'text-white/70 hover:text-white hover:bg-white/10' : 'text-base-content/70 hover:text-base-content hover:bg-base-200'"
|
||
>
|
||
<Icon name="lucide:bot" size="18" />
|
||
</NuxtLink>
|
||
</div>
|
||
|
||
<div class="w-px h-6 bg-white/20 self-center" />
|
||
<div class="flex items-center px-2 py-2">
|
||
<!-- Globe (language/currency) dropdown -->
|
||
<div class="dropdown dropdown-end">
|
||
<button
|
||
tabindex="0"
|
||
class="w-8 h-8 rounded-full flex items-center justify-center transition-colors"
|
||
:class="useWhiteText ? 'text-white/70 hover:text-white hover:bg-white/10' : 'text-base-content/70 hover:text-base-content hover:bg-base-200'"
|
||
>
|
||
<Icon name="lucide:globe" size="18" />
|
||
</button>
|
||
<div tabindex="0" class="dropdown-content bg-base-100 rounded-box z-50 w-52 p-4 shadow-lg border border-base-300">
|
||
<div class="font-semibold mb-2">{{ $t('common.language') }}</div>
|
||
<div class="flex gap-2 mb-4">
|
||
<NuxtLink
|
||
v-for="loc in locales"
|
||
:key="loc.code"
|
||
:to="switchLocalePath(loc.code)"
|
||
class="btn btn-sm"
|
||
:class="locale === loc.code ? 'btn-primary' : 'btn-ghost'"
|
||
>
|
||
{{ loc.code.toUpperCase() }}
|
||
</NuxtLink>
|
||
</div>
|
||
<div class="font-semibold mb-2">{{ $t('common.theme') }}</div>
|
||
<button
|
||
class="btn btn-sm btn-ghost w-full justify-start"
|
||
@click="$emit('toggle-theme')"
|
||
>
|
||
<Icon :name="theme === 'night' ? 'lucide:sun' : 'lucide:moon'" size="16" />
|
||
{{ theme === 'night' ? $t('common.theme_light') : $t('common.theme_dark') }}
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Team dropdown -->
|
||
<div v-if="loggedIn && userData?.teams?.length" class="w-px h-6 bg-white/20 self-center" />
|
||
<div v-if="loggedIn && userData?.teams?.length" class="flex items-center px-2 py-2">
|
||
<div class="dropdown dropdown-end">
|
||
<button
|
||
tabindex="0"
|
||
class="h-8 flex items-center gap-1 px-2 rounded-lg transition-colors"
|
||
:class="useWhiteText ? 'text-white/70 hover:text-white hover:bg-white/10' : 'text-base-content/70 hover:text-base-content hover:bg-base-200'"
|
||
>
|
||
<Icon name="lucide:building-2" size="16" />
|
||
<span class="hidden lg:inline max-w-24 truncate text-xs">
|
||
{{ userData?.activeTeam?.name || $t('common.selectTeam') }}
|
||
</span>
|
||
<Icon name="lucide:chevron-down" size="12" />
|
||
</button>
|
||
<ul tabindex="0" class="dropdown-content menu bg-base-100 rounded-box z-50 w-56 p-2 shadow-lg border border-base-300">
|
||
<li class="menu-title"><span>{{ $t('common.teams') }}</span></li>
|
||
<li v-for="team in userData?.teams" :key="team.id">
|
||
<a
|
||
@click="$emit('switch-team', team)"
|
||
:class="{ active: team.id === userData?.activeTeamId }"
|
||
>
|
||
{{ team.name }}
|
||
</a>
|
||
</li>
|
||
<div class="divider my-1"></div>
|
||
<li>
|
||
<NuxtLink :to="localePath('/clientarea/team')">
|
||
<Icon name="lucide:settings" size="16" />
|
||
{{ $t('cabinetNav.teamSettings') }}
|
||
</NuxtLink>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- User menu -->
|
||
<div v-if="sessionChecked" class="w-px h-6 bg-white/20 self-center" />
|
||
<div v-if="sessionChecked" class="flex items-center px-2 py-2">
|
||
<template v-if="loggedIn">
|
||
<div class="dropdown dropdown-end">
|
||
<div
|
||
tabindex="0"
|
||
role="button"
|
||
class="w-8 h-8 rounded-full overflow-hidden ring-2 transition-all cursor-pointer"
|
||
:class="useWhiteText ? 'ring-white/20 hover:ring-white/40' : 'ring-base-300 hover:ring-primary'"
|
||
>
|
||
<div v-if="userAvatarSvg" v-html="userAvatarSvg" class="w-full h-full" />
|
||
<div
|
||
v-else
|
||
class="w-full h-full flex items-center justify-center font-bold text-xs"
|
||
:class="useWhiteText ? 'bg-white/20 text-white' : 'bg-base-300 text-base-content'"
|
||
>
|
||
{{ userInitials }}
|
||
</div>
|
||
</div>
|
||
<ul
|
||
tabindex="0"
|
||
class="dropdown-content menu bg-base-100 rounded-box z-50 w-52 p-2 shadow-lg border border-base-300"
|
||
>
|
||
<li class="menu-title">
|
||
<span>{{ userName }}</span>
|
||
</li>
|
||
<li>
|
||
<NuxtLink :to="localePath('/clientarea/profile')">
|
||
<Icon name="lucide:user" size="16" />
|
||
{{ $t('dashboard.profile') }}
|
||
</NuxtLink>
|
||
</li>
|
||
<div class="divider my-1"></div>
|
||
<li>
|
||
<a @click="$emit('sign-out')" class="text-error">
|
||
<Icon name="lucide:log-out" size="16" />
|
||
{{ $t('auth.logout') }}
|
||
</a>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</template>
|
||
<template v-else>
|
||
<button
|
||
@click="$emit('sign-in')"
|
||
class="px-4 py-1.5 rounded-full text-sm font-medium transition-colors"
|
||
:class="useWhiteText ? 'bg-white/20 text-white hover:bg-white/30' : 'bg-primary text-primary-content hover:bg-primary-focus'"
|
||
>
|
||
{{ $t('auth.login') }}
|
||
</button>
|
||
</template>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</header>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import type { SelectMode } from '~/composables/useCatalogSearch'
|
||
import { entityColors } from '~/composables/useCatalogSearch'
|
||
|
||
import type { CatalogMode } from '~/composables/useCatalogSearch'
|
||
|
||
const props = withDefaults(defineProps<{
|
||
sessionChecked?: boolean
|
||
loggedIn?: boolean
|
||
userAvatarSvg?: string
|
||
userName?: string
|
||
userInitials?: string
|
||
theme?: 'cupcake' | 'night'
|
||
userData?: {
|
||
id?: string
|
||
activeTeam?: { name?: string; teamType?: string }
|
||
activeTeamId?: string
|
||
teams?: Array<{ id?: string; name?: string; logtoOrgId?: string }>
|
||
} | null
|
||
isSeller?: boolean
|
||
// Role switching props
|
||
hasMultipleRoles?: boolean
|
||
currentRole?: string
|
||
// Search props
|
||
activeTokens?: Array<{ type: string; id: string; label: string; icon: string }>
|
||
availableChips?: Array<{ type: string; label: string }>
|
||
selectMode?: SelectMode
|
||
searchQuery?: string
|
||
// Catalog mode props
|
||
catalogMode?: CatalogMode
|
||
// Quote mode props
|
||
productLabel?: string
|
||
hubLabel?: string
|
||
quantity?: string
|
||
canSearch?: boolean
|
||
showModeToggle?: boolean
|
||
showActiveMode?: boolean // Whether to show active state on mode toggle
|
||
// Glass style applied when header is collapsed
|
||
isCollapsed?: boolean
|
||
// Home page flag for transparent background
|
||
isHomePage?: boolean
|
||
// Client area flag - shows cabinet tabs instead of search
|
||
isClientArea?: boolean
|
||
// Dynamic height for hero effect
|
||
height?: number
|
||
// Collapse progress for hero layout
|
||
collapseProgress?: number
|
||
}>(), {
|
||
height: 100,
|
||
collapseProgress: 1
|
||
})
|
||
|
||
defineEmits([
|
||
'toggle-theme',
|
||
'sign-out',
|
||
'sign-in',
|
||
'switch-team',
|
||
'switch-role',
|
||
// Search events
|
||
'start-select',
|
||
'cancel-select',
|
||
'edit-token',
|
||
'remove-token',
|
||
'update:search-query',
|
||
'update-quantity',
|
||
// Quote mode
|
||
'search',
|
||
'set-catalog-mode'
|
||
])
|
||
|
||
const localePath = useLocalePath()
|
||
const route = useRoute()
|
||
const { locale, locales } = useI18n()
|
||
const switchLocalePath = useSwitchLocalePath()
|
||
const { t } = useI18n()
|
||
|
||
// Check if client area tab is active
|
||
const isClientAreaTabActive = (path: string) => {
|
||
const currentPath = route.path
|
||
const localizedPath = localePath(path)
|
||
return currentPath === localizedPath || currentPath.startsWith(localizedPath + '/')
|
||
}
|
||
|
||
const inputRef = ref<HTMLInputElement>()
|
||
const localSearchQuery = ref(props.searchQuery || '')
|
||
const localQuantity = ref(props.quantity || '')
|
||
|
||
watch(() => props.searchQuery, (val) => {
|
||
localSearchQuery.value = val || ''
|
||
})
|
||
|
||
watch(() => props.quantity, (val) => {
|
||
localQuantity.value = val || ''
|
||
})
|
||
|
||
const focusInput = () => {
|
||
inputRef.value?.focus()
|
||
}
|
||
|
||
const placeholder = computed(() => {
|
||
if (props.selectMode === 'product') return t('catalog.search.searchProducts')
|
||
if (props.selectMode === 'supplier') return t('catalog.search.searchSuppliers')
|
||
if (props.selectMode === 'hub') return t('catalog.search.searchHubs')
|
||
if (!props.activeTokens?.length) return t('catalog.search.placeholder')
|
||
return t('catalog.search.refine')
|
||
})
|
||
|
||
const selectModeLabel = computed(() => {
|
||
if (props.selectMode === 'product') return t('catalog.filters.product')
|
||
if (props.selectMode === 'supplier') return t('catalog.filters.supplier')
|
||
if (props.selectMode === 'hub') return t('catalog.filters.hub')
|
||
return ''
|
||
})
|
||
|
||
const selectModeIcon = computed(() => {
|
||
if (props.selectMode === 'product') return 'lucide:package'
|
||
if (props.selectMode === 'supplier') return 'lucide:factory'
|
||
if (props.selectMode === 'hub') return 'lucide:map-pin'
|
||
return 'lucide:search'
|
||
})
|
||
|
||
const getTokenColor = (type: string) => {
|
||
return entityColors[type as keyof typeof entityColors] || entityColors.product
|
||
}
|
||
|
||
const getTokenIcon = (type: string) => {
|
||
const icons: Record<string, string> = {
|
||
product: 'lucide:shopping-bag',
|
||
hub: 'lucide:warehouse',
|
||
supplier: 'lucide:factory'
|
||
}
|
||
return icons[type] || 'lucide:tag'
|
||
}
|
||
|
||
const isHeroLayout = computed(() => props.isHomePage && !props.isClientArea)
|
||
const topRowHeight = 100
|
||
|
||
const rowStyle = computed(() => {
|
||
if (isHeroLayout.value) {
|
||
return { height: `${topRowHeight}px` }
|
||
}
|
||
return { height: `${props.height}px` }
|
||
})
|
||
|
||
const glassStyle = computed(() => {
|
||
if (isHeroLayout.value) {
|
||
return { height: `${topRowHeight}px` }
|
||
}
|
||
return { height: '100%' }
|
||
})
|
||
|
||
const centerStyle = computed(() => {
|
||
if (!isHeroLayout.value) return {}
|
||
const heroHeight = props.height || topRowHeight
|
||
const minTop = 0
|
||
const maxTop = Math.max(120, Math.round(heroHeight * 0.42))
|
||
const progress = Math.min(1, Math.max(0, props.collapseProgress || 0))
|
||
const top = Math.round(maxTop - (maxTop - minTop) * progress)
|
||
return { marginTop: `${top}px` }
|
||
})
|
||
|
||
// Header background classes
|
||
const headerClasses = computed(() => {
|
||
if (props.isHomePage && !props.isCollapsed) {
|
||
return 'bg-transparent'
|
||
}
|
||
if (props.isCollapsed) {
|
||
return 'bg-transparent backdrop-blur-xl'
|
||
}
|
||
return 'bg-transparent backdrop-blur-xl'
|
||
})
|
||
|
||
// Use white text on dark backgrounds (collapsed or home page with animation)
|
||
const useWhiteText = computed(() => props.isCollapsed || props.isHomePage)
|
||
</script>
|