Initial commit
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# useScrollPosition
|
||||
|
||||
Tracks the vertical scroll position of the window or a specific scrollable element.
|
||||
|
||||
## Signature
|
||||
|
||||
```ts
|
||||
function useScrollPosition(options?: { targetRef?: RefObject<HTMLElement | Document> }): number;
|
||||
```
|
||||
|
||||
### Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ----------- | ------------------------------------ | ---------- | ------------------------------------------------------- |
|
||||
| `targetRef` | `RefObject<HTMLElement \| Document>` | `document` | Ref to a scrollable element; falls back to the document |
|
||||
|
||||
Returns the current `scrollY` (window) or `scrollTop` (element) as a number.
|
||||
|
||||
## Usage
|
||||
|
||||
```tsx
|
||||
// Track window scroll
|
||||
function ScrollProgress() {
|
||||
const scrollY = useScrollPosition();
|
||||
|
||||
return <div>Scrolled: {scrollY}px</div>;
|
||||
}
|
||||
```
|
||||
|
||||
```tsx
|
||||
// Track a specific scrollable container
|
||||
function VirtualList() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const scrollTop = useScrollPosition({ targetRef: containerRef });
|
||||
|
||||
return (
|
||||
<div ref={containerRef} style={{ overflowY: 'auto', height: 400 }}>
|
||||
{/* items */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
- Initial position is read synchronously on mount so there is no flash to `0`.
|
||||
- Automatically switches between `window.scrollY` and `element.scrollTop` based on the target.
|
||||
- Client-only (`'use client'`).
|
||||
@@ -0,0 +1 @@
|
||||
export * from './useScrollPosition';
|
||||
@@ -0,0 +1,34 @@
|
||||
'use client';
|
||||
|
||||
import { RefObject, useEffect, useState } from 'react';
|
||||
|
||||
interface UseScrollPositionProps {
|
||||
targetRef?: RefObject<HTMLElement | Document | undefined>; // Ref to the scrollable element
|
||||
}
|
||||
|
||||
export function useScrollPosition({ targetRef }: UseScrollPositionProps = {}): number {
|
||||
const [scrollPosition, setScrollPosition] = useState<number>(0);
|
||||
|
||||
useEffect(() => {
|
||||
// If the ref is not provided or its current value is null, fall back to document
|
||||
const target = targetRef?.current || document;
|
||||
const scrollable = target === document ? window : target;
|
||||
|
||||
const updatePosition = () => {
|
||||
// Determine if we're scrolling the document or a specific element
|
||||
const scrollY = target === document ? window.scrollY : (target as HTMLElement).scrollTop;
|
||||
setScrollPosition(scrollY);
|
||||
};
|
||||
|
||||
scrollable.addEventListener('scroll', updatePosition);
|
||||
|
||||
// Set the initial position
|
||||
updatePosition();
|
||||
|
||||
return () => {
|
||||
scrollable.removeEventListener('scroll', updatePosition);
|
||||
};
|
||||
}, [targetRef]);
|
||||
|
||||
return scrollPosition;
|
||||
}
|
||||
Reference in New Issue
Block a user