Releases: MilkshakeStudio/nuxt-lenis
Nuxt 4
Release Notes v3.0.0
🚀 Major Release: Global Hooks System
We're excited to announce nuxt-lenis v3.0.0, a major release that introduces a powerful global hooks system, enabling developers to tap into Lenis lifecycle events from anywhere in their Nuxt application.
✨ New Features
🎯 Global Hooks System
The biggest addition in v3.0.0 is the introduction of global hooks using Nuxt's native hook system. This allows for powerful integrations and decoupled architecture.
Available Hooks:
lenis:created- Triggered when a Lenis instance is createdlenis:initiated- Triggered when a Lenis instance is fully set up and readylenis:scroll- Triggered on every scroll event from any Lenis instancelenis:destroy- Triggered before a Lenis instance is destroyed
Usage Example:
<script setup>
import { useNuxtApp } from '#app'
const nuxtApp = useNuxtApp()
onMounted(() => {
// Listen for Lenis initiation
nuxtApp.hook('lenis:initiated', (payload) => {
console.log('🚀 Lenis ready:', payload.id)
// Your custom initialization logic here
})
// Listen for scroll events
nuxtApp.hook('lenis:scroll', (payload) => {
console.log('Scroll progress:', payload.state.progress)
})
})
</script>📋 Hook Payloads
Each hook provides rich payload data:
// lenis:created
{ lenis: Lenis, id: string, options: LenisOptions }
// lenis:initiated
{ lenis: Lenis, id: string, isDefault: boolean }
// lenis:scroll
{ lenis: Lenis, id: string, state: ScrollState }
// lenis:destroy
{ lenis: Lenis | undefined, id: string }🎨 Enhanced TypeScript Support
- Added comprehensive type definitions for all hooks
- Extended Nuxt's
RuntimeNuxtHooksinterface - Full IntelliSense support for hook payloads
🛠️ Technical Improvements
Architecture Enhancements
- Decoupled Event System: Components can now react to Lenis events without direct coupling
- Native Nuxt Integration: Uses Nuxt's built-in hook system (
nuxtApp.hook()/nuxtApp.callHook()) - Performance Optimized: Efficient event propagation with minimal overhead
Developer Experience
- Rich Debugging: Console logging for all lifecycle events
- Documentation: Comprehensive docs with real-world examples
- Playground Examples: Live examples demonstrating hook usage
🎯 Use Cases
The new hooks system enables powerful integrations:
Analytics & Tracking
<script setup>
nuxtApp.hook('lenis:scroll', (payload) => {
if (payload.state.progress % 0.25 === 0) {
gtag('event', 'scroll_progress', {
progress: Math.round(payload.state.progress * 100)
})
}
})
</script>Custom Animations
<script setup>
nuxtApp.hook('lenis:scroll', (payload) => {
const { scroll, velocity, direction } = payload.state
// Create custom scroll-based effects
updateParallaxElements(scroll)
updateScrollIndicator(payload.state.progress)
})
</script>Global State Management
<script setup>
const globalScrollState = reactive({
isScrolling: false,
progress: 0,
velocity: 0
})
nuxtApp.hook('lenis:scroll', (payload) => {
Object.assign(globalScrollState, {
isScrolling: payload.state.isScrolling,
progress: payload.state.progress,
velocity: payload.state.velocity
})
})
</script>📚 Documentation
- Hooks Guide - Comprehensive guide with examples
- Playground Examples - Live demonstrations
- TypeScript Definitions - Full type support
🔄 Migration Guide
From v2.x to v3.0.0
This is a non-breaking release! All existing functionality remains unchanged. The hooks system is an additive feature.
No migration required - your existing code will continue to work exactly as before.
New Projects
For new projects, you can immediately start using the hooks system:
<script setup>
import { useNuxtApp } from '#app'
const nuxtApp = useNuxtApp()
onMounted(() => {
nuxtApp.hook('lenis:initiated', (payload) => {
// Your code here
})
})
</script>🐛 Bug Fixes
- Fixed TypeScript errors in
destroyLenisfunction - Improved type safety in
getScrollStatefunction - Enhanced error handling in hook callbacks
📦 Dependencies
- Lenis:
^1.2.3(unchanged) - Nuxt: Compatible with
^4.0.0
🚀 Performance
- Zero overhead when hooks are not used
- Minimal impact when hooks are registered
- Efficient propagation of scroll events
🔮 Future Roadmap
- v3.1.0: Additional hooks (
lenis:start,lenis:stop,lenis:resize) - v3.2.0: Hook middleware system for advanced filtering
- v3.3.0: Built-in analytics integrations
💝 Acknowledgments
Special thanks to the community for requesting this feature and providing valuable feedback during development.
📝 Full Changelog
Added
- 🎯 Global hooks system using Nuxt's native hooks
- 📋 Four new lifecycle hooks (
created,initiated,scroll,destroy) - 🎨 Comprehensive TypeScript definitions
- 📚 Documentation and examples
- 🎮 Interactive playground demos
Fixed
- 🐛 TypeScript errors in instance management
- 🔧 Improved type safety across the module
Changed
- 📦 Version bump to 3.0.0 (major feature addition)
- 🏗️ Enhanced internal architecture for hook support
Install the latest version:
npm install nuxt-lenis@^3.0.0Happy scrolling! 🚀
Full Changelog: v2.1.2...v3.0.0
Version 2
Nuxt Lenis - Version 2 Release Notes
Overview
Version 2 of Nuxt Lenis introduces a major refactor of the module’s architecture. The primary goal of this release is to provide a more robust, type-safe, and reactive API by centralizing multiple Lenis instances via a Nuxt plugin and exposing a composable API. This release also simplifies the component interface by replacing emitted events with a prop for scroll callbacks.
New Features & Improvements
-
Centralized Instance Management:
The Nuxt plugin now centrally manages all Lenis instances. This makes it easier to create, retrieve, and destroy instances using a unique ID. -
Composable API (
useLenis):
A new composable is provided for accessing Lenis methods and reactive scroll states. The API includes:createLenis: Creates and registers a new Lenis instance.getLenis: Retrieves a Lenis instance by ID (or the default if no ID is provided).destroyLenis: Destroys a Lenis instance and cleans up its state.scrollState: Returns reactive scroll state data.watchScrollState: Allows you to subscribe to scroll state changes.
-
Simplified Component Interface:
The<lenis>component now accepts anonScrollprop (instead of emitting events) for scroll callback functions, reducing boilerplate and streamlining integration. -
Type Safety & Reactivity:
The module has been fully refactored with TypeScript, enabling advanced type checking and ensuring reactive state management via Vue’s built-in reactivity APIs. -
Multiple Instance Support:
Both single and multiple instance modes are supported. By providing a unique ID to the<lenis>component and passing the appropriate flag touseLenis(), developers can easily work with multiple scrolling contexts.
Breaking Changes
-
Removed Emits for Scroll Events:
Instead of emitting scroll events, the<lenis>component now expects anonScrollprop for handling scroll callbacks. -
Refactored Plugin API:
- The plugin now exposes the methods (
createLenis,getLenis,destroyLenis,getScrollState) directly via the composable. - Projects using previous versions will need to update their usage to utilize the new composable API.
- The plugin now exposes the methods (
Example Usage
Component Integration
<template>
<lenis id="default" :options="LenisOptions" onScroll="handleScroll">
<NuxtPage />
</lenis>
</template>
<script setup lang="ts">
const LenisOptions = {
smooth: true,
duration: 1.2,
autoRaf: true,
direction: 'vertical'
};
const handleScroll = (data: any) => {
console.log("Scroll detected:", data);
};
</script>Composable Integration
Single Instance
<script setup lang="ts">
import { watch } from 'vue';
import { useLenis } from '#imports';
const { scrollState, getLenis } = useLenis();
// Retrieve the default instance
const instance = getLenis(); // returns the Lenis instance or null
// Watch for scroll state changes
watch(scrollState, (state) => {
console.log("Scroll state:", state);
}, { deep: true });
</script>Multiple Instances
<template>
<lenis id="main">
<NuxtPage />
</lenis>
<lenis id="modal">
<NuxtPage />
</lenis>
</template>
<script setup lang="ts">
import { useLenis } from '#imports';
// Use multiple instance mode by invoking `useLenis(false)`
const { scrollState, getLenis } = useLenis(false);
// Access instances by their ID
const mainInstance = getLenis("main");
const modalInstance = getLenis("modal");
console.log("Main scroll state:", scrollState("main"));
console.log("Modal scroll state:", scrollState("modal"));
</script>Conclusion
Version 2 of Nuxt Lenis greatly improves the flexibility and maintainability of the module through better state management, increased type safety, and a more intuitive API. Enjoy smoother scrolling experiences and enhanced customization!
Happy scrolling!
Single or Multiple
UseLenis now takes in a Boolean value for single of multiple lenis instances.
Bugs Fixed
- Lenis not found on rollup.
Return function
v1.1.1 fix: add function to return empty object in options prop of Lenis.vue…
Restructure
New with 1.1.0
- New composable
useLenis() - Multiple instances
- Wrapper based on parent element
PR from felixdenoix
- Changed the usage of the props in the lenis component to ensure it reacts to props changes.
- raf is canceled in the same time the component is destroyed.
Thank you @felixdenoix
Updated Packages
Updated Lenis Package
Fixed options
forgot to actually use the options
Updated ReadMe
v1.0.1 update readme
Initial Release
Official first release includes:
- Composable for scrollState and LenisVS
- Emit on load and on scroll