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 thescrollTo
function returned fromusePotiah
orpotiah.scrollTo
$potiah
-Potiah
instance
<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