> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# useScrollCallback

> A hook for responding to scroll position changes with callbacks.

A hook for responding to scroll position changes with callbacks for scrolling down and returning to top.

## Usage

```tsx theme={null}
import { useScrollCallback } from "@servicetitan/anvil2-ext-atlas";

function ScrollAwareComponent() {
  const containerRef = useRef<HTMLDivElement>(null);
  const [showScrollToTop, setShowScrollToTop] = useState(false);

  useScrollCallback({
    element: containerRef.current,
    threshold: 100,
    onScrollDown: () => setShowScrollToTop(true),
    onScrollTop: () => setShowScrollToTop(false),
  });

  return (
    <div ref={containerRef} style={{ overflow: "auto", height: 400 }}>
      {/* Scrollable content */}
      {showScrollToTop && (
        <button onClick={() => scrollToTop()}>Back to Top</button>
      )}
    </div>
  );
}
```

## Options

| Option       | Type        | Default | Description                             |
| ------------ | ----------- | ------- | --------------------------------------- |
| element      | HTMLElement | null    | The scrollable element to monitor       |
| threshold    | number      | 50      | Pixel threshold to trigger onScrollDown |
| onScrollDown | () => void  | -       | Callback when scrolled past threshold   |
| onScrollTop  | () => void  | -       | Callback when scrolled back to top      |

## Returns

| Property               | Type    | Description                             |
| ---------------------- | ------- | --------------------------------------- |
| lastScrollTop          | number  | Last recorded scroll position           |
| hasTriggeredScrollDown | boolean | Whether onScrollDown has been triggered |

## Behavior

* **One-time Trigger**: `onScrollDown` only fires once per scroll session (until returning to top)
* **Top Detection**: `onScrollTop` fires when scroll position returns to 0
* **Passive Listener**: Uses passive event listener for better scroll performance
* **Window Fallback**: Falls back to window scroll if no element is provided

## Example: Show/Hide Header on Scroll

```tsx theme={null}
import { useScrollCallback } from "@servicetitan/anvil2-ext-atlas";

function ChatWithCollapsibleHeader() {
  const contentRef = useRef<HTMLDivElement>(null);
  const [headerCollapsed, setHeaderCollapsed] = useState(false);

  useScrollCallback({
    element: contentRef.current,
    threshold: 50,
    onScrollDown: () => setHeaderCollapsed(true),
    onScrollTop: () => setHeaderCollapsed(false),
  });

  return (
    <div className="chat-container">
      <Header 
        title="Atlas" 
        className={headerCollapsed ? "collapsed" : ""} 
      />
      <div ref={contentRef} className="chat-content">
        {/* Messages */}
      </div>
    </div>
  );
}
```

## Example: Lazy Load Images on Scroll

```tsx theme={null}
import { useScrollCallback } from "@servicetitan/anvil2-ext-atlas";

function LazyImageGallery() {
  const galleryRef = useRef<HTMLDivElement>(null);
  const [imagesLoaded, setImagesLoaded] = useState(false);

  useScrollCallback({
    element: galleryRef.current,
    threshold: 200,
    onScrollDown: () => {
      if (!imagesLoaded) {
        loadHighResImages();
        setImagesLoaded(true);
      }
    },
  });

  return (
    <div ref={galleryRef} className="gallery">
      {images.map((img) => (
        <img 
          key={img.id} 
          src={imagesLoaded ? img.highRes : img.placeholder} 
        />
      ))}
    </div>
  );
}
```
