import { Meta, Canvas } from '@storybook/addon-docs/blocks'
import * as SyncStories from './../../../docs/guides/sync-grid.stories'

<Meta title="pv-grid/Hooks/useScrollSync" />

# useScrollSync

If you need to sync scrolling with the `Grid` this can be achieved by wrapping the view to sync and the `Grid` in a `GridSyncProvider` and using the `useScrollSync` hook.

```tsx
import { useScrollSync } from '@planview/pv-grid'
```

### Definition

```tsx
function useScrollSync: <T extends HTMLElement>(ref: React.RefObject<T>, bounds?: {head: number, tail: number}) => void
```

### Usage

In the example below, the view wraps a `Grid` and a non-grid view next to it inside a `GridSyncProvider`.
The ref of the view to sync with the grid is passed to the `useScrollSync` hook.

_Since the grid internally uses the hook, it will start to sync with the `MyRightPanel` component._

```tsx
import { Grid, GridSyncProvider, useScrollSync } from '@planview/pv-grid'

const MyRightPanel = () => {
    const ref = React.useRef()
    useScrollSync(ref)
    return <div ref={ref}>{/*content obscured for documentation purpose*/}</div>
}

const MySyncedView = () => {
    return (
        <GridSyncProvider>
            <Grid {.../*props obscured for documentation purpose*/} />
            <MyRightPanel />
        </GridSyncProvider>
    )
}
```

<Canvas of={SyncStories.Default} />

### Adjusting for grid scroll head and tail

As you might have noticed in the example below, there are blank areas above and below the synced list to the right of the grid _(here referred to as `head` and `tail`)_. Those areas are added so that the right panel adjusts for heights that may displace the scroll area from the top/bottom.
Reasons for this can be sticky **headers** or **footers** but also **horizontal scrollbars**. To help adjust for these factors two [css custom properties](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties)s are added to the element passed to the hook. `--grid-scroll-head` and `--grid-scroll-tail`.
The values of these properties are calculated based on how elements within a sync context stack next to each other and should be used when styling the synced panel to adjust for head and tail.

In the example above the adjustment is made by using **padding**, but it's up to the consumer to figure out how to best style the scrolling element.

```css
padding-top: var(--grid-scroll-head);
padding-bottom: var(--grid-scroll-tail);
```

### Head and/or tail in synced component

If the list were to have it's own head, (e.g. a sticky header), the height of the head needs to be passed to the hook via the second (`bounds`) argument of the hook. This will let all synced panels within the context know and adjust to the head of the panel and make sure all content is aligned properly.

_Heights of horizontal scrollbars are automatically calculated and are not required to be passed in._

```tsx
//Pass in the height of the panels sticky header to the hook.
useScrollSync(ref, { head: 36 })
```
