Skip to content

Commit

Permalink
add usePositionStickyObserver
Browse files Browse the repository at this point in the history
  • Loading branch information
brandonreid committed Aug 21, 2023
1 parent 34d8371 commit 8fcf97d
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export * from './useMutationObserver'
export * from './useNow'
export * from './usePatchRef'
export * from './useResizeObserver'
export * from './usePositionStickyObserver'
export * from './useRouteParam'
export * from './useRouteQuery'
export * from './useRouteQueryParam'
Expand Down
34 changes: 34 additions & 0 deletions src/usePositionStickyObserver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# usePositionStickyObserver

This composition is abstracts away the logic necessary to determine if a `position: sticky;` element has gone into it's "stuck" mode. This is useful when you want to style the element differently when it's stuck, like if you want to add a background color.

## Example

```typescript
const stickyHeader = ref<HTMLElement>()
const { stuck } = usePositionStickyObserver(stickyHeader)

const classes = computed(() ({
header: {
'header--stuck': stuck.value,
}
}))
```

## Arguments

| Name | Type |
| ------- | ---------------------------------------------- |
| element | `HTMLElement \| Ref<HTMLElement \| undefined>` |
| options | '{}' |

### Options

| Name | Type |
| --------------- | ------------------------------------------------------------------------------------------------------ |
| rootMargin | `string`, [MDN DOcs](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin) |
| boundingElement | `HTMLElement \| Ref<HTMLElement \| undefined>`. The scroll container, defaults to the body. |

## Returns

`UsePositionStickyObserverResponse`
1 change: 1 addition & 0 deletions src/usePositionStickyObserver/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './usePositionStickyObserver'
57 changes: 57 additions & 0 deletions src/usePositionStickyObserver/usePositionStickyObserver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { Ref, computed, onMounted, ref, toValue } from 'vue'

Check failure on line 1 in src/usePositionStickyObserver/usePositionStickyObserver.ts

View workflow job for this annotation

GitHub Actions / Type Validation

Module '"vue"' has no exported member 'toValue'.
import { MaybeRefOrGetter } from '@/types/maybe'
import { useIntersectionObserver } from '@/useIntersectionObserver'

export type UsePositionStickyObserverResponse = {
stuck: Ref<boolean>,
}

export type UsePositionStickyObserverOptions = {
rootMargin?: string,
boundingElement?: MaybeRefOrGetter<HTMLElement | undefined>,
}

const usePositionStickyObserverDefaultOptions = {
rootMargin: '-1px 0px 0px 0px',
boundingElement: document.body,
}

export function usePositionStickyObserver(
element: MaybeRefOrGetter<HTMLElement | undefined>,
options?: MaybeRefOrGetter<UsePositionStickyObserverOptions>,
): UsePositionStickyObserverResponse {
const elementRef = computed(() => toValue(element))
const optionsRef = computed(() => {
if (!options) {
return usePositionStickyObserverDefaultOptions
}

const { rootMargin, boundingElement } = toValue(options)
const boundingElementRef = toValue(boundingElement)

return {
rootMargin: rootMargin ?? usePositionStickyObserverDefaultOptions.rootMargin,
boundingElement: boundingElementRef ?? usePositionStickyObserverDefaultOptions.boundingElement,
}
})

const stuck = ref(false)

function intersect(entries: IntersectionObserverEntry[]): void {
entries.forEach(entry => {
stuck.value = entry.intersectionRatio < 1
})
}

const { observe } = useIntersectionObserver(intersect, computed(() => ({
threshold: [1],
rootMargin: optionsRef.value.rootMargin,
root: optionsRef.value.boundingElement,
})))

onMounted(() => observe(elementRef))

return {
stuck,
}
}

0 comments on commit 8fcf97d

Please sign in to comment.