UNPKG

@empathyco/x-components

Version:
161 lines (125 loc) 5.7 kB
--- 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> ```