@empathyco/x-components
Version:
Empathy X Components
161 lines (125 loc) • 5.7 kB
Markdown
---
title: MainScroll
---
# MainScroll
Extends the scroll making it able to sync the first visible element, and allowing
the children position to be restored.
Each child element that wants to have this support must be wrapped in a MainScrollItem
component.
## Props
| Name | Description | Type | Default |
| ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------ |
| <code>useWindow</code> | If `true`, sets this scroll instance to the main of the application. Being the main<br />scroll implies that features like restoring the scroll when the query changes, or storing<br />the scroll position in the URL will be enabled for this container. | <code>boolean</code> | <code>false</code> |
| <code>restoreScrollTimeoutMs</code> | Timeout in milliseconds to abort trying to restore the scroll position to the target<br />element. | <code>number</code> | <code>5000</code> |
| <code>threshold</code> | Intersection percentage to consider an element visible. | <code>number</code> | <code>0.3</code> |
| <code>margin</code> | Adjusts the size of the scroll container bounds. | <code>string</code> | <code>'0px'</code> |
## Events
This component emits the following events:
- [`UserScrolledToElement`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts)
- [`ScrollRestoreFailed`](https://github.com/empathyco/x/blob/main/packages/x-components/src/wiring/events.types.ts)
## See it in action
The `MainScroll` component must be an ancestor of the `MainScrollItem` components. This is because
it injects the needed utilities to determine the first visible item.
```vue
<template>
<MainScroll>
<ul>
<MainScrollItem v-for="item in 24" tag="li">Item {{ item }}</MainScrollItem>
</ul>
</MainScroll>
</template>
<script>
import { MainScroll, MainScrollItem } from '@empathyco/x-components/scroll'
export default {
name: 'MainScrollDemo',
components: {
MainScroll,
MainScrollItem,
},
}
</script>
<style lang="css" scoped>
ul {
overflow: auto;
max-height: 200px;
}
li {
height: 50px;
line-height: 50px;
}
</style>
```
### Play with props
#### Window scroll
In case you aren't using a custom scrolling element like the `Scroll` panel, and want to use the
default browser scroll, you can do so by using the `useWindow` prop:
```vue
<template>
<MainScroll useWindow>
<ul>
<MainScrollItem v-for="item in 24" tag="li">Item {{ item }}</MainScrollItem>
</ul>
</MainScroll>
</template>
<script>
import { MainScroll, MainScrollItem } from '@empathyco/x-components/scroll'
export default {
name: 'MainScrollDemo',
components: {
MainScroll,
MainScrollItem,
},
}
</script>
```
#### Timeout for restoring scroll
When your application is loaded, this component, together with the `MainScrollItem` will try to
restore the scroll to the provided position (if available). Because of the dynamic nature of
JavaScript applications, the element that it tries to restore the scroll to might not be available
anymore. For this reason after a defined time, the scroll restoration will be considered failed.
This time can be configured through the `restore-scroll-timeout-ms` prop. This is specially useful
when combined with the URL X Module.
```vue
<template>
<MainScroll :restoreScrollTimeoutMs="1000">
<ul>
<MainScrollItem v-for="item in 24" tag="li">Item {{ item }}</MainScrollItem>
</ul>
</MainScroll>
</template>
<script>
import { MainScroll, MainScrollItem } from '@empathyco/x-components/scroll'
export default {
name: 'MainScrollDemo',
components: {
MainScroll,
MainScrollItem,
},
}
</script>
```
#### Adjust first visible item
By default this component will consider the first visible item, the first element that is at least
intersecting a 50% with its container. However this arbitrary number might not always be the best.
To configure this, you can use the `margin` and `threshold` props, which work exactly like in the
`IntersectionObserver` API. In this example we are reducing the bounds of the intersection by 50px,
and adjusting the element to be at least 75% intersecting.
```vue
<template>
<MainScroll :threshold="0.75" margin="-50px">
<ul>
<MainScrollItem v-for="item in 24" tag="li">Item {{ item }}</MainScrollItem>
</ul>
</MainScroll>
</template>
<script>
import { MainScroll, MainScrollItem } from '@empathyco/x-components/scroll'
export default {
name: 'MainScrollDemo',
components: {
MainScroll,
MainScrollItem,
},
}
</script>
```