Skip to content

Commit 1dd92b9

Browse files
committed
Core - Drop scrollRestoration SPA logic, fine-tune resizeObserver callback handling
1 parent 7d9c2b7 commit 1dd92b9

File tree

9 files changed

+34
-116
lines changed

9 files changed

+34
-116
lines changed

packages/vue-use-fixed-header/src/useFixedHeader.ts

Lines changed: 8 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { shallowRef, ref, unref, watch, computed, readonly, type CSSProperties as CSS } from 'vue'
22

3-
import { isSSR, useReducedMotion } from './utils'
3+
import { useReducedMotion, isBrowser } from './utils'
44
import { TRANSITION_STYLES } from './constants'
55

66
import type { UseFixedHeaderOptions, MaybeTemplateRef } from './types'
@@ -29,10 +29,9 @@ export function useFixedHeader(
2929

3030
const internal = {
3131
resizeObserver: undefined as ResizeObserver | undefined,
32-
skipInitialObserverCb: true,
32+
initResizeObserver: false,
3333
isListeningScroll: false,
3434
isHovering: false,
35-
isMount: true,
3635
}
3736

3837
const styles = shallowRef<CSS>({})
@@ -80,47 +79,15 @@ export function useFixedHeader(
8079

8180
// Callbacks
8281

83-
/**
84-
* Hides the header on page load before it has a chance to paint
85-
* if scroll restoration is instant. If not, applies the enter
86-
* styles immediately (without transitions).
87-
*/
88-
function onScrollRestoration() {
89-
window.requestAnimationFrame(() => {
90-
if (!internal.isMount) return
91-
92-
if (!isFixed()) {
93-
internal.isMount = false
94-
return
95-
}
96-
97-
const isInstant = getScrollTop() > getHeaderHeight() * 1.2 // Resolves to false if scroll is smooth
98-
99-
if (isInstant) {
100-
setStyles({
101-
transform: leaveStyles.transform,
102-
...(transitionOpacity() ? { opacity: 0 } : {}),
103-
visibility: 'hidden',
104-
})
105-
} else {
106-
setStyles({
107-
transform: enterStyles.transform,
108-
...(transitionOpacity() ? { opacity: 1 } : {}),
109-
})
110-
}
111-
112-
internal.isMount = false
113-
})
114-
}
115-
11682
/**
11783
* Resize observer is added wheter or not the header is fixed/sticky
11884
* as it is in charge of toggling scroll/pointer listeners if it
11985
* turns from fixed/sticky to something else and vice-versa.
12086
*/
12187
function addResizeObserver() {
12288
internal.resizeObserver = new ResizeObserver(() => {
123-
if (internal.skipInitialObserverCb) return (internal.skipInitialObserverCb = false)
89+
// Skip the initial call
90+
if (!internal.initResizeObserver) return (internal.initResizeObserver = true)
12491
toggleListeners()
12592
})
12693

@@ -189,7 +156,7 @@ export function useFixedHeader(
189156
// Scroll Events
190157

191158
function createScrollHandler() {
192-
let prevTop = 0
159+
let prevTop = isBrowser ? getScrollTop() : 0
193160

194161
return () => {
195162
const scrollTop = getScrollTop()
@@ -276,22 +243,22 @@ export function useFixedHeader(
276243
removePointerListener()
277244
}
278245

279-
!isSSR &&
246+
isBrowser &&
280247
watch(
281248
() => [unref(target), getRoot(), isReduced.value, unref(options.watch)],
282249
([headerEl, rootEl, isReduced], _, onCleanup) => {
283250
const shouldInit = !isReduced && headerEl && (rootEl || rootEl === null)
284251

285252
if (shouldInit) {
286253
addResizeObserver()
287-
onScrollRestoration()
288254
toggleListeners()
289255
}
290256

291257
onCleanup(() => {
292258
removeListeners()
293-
internal.resizeObserver?.disconnect()
294259
removeStyles()
260+
internal.resizeObserver?.disconnect()
261+
internal.initResizeObserver = false
295262
})
296263
},
297264
{ immediate: true, flush: 'post' },

packages/vue-use-fixed-header/src/utils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { onBeforeUnmount, onMounted, ref } from 'vue'
22

3-
export const isSSR = typeof window === 'undefined'
3+
export const isBrowser = typeof window !== 'undefined'
44

55
export function useReducedMotion() {
66
const isReduced = ref(false)
77

8-
if (isSSR) return isReduced
8+
if (!isBrowser) return isReduced
99

1010
const query = window.matchMedia('(prefers-reduced-motion: reduce)')
1111

packages/vue-use-fixed-header/tests/components/ContainerScroll.vue

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,10 @@
11
<script setup lang="ts">
2-
import { onBeforeMount, ref } from 'vue'
2+
import { ref } from 'vue'
33
import { useFixedHeader } from '../../src'
44
5-
const props = defineProps<{
6-
instantScrollRestoration?: boolean
7-
}>()
8-
95
const containerRef = ref<HTMLElement | null>(null)
106
const headerRef = ref<HTMLElement | null>(null)
117
12-
onBeforeMount(() => {
13-
if (!props.instantScrollRestoration) return
14-
15-
window.requestAnimationFrame(() => {
16-
if (!containerRef.value) throw new Error('containerRef is null')
17-
18-
containerRef.value.scroll(0, window.innerHeight / 3)
19-
})
20-
})
21-
228
const { styles } = useFixedHeader(headerRef, {
239
root: containerRef,
2410
})

packages/vue-use-fixed-header/tests/components/Watch.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,3 @@ const position = computed(() => (props.watch.value ? 'relative' : 'fixed'))
4141
background: red;
4242
}
4343
</style>
44-
../../src/useFixedHeader

packages/vue-use-fixed-header/tests/components/WindowScroll.vue

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
<script setup lang="ts">
2-
import { onBeforeMount, ref } from 'vue'
2+
import { ref } from 'vue'
33
import { useFixedHeader } from '../../src'
44
5-
const props = defineProps<{
6-
instantScrollRestoration?: boolean
7-
}>()
8-
95
const headerRef = ref<HTMLElement | null>(null)
106
11-
onBeforeMount(() => {
12-
if (!props.instantScrollRestoration) return
13-
14-
window.requestAnimationFrame(() => {
15-
window.scroll(0, window.innerHeight / 3)
16-
})
17-
})
18-
197
const { styles } = useFixedHeader(headerRef)
208
</script>
219

packages/vue-use-fixed-header/tests/page-load.cy.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
function testIstantRestoration() {
22
return cy
3-
.mountApp({
4-
props: {
5-
instantScrollRestoration: true,
6-
},
7-
})
3+
.mountApp()
4+
.getScrollSubject()
5+
.scrollTo('bottom', { duration: 0 })
86
.get('header')
97
.should('not.be.visible')
108
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import { TRANSITION_STYLES } from '../src/constants'
2+
3+
describe('Styles', () => {
4+
const { enterStyles, leaveStyles } = TRANSITION_STYLES
5+
6+
it('Transitions are toggled properly', () => {
7+
cy.mountApp()
8+
.scrollDown()
9+
.get('header')
10+
.should('be.hidden')
11+
.checkStyles(leaveStyles)
12+
13+
.scrollUp()
14+
.get('header')
15+
.should('be.visible')
16+
.checkStyles(enterStyles)
17+
})
18+
})

packages/vue-use-fixed-header/tests/styles.ts

Lines changed: 0 additions & 38 deletions
This file was deleted.

packages/vue-use-fixed-header/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"compilerOptions": {
3-
"target": "ES2020",
3+
"target": "ES2015",
44
"module": "ES2020",
55
"moduleResolution": "Node",
66
"strict": true,

0 commit comments

Comments
 (0)