fix some bugs
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<div
|
||||
ref="headerRef"
|
||||
class="app-header px-4 py-2 top-0 z-30 wrap-fix background-color-transition"
|
||||
:class="{ 'app-header--scrolled': scrollY > 50 }"
|
||||
:class="{ 'app-header--scrolled': isHeaderScrolled }"
|
||||
>
|
||||
<div class="flex justify-between my-2 items-center">
|
||||
<div v-if="isBoursecuProject()" class="flex items-center gap-2">
|
||||
@@ -40,47 +40,126 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { computed, nextTick, onMounted, onUnmounted, ref } from 'vue'
|
||||
import { useUserStore } from '@/store/userStore'
|
||||
import router from '@/router'
|
||||
import Icon from '@/components/BasicPacks/BasicIcon.vue'
|
||||
import { getProjectMobileNavLogo, isBoursecuProject } from '@/utils/config'
|
||||
|
||||
const headerRef = ref<HTMLElement | null>(null)
|
||||
const scrollY = ref(0)
|
||||
const isHeaderScrolled = ref(false)
|
||||
|
||||
const userStore = useUserStore()
|
||||
const projectLogo = computed(() => getProjectMobileNavLogo())
|
||||
|
||||
let intersectionObserver: IntersectionObserver | null = null
|
||||
let scrollTarget: HTMLElement | Window | null = null
|
||||
|
||||
function isScrollableOverflow(value: string) {
|
||||
return value === 'auto' || value === 'scroll' || value === 'overlay'
|
||||
}
|
||||
|
||||
function findScrollParent(el: HTMLElement | null): HTMLElement | null {
|
||||
let node = el?.parentElement ?? null
|
||||
|
||||
while (node) {
|
||||
const { overflowY } = getComputedStyle(node)
|
||||
if (overflowY === 'auto' || overflowY === 'scroll') {
|
||||
const style = getComputedStyle(node)
|
||||
const overflowY = style.overflowY
|
||||
const overflow = style.overflow
|
||||
|
||||
if (isScrollableOverflow(overflowY) || isScrollableOverflow(overflow)) {
|
||||
return node
|
||||
}
|
||||
|
||||
node = node.parentElement
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function updateScrollY() {
|
||||
if (!scrollTarget) return
|
||||
scrollY.value = scrollTarget instanceof Window ? scrollTarget.scrollY : scrollTarget.scrollTop
|
||||
function resolveScrollRoot(): HTMLElement | null {
|
||||
const header = headerRef.value
|
||||
if (!header) return null
|
||||
|
||||
const chromeInner = header.closest('.main-with-bottom-chrome-inner')
|
||||
if (chromeInner instanceof HTMLElement) {
|
||||
return chromeInner
|
||||
}
|
||||
|
||||
const fromParent = findScrollParent(header)
|
||||
if (fromParent) {
|
||||
return fromParent
|
||||
}
|
||||
|
||||
const global = document.querySelector('.main-with-bottom-chrome-inner')
|
||||
return global instanceof HTMLElement ? global : null
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
scrollTarget = findScrollParent(headerRef.value) ?? window
|
||||
scrollTarget.addEventListener('scroll', updateScrollY, { passive: true })
|
||||
updateScrollY()
|
||||
function resolveScrollSentinel(scrollRoot: HTMLElement | null): HTMLElement | null {
|
||||
if (!scrollRoot) return null
|
||||
|
||||
const local = scrollRoot.querySelector('.app-header-scroll-sentinel')
|
||||
if (local instanceof HTMLElement) {
|
||||
return local
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
function updateScrollStateFromPosition() {
|
||||
if (!scrollTarget) return
|
||||
|
||||
const next =
|
||||
scrollTarget instanceof Window
|
||||
? scrollTarget.scrollY > 50
|
||||
: scrollTarget.scrollTop > 50
|
||||
|
||||
isHeaderScrolled.value = next
|
||||
}
|
||||
|
||||
function teardownScrollTracking() {
|
||||
intersectionObserver?.disconnect()
|
||||
intersectionObserver = null
|
||||
|
||||
scrollTarget?.removeEventListener('scroll', updateScrollStateFromPosition)
|
||||
scrollTarget = null
|
||||
}
|
||||
|
||||
function setupScrollTracking() {
|
||||
teardownScrollTracking()
|
||||
|
||||
const scrollRoot = resolveScrollRoot()
|
||||
const sentinel = resolveScrollSentinel(scrollRoot)
|
||||
|
||||
if (scrollRoot && sentinel && typeof IntersectionObserver !== 'undefined') {
|
||||
intersectionObserver = new IntersectionObserver(
|
||||
([entry]) => {
|
||||
isHeaderScrolled.value = !entry?.isIntersecting
|
||||
},
|
||||
{
|
||||
root: scrollRoot,
|
||||
threshold: 0,
|
||||
rootMargin: '-1px 0px 0px 0px',
|
||||
},
|
||||
)
|
||||
intersectionObserver.observe(sentinel)
|
||||
return
|
||||
}
|
||||
|
||||
scrollTarget = scrollRoot ?? window
|
||||
scrollTarget.addEventListener('scroll', updateScrollStateFromPosition, { passive: true })
|
||||
updateScrollStateFromPosition()
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
setupScrollTracking()
|
||||
await nextTick()
|
||||
setupScrollTracking()
|
||||
requestAnimationFrame(() => setupScrollTracking())
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
scrollTarget?.removeEventListener('scroll', updateScrollY)
|
||||
teardownScrollTracking()
|
||||
})
|
||||
|
||||
defineEmits<{
|
||||
@@ -93,10 +172,8 @@ defineEmits<{
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/* عین bg-white shadow opacity-95 قبلی */
|
||||
.app-header--scrolled {
|
||||
background-color: #fff;
|
||||
opacity: 0.95;
|
||||
background-color: rgba(255, 255, 255, 0.92);
|
||||
box-shadow:
|
||||
0 1px 3px 0 rgb(0 0 0 / 0.1),
|
||||
0 1px 2px -1px rgb(0 0 0 / 0.1);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
class="w-full flex justify-evenly rounded-lg py-2 home_appear_fade_in"
|
||||
:class="[
|
||||
isBoursecuLayout ? 'mt-8 pt-2' : 'mt-6',
|
||||
variant === 'mobile' ? 'pb-45' : 'mt-0 pb-0',
|
||||
variant === 'mobile' ? 'pb-20' : 'mt-0 pb-0',
|
||||
]"
|
||||
>
|
||||
<div class="text-center w-full">
|
||||
|
||||
Reference in New Issue
Block a user