Creating scroll scene β
There will be only simple code examples to introduce the basic concepts and capabilities of Potiah.
Basic β
Wrap all your app components with ScrollView.
<script setup lang="ts">
import { ScrollView } from 'potiah'
</script>
<template>
<ScrollView root>
<!-- your components/content -->
</ScrollView>
</template><script setup lang="ts">
import { ScrollView } from 'potiah'
</script>
<template>
<ScrollView root>
<!-- your components/content -->
</ScrollView>
</template>This will enable smooth scroll from lenis on whole document. The root prop means that scroll will use window as a wrapper and document.documentElement as the scrollable content and won't create any additional HTML elements.
Smooth scroll and nothing else
If smooth scroll from Lenis is all what you want, you can stop right there π
Attributes
Actually you can define data-* attributes on components/elements within ScrollView and Locomotive Scroll will work. But for this purpose the library provides ScrollComponent component with many features. Look here.
Single scroll instance
There is single available instance of Potiah for each app. So, if You mount multiple ScrollView components at once, the latter will work and previous not.
Reactive prop β
ScrollView properties include some Lenis instance options.
<script setup lang="ts">
import { ref } from 'vue'
import { ScrollView } from 'potiah'
const duration = ref(1.2)
</script>
<template>
<ScrollView root :duration="duration">
<button @click="duration++">+</button>
<button @click="duration--">-</button>
<button @click="duration = 1.2">RESET</button>
</ScrollView>
</template><script setup lang="ts">
import { ref } from 'vue'
import { ScrollView } from 'potiah'
const duration = ref(1.2)
</script>
<template>
<ScrollView root :duration="duration">
<button @click="duration++">+</button>
<button @click="duration--">-</button>
<button @click="duration = 1.2">RESET</button>
</ScrollView>
</template>For example, current page content is rendered inside ScrollView, which accepts reactive prop duration. Try to change duration ref value with the buttons below and see how the scrolling behavior changes.
Value
Duration of scroll animation is 1.0s .
See also ScrollView
More advanced β
ScrollComponent gathering data-* attributes from LocomotiveScroll element.
ScrollComponent can be as deep as you need it to be, until it is rendered within ScrollView.
You can place your components / content inside ScrollComponent. In fact, ScrollComponent is just a wrapper with native HTML element inside. The is argument specifies which HTML element will be rendered.
Reactivity
Not all props are reactive (react to updates)! You can see details on component page.
<script setup lang="ts">
import { ScrollView, ScrollComponent } from 'potiah'
</script>
<template>
<ScrollView root>
<ScrollComponent is="section" class="first-scroll-component" :speed="0.2">
<!-- your components/content -->
</ScrollComponent>
<ScrollComponent is="div" class="second-scroll-component" position="start,end">
<!-- your components/content -->
</ScrollComponent>
<!-- your components/content -->
</ScrollView>
</template><script setup lang="ts">
import { ScrollView, ScrollComponent } from 'potiah'
</script>
<template>
<ScrollView root>
<ScrollComponent is="section" class="first-scroll-component" :speed="0.2">
<!-- your components/content -->
</ScrollComponent>
<ScrollComponent is="div" class="second-scroll-component" position="start,end">
<!-- your components/content -->
</ScrollComponent>
<!-- your components/content -->
</ScrollView>
</template>See also ScrollComponent
Composable β
usePotiah - composable that returns Potiah instance, scrollTo function, direction, isScrolling refs.
scrollTo can be used to scroll target element or specified value in pixels.
scrollTo
This page uses the scrollTo function to scroll to anchors by clicking on links in the right bar or on headers anchors.
<script setup lang="ts">
import { computed } from "vue";
import { usePotiah, ScrollView } from "potiah";
const { direction, isScrolling, potiah } = usePotiah();
const scrollText = computed(() => {
let text = "βΊοΈ not scrolling";
if (isScrolling.value) { // or potiah.isScrolling
// or potiah.direction
text = direction.value == 1 ? "β¬οΈ scrolling down" : "β¬οΈ scrolling up";
}
return text;
});
</script>
<template>
<ScrollView root>
<span>{{ scrollText }}</span>
<!-- your components/content -->
</ScrollView>
</template><script setup lang="ts">
import { computed } from "vue";
import { usePotiah, ScrollView } from "potiah";
const { direction, isScrolling, potiah } = usePotiah();
const scrollText = computed(() => {
let text = "βΊοΈ not scrolling";
if (isScrolling.value) { // or potiah.isScrolling
// or potiah.direction
text = direction.value == 1 ? "β¬οΈ scrolling down" : "β¬οΈ scrolling up";
}
return text;
});
</script>
<template>
<ScrollView root>
<span>{{ scrollText }}</span>
<!-- your components/content -->
</ScrollView>
</template>With the code example above, we can make a computed property that gives us information about the current scrolling state, as shown below:
You are: βΊοΈ not scrolling
See also usePotiah
Event β
ScrollView emits lenis-scroll event when perform smooth scrolling. Therefore, you can use values from event to make animations, transitions, change states, anything what possible π.
<script setup lang="ts">
import { ref } from "vue";
import { ScrollView } from "potiah";
const velocity = ref(0)
</script>
<template>
<ScrollView root @lenis-scroll='(l) => (velocity = l.velocity)'>
<span>{{ velocity }}</span>
<!-- your components/content -->
</ScrollView>
</template><script setup lang="ts">
import { ref } from "vue";
import { ScrollView } from "potiah";
const velocity = ref(0)
</script>
<template>
<ScrollView root @lenis-scroll='(l) => (velocity = l.velocity)'>
<span>{{ velocity }}</span>
<!-- your components/content -->
</ScrollView>
</template>Velocity is 0
Bad practice
Example above use reactive ref as velocity value for simplicity. This can result in pure performance due to the high frequency of the emitted event. You want to avoid this and change the DOM element property directly in such a case as above.
Non-root view β
ScrollView can be a non-root component. Next means that wrapper and content elements will be rendered.
For scrolling to work specify height and overflow style properties for ScrollView wrapper element.
<script setup lang="ts">
import { ScrollView } from 'potiah'
</script>
<template>
<header>
<!-- header content -->
</header>
<ScrollView class="scroll-wrapper">
<!-- scroll content -->
</ScrollView>
<footer>
<!-- footer content -->
</footer>
</template>
<style>
.scroll-wrapper {
height: 80vh;
overflow-y: hidden;
}
</style><script setup lang="ts">
import { ScrollView } from 'potiah'
</script>
<template>
<header>
<!-- header content -->
</header>
<ScrollView class="scroll-wrapper">
<!-- scroll content -->
</ScrollView>
<footer>
<!-- footer content -->
</footer>
</template>
<style>
.scroll-wrapper {
height: 80vh;
overflow-y: hidden;
}
</style>See also ScrollView
Global properties β
There are two global properties of the app available in template:
$scrollTo- same as thescrollTofunction returned fromusePotiahorpotiah.scrollTo$potiah-Potiahinstance
<script setup lang="ts">
import { ScrollView } from 'potiah'
</script>
<template>
<ScrollView root>
<button @click="$scrollTo('#target-id')">Scroll To</button>
<span>{{ $potiah.isScrolling }}</span>
<!-- scroll content -->
</ScrollView>
</template><script setup lang="ts">
import { ScrollView } from 'potiah'
</script>
<template>
<ScrollView root>
<button @click="$scrollTo('#target-id')">Scroll To</button>
<span>{{ $potiah.isScrolling }}</span>
<!-- scroll content -->
</ScrollView>
</template>Try It Online β
If you want to see how things works you can try it directly in your browser
Limitations β
Dynamic rendering β οΈ
For now it is not possible to dynamically change layout inside ScrollView.
See also limitations