feat: align landing capsule and remove glass from map ui

This commit is contained in:
Ruslan Bakiev
2026-03-12 15:25:37 +07:00
parent 2761e61f01
commit 530c97b912
11 changed files with 71 additions and 32 deletions

View File

@@ -85,6 +85,13 @@
backdrop-filter: blur(22px); backdrop-filter: blur(22px);
-webkit-backdrop-filter: blur(22px); -webkit-backdrop-filter: blur(22px);
} }
/* Map overlays must stay solid (no glass) */
.map-chip {
background: color-mix(in oklab, var(--color-base-100) 96%, transparent);
border: 1px solid color-mix(in oklab, var(--color-base-300) 80%, transparent);
box-shadow: 0 10px 24px rgba(15, 23, 42, 0.12);
}
} }
/* ── Header glass: two-layer Apple-style glassmorphism ── */ /* ── Header glass: two-layer Apple-style glassmorphism ── */

View File

@@ -12,9 +12,9 @@
/> />
<!-- Sheet content --> <!-- Sheet content -->
<div class="relative flex w-full max-w-[980px] flex-col overflow-hidden rounded-t-[2rem] border border-white/60 bg-base-100/95 shadow-[0_-24px_70px_rgba(15,23,42,0.3)] backdrop-blur-xl"> <div class="relative flex w-full max-w-[980px] flex-col overflow-hidden rounded-t-[2rem] border border-base-300 bg-base-100 shadow-[0_-24px_70px_rgba(15,23,42,0.3)]">
<!-- Header with drag handle and close --> <!-- Header with drag handle and close -->
<div class="sticky top-0 z-10 border-b border-base-300 bg-base-100/90"> <div class="sticky top-0 z-10 border-b border-base-300 bg-base-100">
<div class="flex justify-center py-2"> <div class="flex justify-center py-2">
<div class="h-1.5 w-12 rounded-full bg-base-content/20" /> <div class="h-1.5 w-12 rounded-full bg-base-content/20" />
</div> </div>

View File

@@ -12,9 +12,9 @@
/> />
<!-- Sheet content --> <!-- Sheet content -->
<div class="relative flex-1 bg-black/40 backdrop-blur-xl rounded-t-2xl border-t border-white/20 shadow-2xl overflow-hidden"> <div class="relative flex-1 bg-neutral rounded-t-2xl border-t border-neutral/70 shadow-2xl overflow-hidden">
<!-- Header with drag handle and close --> <!-- Header with drag handle and close -->
<div class="sticky top-0 z-10 bg-black/30 backdrop-blur-md border-b border-white/10"> <div class="sticky top-0 z-10 bg-neutral border-b border-white/10">
<div class="flex justify-center py-2"> <div class="flex justify-center py-2">
<div class="w-12 h-1.5 bg-white/30 rounded-full" /> <div class="w-12 h-1.5 bg-white/30 rounded-full" />
</div> </div>

View File

@@ -1,7 +1,7 @@
<template> <template>
<div class="flex flex-col h-full"> <div class="flex flex-col h-full">
<!-- Header: белое стекло (negative margins to expand beyond parent padding) --> <!-- Header: solid panel (negative margins to expand beyond parent padding) -->
<div class="sticky top-0 z-10 -mx-4 -mt-4 px-4 pt-4 pb-3 rounded-t-xl bg-white/90 backdrop-blur-md border-b border-white/20"> <div class="sticky top-0 z-10 -mx-4 -mt-4 px-4 pt-4 pb-3 rounded-t-xl bg-base-100 border-b border-base-300">
<slot name="header" /> <slot name="header" />
</div> </div>

View File

@@ -12,9 +12,9 @@
/> />
<!-- Sheet content --> <!-- Sheet content -->
<div class="relative flex w-full max-w-[980px] flex-col overflow-hidden rounded-t-[2rem] border border-white/60 bg-base-100/95 shadow-[0_-24px_70px_rgba(15,23,42,0.3)] backdrop-blur-xl"> <div class="relative flex w-full max-w-[980px] flex-col overflow-hidden rounded-t-[2rem] border border-base-300 bg-base-100 shadow-[0_-24px_70px_rgba(15,23,42,0.3)]">
<!-- Header with drag handle and close --> <!-- Header with drag handle and close -->
<div class="sticky top-0 z-10 border-b border-base-300 bg-base-100/90"> <div class="sticky top-0 z-10 border-b border-base-300 bg-base-100">
<div class="flex justify-center py-2"> <div class="flex justify-center py-2">
<div class="h-1.5 w-12 rounded-full bg-base-content/20" /> <div class="h-1.5 w-12 rounded-full bg-base-content/20" />
</div> </div>

View File

@@ -98,8 +98,10 @@
<!-- Center: Search input OR Client Area tabs (vertically centered) --> <!-- Center: Search input OR Client Area tabs (vertically centered) -->
<div <div
class="flex-1 flex flex-col items-center max-w-2xl mx-auto gap-2 transition-all" class="relative flex-1 flex flex-col items-center mx-auto gap-2 transition-all"
:class="isHeroLayout ? 'justify-start' : 'justify-center'" :class="[
isHeroLayout ? 'w-full max-w-none justify-start' : 'max-w-2xl justify-center'
]"
:style="centerStyle" :style="centerStyle"
> >
<!-- Hero slot for home page title --> <!-- Hero slot for home page title -->
@@ -141,7 +143,11 @@
<!-- Quote mode: Step-based capsule navigation (like logistics) --> <!-- Quote mode: Step-based capsule navigation (like logistics) -->
<template v-else-if="catalogMode === 'quote'"> <template v-else-if="catalogMode === 'quote'">
<div class="flex items-center w-full rounded-full pill-glass overflow-hidden"> <div
class="flex items-center rounded-full pill-glass overflow-hidden"
:class="searchCapsuleClass"
:style="searchCapsuleStyle"
>
<!-- Product segment --> <!-- Product segment -->
<NuxtLink <NuxtLink
:to="localePath('/catalog/product')" :to="localePath('/catalog/product')"
@@ -182,7 +188,9 @@
<template v-else> <template v-else>
<!-- Big pill input --> <!-- Big pill input -->
<div <div
class="flex items-center gap-3 w-full px-5 py-3 rounded-full pill-glass focus-within:ring-2 focus-within:ring-primary/20 transition-all cursor-text" class="flex items-center gap-3 px-5 py-3 rounded-full pill-glass focus-within:ring-2 focus-within:ring-primary/20 transition-all cursor-text"
:class="searchCapsuleClass"
:style="searchCapsuleStyle"
@click="focusInput" @click="focusInput"
> >
<Icon name="lucide:search" size="22" class="text-primary flex-shrink-0" /> <Icon name="lucide:search" size="22" class="text-primary flex-shrink-0" />
@@ -409,9 +417,12 @@ const props = withDefaults(defineProps<{
height?: number height?: number
// Collapse progress for hero layout // Collapse progress for hero layout
collapseProgress?: number collapseProgress?: number
// Home scroll position for floating center capsule
heroScrollY?: number
}>(), { }>(), {
height: 100, height: 100,
collapseProgress: 1 collapseProgress: 1,
heroScrollY: 0
}) })
defineEmits([ defineEmits([
@@ -516,6 +527,8 @@ const getTokenIcon = (type: string) => {
const isHeroLayout = computed(() => props.isHomePage && !props.isClientArea) const isHeroLayout = computed(() => props.isHomePage && !props.isClientArea)
const topRowHeight = 100 const topRowHeight = 100
const LANDING_CAPSULE_TOP_START = 450
const LANDING_CAPSULE_TOP_STOP = 2
const rowStyle = computed(() => { const rowStyle = computed(() => {
if (isHeroLayout.value) { if (isHeroLayout.value) {
@@ -534,6 +547,24 @@ const centerStyle = computed(() => {
return { marginTop: `${top}px` } return { marginTop: `${top}px` }
}) })
const isFloatingHomeCapsule = computed(() => isHeroLayout.value)
const landingCapsuleTop = computed(() => {
if (!isFloatingHomeCapsule.value) return LANDING_CAPSULE_TOP_STOP
const y = Math.max(0, props.heroScrollY || 0)
return Math.max(LANDING_CAPSULE_TOP_STOP, LANDING_CAPSULE_TOP_START - y)
})
const searchCapsuleClass = computed(() => {
if (!isFloatingHomeCapsule.value) return 'w-full'
return 'w-full lg:fixed lg:left-1/2 lg:z-40 lg:w-[min(1120px,calc(100%-1.5rem))] lg:-translate-x-1/2 transition-[top] duration-200 ease-out'
})
const searchCapsuleStyle = computed(() => {
if (!isFloatingHomeCapsule.value) return undefined
return { top: `${landingCapsuleTop.value}px` }
})
// Use white text on dark backgrounds (collapsed or home page with animation) // Use white text on dark backgrounds (collapsed or home page with animation)
const useWhiteText = computed(() => props.isCollapsed || props.isHomePage) const useWhiteText = computed(() => props.isCollapsed || props.isHomePage)
</script> </script>

View File

@@ -26,7 +26,7 @@
<!-- View mode loading indicator --> <!-- View mode loading indicator -->
<div <div
v-if="clusterLoading || loading" v-if="clusterLoading || loading"
class="absolute top-[116px] left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 pill-glass rounded-full px-4 py-2" class="absolute top-[116px] left-1/2 -translate-x-1/2 z-30 flex items-center gap-2 map-chip rounded-full px-4 py-2"
> >
<span class="loading loading-spinner loading-sm text-base-content" /> <span class="loading loading-spinner loading-sm text-base-content" />
<span class="text-base-content text-sm font-medium">{{ $t('common.loading') }}</span> <span class="text-base-content text-sm font-medium">{{ $t('common.loading') }}</span>
@@ -35,7 +35,7 @@
<!-- List button (LEFT, opens panel) - hide when panel is open --> <!-- List button (LEFT, opens panel) - hide when panel is open -->
<button <button
v-if="!isPanelOpen" v-if="!isPanelOpen"
class="absolute top-[116px] left-4 z-20 hidden lg:flex items-center gap-2 pill-glass rounded-full px-3 py-1.5 text-base-content text-sm hover:bg-white/20 transition-colors" class="absolute top-[116px] left-4 z-20 hidden lg:flex items-center gap-2 map-chip rounded-full px-3 py-1.5 text-base-content text-sm hover:bg-base-200 transition-colors"
@click="openPanel" @click="openPanel"
> >
<Icon name="lucide:menu" size="16" /> <Icon name="lucide:menu" size="16" />
@@ -45,7 +45,7 @@
<!-- Filter by bounds checkbox (LEFT, next to panel when open) - only in selection mode --> <!-- Filter by bounds checkbox (LEFT, next to panel when open) - only in selection mode -->
<label <label
v-if="selectMode !== null" v-if="selectMode !== null"
class="absolute top-[116px] left-[calc(1rem+32rem+1rem)] z-20 hidden lg:flex items-center gap-2 pill-glass rounded-full px-3 py-1.5 cursor-pointer text-base-content text-sm hover:bg-white/20 transition-colors" class="absolute top-[116px] left-[calc(1rem+32rem+1rem)] z-20 hidden lg:flex items-center gap-2 map-chip rounded-full px-3 py-1.5 cursor-pointer text-base-content text-sm hover:bg-base-200 transition-colors"
> >
<input <input
type="checkbox" type="checkbox"
@@ -60,11 +60,11 @@
<!-- View toggle (top RIGHT overlay, below header) - hide in info mode or when hideViewToggle --> <!-- View toggle (top RIGHT overlay, below header) - hide in info mode or when hideViewToggle -->
<div v-if="!isInfoMode && !hideViewToggle" class="absolute top-[116px] right-4 z-20 hidden lg:flex items-center gap-2"> <div v-if="!isInfoMode && !hideViewToggle" class="absolute top-[116px] right-4 z-20 hidden lg:flex items-center gap-2">
<!-- View mode toggle --> <!-- View mode toggle -->
<div class="flex gap-1 pill-glass rounded-full p-1"> <div class="flex gap-1 map-chip rounded-full p-1">
<button <button
v-if="showOffersToggle" v-if="showOffersToggle"
class="flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-bold transition-colors" class="flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-bold transition-colors"
:class="mapViewMode === 'offers' ? 'bg-white/20 text-base-content' : 'text-base-content/70 hover:text-base-content hover:bg-white/10'" :class="mapViewMode === 'offers' ? 'bg-base-300 text-base-content' : 'text-base-content/70 hover:text-base-content hover:bg-base-200'"
@click="setMapViewMode('offers')" @click="setMapViewMode('offers')"
> >
<span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #f97316"> <span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #f97316">
@@ -75,7 +75,7 @@
<button <button
v-if="showHubsToggle" v-if="showHubsToggle"
class="flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-bold transition-colors" class="flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-bold transition-colors"
:class="mapViewMode === 'hubs' ? 'bg-white/20 text-base-content' : 'text-base-content/70 hover:text-base-content hover:bg-white/10'" :class="mapViewMode === 'hubs' ? 'bg-base-300 text-base-content' : 'text-base-content/70 hover:text-base-content hover:bg-base-200'"
@click="setMapViewMode('hubs')" @click="setMapViewMode('hubs')"
> >
<span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #22c55e"> <span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #22c55e">
@@ -86,7 +86,7 @@
<button <button
v-if="showSuppliersToggle" v-if="showSuppliersToggle"
class="flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-bold transition-colors" class="flex items-center gap-2 px-3 py-1.5 rounded-full text-sm font-bold transition-colors"
:class="mapViewMode === 'suppliers' ? 'bg-white/20 text-base-content' : 'text-base-content/70 hover:text-base-content hover:bg-white/10'" :class="mapViewMode === 'suppliers' ? 'bg-base-300 text-base-content' : 'text-base-content/70 hover:text-base-content hover:bg-base-200'"
@click="setMapViewMode('suppliers')" @click="setMapViewMode('suppliers')"
> >
<span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #3b82f6"> <span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #3b82f6">
@@ -104,7 +104,7 @@
class="absolute top-[116px] left-4 bottom-4 z-30 max-w-[calc(100vw-2rem)] hidden lg:block" class="absolute top-[116px] left-4 bottom-4 z-30 max-w-[calc(100vw-2rem)] hidden lg:block"
:class="panelWidth" :class="panelWidth"
> >
<div class="bg-white/90 backdrop-blur-[14px] border border-white/50 rounded-[1.1rem] shadow-2xl h-full flex flex-col text-base-content"> <div class="bg-neutral text-neutral-content border border-neutral/70 rounded-[1.1rem] shadow-2xl h-full flex flex-col">
<slot name="panel" /> <slot name="panel" />
</div> </div>
</div> </div>
@@ -116,7 +116,7 @@
<div class="flex justify-between px-4 mb-2"> <div class="flex justify-between px-4 mb-2">
<!-- List button (mobile) --> <!-- List button (mobile) -->
<button <button
class="flex items-center gap-2 pill-glass rounded-full px-3 py-2 text-base-content text-sm font-medium" class="flex items-center gap-2 map-chip rounded-full px-3 py-2 text-base-content text-sm font-medium"
@click="openPanel" @click="openPanel"
> >
<Icon name="lucide:menu" size="16" /> <Icon name="lucide:menu" size="16" />
@@ -124,11 +124,11 @@
</button> </button>
<!-- Mobile view toggle - hide in info mode or when hideViewToggle --> <!-- Mobile view toggle - hide in info mode or when hideViewToggle -->
<div v-if="!isInfoMode && !hideViewToggle" class="flex gap-1 pill-glass rounded-full p-1"> <div v-if="!isInfoMode && !hideViewToggle" class="flex gap-1 map-chip rounded-full p-1">
<button <button
v-if="showOffersToggle" v-if="showOffersToggle"
class="flex items-center justify-center w-8 h-8 rounded-full transition-colors" class="flex items-center justify-center w-8 h-8 rounded-full transition-colors"
:class="mapViewMode === 'offers' ? 'bg-white/20' : 'hover:bg-white/10'" :class="mapViewMode === 'offers' ? 'bg-base-300' : 'hover:bg-base-200'"
@click="setMapViewMode('offers')" @click="setMapViewMode('offers')"
> >
<span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #f97316"> <span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #f97316">
@@ -138,7 +138,7 @@
<button <button
v-if="showHubsToggle" v-if="showHubsToggle"
class="flex items-center justify-center w-8 h-8 rounded-full transition-colors" class="flex items-center justify-center w-8 h-8 rounded-full transition-colors"
:class="mapViewMode === 'hubs' ? 'bg-white/20' : 'hover:bg-white/10'" :class="mapViewMode === 'hubs' ? 'bg-base-300' : 'hover:bg-base-200'"
@click="setMapViewMode('hubs')" @click="setMapViewMode('hubs')"
> >
<span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #22c55e"> <span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #22c55e">
@@ -148,7 +148,7 @@
<button <button
v-if="showSuppliersToggle" v-if="showSuppliersToggle"
class="flex items-center justify-center w-8 h-8 rounded-full transition-colors" class="flex items-center justify-center w-8 h-8 rounded-full transition-colors"
:class="mapViewMode === 'suppliers' ? 'bg-white/20' : 'hover:bg-white/10'" :class="mapViewMode === 'suppliers' ? 'bg-base-300' : 'hover:bg-base-200'"
@click="setMapViewMode('suppliers')" @click="setMapViewMode('suppliers')"
> >
<span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #3b82f6"> <span class="w-5 h-5 rounded-full flex items-center justify-center" style="background-color: #3b82f6">
@@ -162,7 +162,7 @@
<Transition name="slide-up"> <Transition name="slide-up">
<div <div
v-if="isPanelOpen" v-if="isPanelOpen"
class="bg-white rounded-t-3xl shadow-[0_-8px_40px_rgba(0,0,0,0.12)] transition-all duration-300 text-base-content h-[60vh]" class="bg-neutral text-neutral-content rounded-t-3xl border-t border-neutral/70 shadow-[0_-8px_40px_rgba(0,0,0,0.35)] transition-all duration-300 h-[60vh]"
> >
<!-- Drag handle / close --> <!-- Drag handle / close -->
<div <div

View File

@@ -18,6 +18,7 @@
class="relative z-10" class="relative z-10"
:height="isHomePage ? heroHeight : 100" :height="isHomePage ? heroHeight : 100"
:collapse-progress="isHomePage ? collapseProgress : 1" :collapse-progress="isHomePage ? collapseProgress : 1"
:hero-scroll-y="isHomePage ? heroScrollY : 0"
:session-checked="sessionChecked" :session-checked="sessionChecked"
:logged-in="isLoggedIn" :logged-in="isLoggedIn"
:user-avatar-svg="userAvatarSvg" :user-avatar-svg="userAvatarSvg"
@@ -126,6 +127,7 @@ const { headerOffset, isCollapsed } = useScrollCollapse(100)
// Hero scroll for home page // Hero scroll for home page
const { const {
scrollY: heroScrollY,
heroHeight, heroHeight,
heroBaseHeight, heroBaseHeight,
collapseProgress, collapseProgress,
@@ -358,4 +360,3 @@ const onSearch = () => {
searchTrigger.value++ searchTrigger.value++
} }
</script> </script>

View File

@@ -15,14 +15,14 @@
<div class="fixed inset-x-0 bottom-0 z-50 flex justify-center px-3 md:px-4" style="height: 72vh"> <div class="fixed inset-x-0 bottom-0 z-50 flex justify-center px-3 md:px-4" style="height: 72vh">
<div class="absolute inset-0 -top-[32vh] bg-gradient-to-t from-black/45 via-black/20 to-transparent" /> <div class="absolute inset-0 -top-[32vh] bg-gradient-to-t from-black/45 via-black/20 to-transparent" />
<!-- Sheet --> <!-- Sheet -->
<div class="relative flex w-full max-w-[980px] flex-col overflow-hidden rounded-t-[2rem] border border-white/60 bg-base-100/95 shadow-[0_-24px_70px_rgba(15,23,42,0.3)] backdrop-blur-xl"> <div class="relative flex w-full max-w-[980px] flex-col overflow-hidden rounded-t-[2rem] border border-base-300 bg-base-100 shadow-[0_-24px_70px_rgba(15,23,42,0.3)]">
<!-- Drag handle --> <!-- Drag handle -->
<div class="flex justify-center py-2"> <div class="flex justify-center py-2">
<div class="h-1.5 w-12 rounded-full bg-base-content/20" /> <div class="h-1.5 w-12 rounded-full bg-base-content/20" />
</div> </div>
<!-- Header --> <!-- Header -->
<div class="border-b border-base-300 bg-base-100/90 px-6 pb-4"> <div class="border-b border-base-300 bg-base-100 px-6 pb-4">
<!-- Back button --> <!-- Back button -->
<NuxtLink :to="localePath('/clientarea/orders')" class="mb-3 inline-flex items-center gap-1 text-sm text-base-content/60 hover:text-base-content"> <NuxtLink :to="localePath('/clientarea/orders')" class="mb-3 inline-flex items-center gap-1 text-sm text-base-content/60 hover:text-base-content">
<Icon name="lucide:arrow-left" size="16" /> <Icon name="lucide:arrow-left" size="16" />

View File

@@ -13,7 +13,7 @@
<!-- Bottom Sheet --> <!-- Bottom Sheet -->
<div class="fixed inset-x-0 bottom-0 z-50 flex flex-col" style="height: 70vh"> <div class="fixed inset-x-0 bottom-0 z-50 flex flex-col" style="height: 70vh">
<!-- Glass sheet --> <!-- Glass sheet -->
<div class="relative flex-1 bg-black/40 backdrop-blur-xl rounded-t-2xl border-t border-white/20 shadow-2xl overflow-hidden"> <div class="relative flex-1 bg-neutral rounded-t-2xl border-t border-neutral/70 shadow-2xl overflow-hidden">
<!-- Drag handle --> <!-- Drag handle -->
<div class="flex justify-center py-2"> <div class="flex justify-center py-2">
<div class="w-12 h-1.5 bg-white/30 rounded-full" /> <div class="w-12 h-1.5 bg-white/30 rounded-full" />

View File

@@ -13,7 +13,7 @@
<!-- Bottom Sheet --> <!-- Bottom Sheet -->
<div class="fixed inset-x-0 bottom-0 z-50 flex flex-col" style="height: 70vh"> <div class="fixed inset-x-0 bottom-0 z-50 flex flex-col" style="height: 70vh">
<!-- Glass sheet --> <!-- Glass sheet -->
<div class="relative flex-1 bg-black/40 backdrop-blur-xl rounded-t-2xl border-t border-white/20 shadow-2xl overflow-hidden"> <div class="relative flex-1 bg-neutral rounded-t-2xl border-t border-neutral/70 shadow-2xl overflow-hidden">
<!-- Drag handle --> <!-- Drag handle -->
<div class="flex justify-center py-2"> <div class="flex justify-center py-2">
<div class="w-12 h-1.5 bg-white/30 rounded-full" /> <div class="w-12 h-1.5 bg-white/30 rounded-full" />