enhance(client): better sticky-container component
This commit is contained in:
		| @@ -174,9 +174,6 @@ onUnmounted(() => { | ||||
| .fdidabkb { | ||||
| 	--height: 60px; | ||||
| 	display: flex; | ||||
| 	position: sticky; | ||||
| 	top: var(--stickyTop, 0); | ||||
| 	z-index: 1000; | ||||
| 	width: 100%; | ||||
| 	-webkit-backdrop-filter: var(--blur, blur(15px)); | ||||
| 	backdrop-filter: var(--blur, blur(15px)); | ||||
|   | ||||
| @@ -1,6 +1,8 @@ | ||||
| <template> | ||||
| <div ref="rootEl"> | ||||
| 	<slot name="header"></slot> | ||||
| 	<div ref="headerEl"> | ||||
| 		<slot name="header"></slot> | ||||
| 	</div> | ||||
| 	<div ref="bodyEl" :data-sticky-container-header-height="headerHeight"> | ||||
| 		<slot></slot> | ||||
| 	</div> | ||||
| @@ -8,39 +10,25 @@ | ||||
| </template> | ||||
|  | ||||
| <script lang="ts" setup> | ||||
| import { onMounted, onUnmounted } from 'vue'; | ||||
| import { onMounted, onUnmounted, provide, inject, Ref, ref, watch } from 'vue'; | ||||
|  | ||||
| const props = withDefaults(defineProps<{ | ||||
| 	autoSticky?: boolean; | ||||
| }>(), { | ||||
| 	autoSticky: false, | ||||
| }); | ||||
| const CURRENT_STICKY_TOP = Symbol('CURRENT_STICKY_TOP'); | ||||
|  | ||||
| const rootEl = $ref<HTMLElement>(); | ||||
| const headerEl = $ref<HTMLElement>(); | ||||
| const bodyEl = $ref<HTMLElement>(); | ||||
|  | ||||
| let headerHeight = $ref<string | undefined>(); | ||||
| let childStickyTop = $ref(0); | ||||
| const parentStickyTop = inject<Ref<number>>(CURRENT_STICKY_TOP, ref(0)); | ||||
| provide(CURRENT_STICKY_TOP, $$(childStickyTop)); | ||||
|  | ||||
| const calc = () => { | ||||
| 	const currentStickyTop = getComputedStyle(rootEl).getPropertyValue('--stickyTop') || '0px'; | ||||
|  | ||||
| 	const header = rootEl.children[0] as HTMLElement; | ||||
| 	if (header === bodyEl) { | ||||
| 		bodyEl.style.setProperty('--stickyTop', currentStickyTop); | ||||
| 	} else { | ||||
| 		bodyEl.style.setProperty('--stickyTop', `calc(${currentStickyTop} + ${header.offsetHeight}px)`); | ||||
| 		headerHeight = header.offsetHeight.toString(); | ||||
|  | ||||
| 		if (props.autoSticky) { | ||||
| 			header.style.setProperty('--stickyTop', currentStickyTop); | ||||
| 			header.style.position = 'sticky'; | ||||
| 			header.style.top = 'var(--stickyTop)'; | ||||
| 			header.style.zIndex = '1'; | ||||
| 		} | ||||
| 	} | ||||
| 	childStickyTop = parentStickyTop.value + headerEl.offsetHeight; | ||||
| 	headerHeight = headerEl.offsetHeight.toString(); | ||||
| }; | ||||
|  | ||||
| const observer = new MutationObserver(() => { | ||||
| const observer = new ResizeObserver(() => { | ||||
| 	window.setTimeout(() => { | ||||
| 		calc(); | ||||
| 	}, 100); | ||||
| @@ -49,11 +37,19 @@ const observer = new MutationObserver(() => { | ||||
| onMounted(() => { | ||||
| 	calc(); | ||||
|  | ||||
| 	observer.observe(rootEl, { | ||||
| 		attributes: false, | ||||
| 		childList: true, | ||||
| 		subtree: false, | ||||
| 	watch(parentStickyTop, calc); | ||||
|  | ||||
| 	watch($$(childStickyTop), () => { | ||||
| 		bodyEl.style.setProperty('--stickyTop', `${childStickyTop}px`); | ||||
| 	}, { | ||||
| 		immediate: true, | ||||
| 	}); | ||||
|  | ||||
| 	headerEl.style.position = 'sticky'; | ||||
| 	headerEl.style.top = 'var(--stickyTop, 0)'; | ||||
| 	headerEl.style.zIndex = '1000'; | ||||
|  | ||||
| 	observer.observe(headerEl); | ||||
| }); | ||||
|  | ||||
| onUnmounted(() => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 syuilo
					syuilo