Skip to content
This repository was archived by the owner on Jan 7, 2026. It is now read-only.

Releases: MilkshakeStudio/nuxt-lenis

Nuxt 4

09 Sep 20:56
9315e85

Choose a tag to compare

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 created
  • lenis:initiated - Triggered when a Lenis instance is fully set up and ready
  • lenis:scroll - Triggered on every scroll event from any Lenis instance
  • lenis: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 RuntimeNuxtHooks interface
  • 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

🔄 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 destroyLenis function
  • Improved type safety in getScrollState function
  • 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.0

Happy scrolling! 🚀

Full Changelog: v2.1.2...v3.0.0

Version 2

09 May 18:05
cb5434c

Choose a tag to compare

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 an onScroll prop (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 to useLenis(), 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 an onScroll prop 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.

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

13 Jun 16:26
9d36f2b

Choose a tag to compare

UseLenis now takes in a Boolean value for single of multiple lenis instances.

Bugs Fixed

  • Lenis not found on rollup.

Return function

21 May 18:49
fd0d63b

Choose a tag to compare

v1.1.1

fix: add function to return empty object in options prop of Lenis.vue…

Restructure

13 Apr 02:04
e61c38d

Choose a tag to compare

New with 1.1.0

  • New composable useLenis()
  • Multiple instances
  • Wrapper based on parent element

PR from felixdenoix

14 Dec 01:23
ce65fa7

Choose a tag to compare

  • 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

28 Sep 14:59

Choose a tag to compare

Updated Lenis Package

Fixed options

02 Sep 18:13

Choose a tag to compare

forgot to actually use the options

Updated ReadMe

09 Aug 15:01

Choose a tag to compare

v1.0.1

update readme

Initial Release

08 Aug 13:22

Choose a tag to compare

Official first release includes:

  • Composable for scrollState and LenisVS
  • Emit on load and on scroll