CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-smooth-scrollbar

Customize scrollbar in modern browsers with smooth scrolling experience.

Pending
Overview
Eval results
Files

momentum-control.mddocs/

Momentum Control

Advanced momentum control for natural scrolling physics with customizable easing and momentum manipulation. Provides fine-grained control over scroll momentum for creating smooth, physics-based scrolling experiences.

Capabilities

Basic Momentum Control

Methods for directly manipulating scroll momentum during scrolling operations.

/**
 * Adds momentum to current scroll velocity
 * @param x - Horizontal momentum to add
 * @param y - Vertical momentum to add
 */
addMomentum(x: number, y: number): void;

/**
 * Sets scroll momentum directly, replacing current momentum
 * @param x - Horizontal momentum value
 * @param y - Vertical momentum value
 */
setMomentum(x: number, y: number): void;

Usage Examples:

// Add momentum for smooth continuation
scrollbar.addMomentum(0, 200); // Add downward momentum

// Stop all momentum immediately
scrollbar.setMomentum(0, 0);

// Set specific momentum for custom scrolling effects
scrollbar.setMomentum(50, -100); // Right and up momentum

Transformable Momentum

Advanced momentum control that allows event-based momentum transformation with callback support.

/**
 * Adds momentum that can be transformed by plugins, with callback notification
 * @param x - Horizontal momentum to add
 * @param y - Vertical momentum to add
 * @param fromEvent - Source event that generated the momentum
 * @param callback - Optional callback function called with scroll decision
 */
addTransformableMomentum(
  x: number, 
  y: number, 
  fromEvent: Event, 
  callback?: AddTransformableMomentumCallback
): void;

Usage Examples:

// Add momentum from custom gesture
const customGestureEvent = new CustomEvent("swipe");
scrollbar.addTransformableMomentum(0, 300, customGestureEvent, function(willScroll) {
  if (willScroll) {
    console.log("Scrolling will occur");
    // Add visual feedback
    this.containerEl.classList.add("scrolling");
  } else {
    console.log("Scroll was prevented by plugin");
  }
});

// Custom momentum with mouse wheel simulation
const wheelEvent = new WheelEvent("wheel", { deltaY: 120 });
scrollbar.addTransformableMomentum(0, 120, wheelEvent, function(willScroll) {
  // Track scroll analytics
  analytics.track("custom_scroll", { willScroll, momentum: 120 });
});

Momentum Physics Configuration

Configuration options that affect momentum behavior and physics calculations.

interface ScrollbarOptions {
  /**
   * Momentum reduction damping factor, float between (0, 1)
   * Lower values = more smooth scrolling (more frames)
   * Higher values = quicker momentum decay
   */
  damping: number;
  
  /**
   * Render every frame in integer pixel values
   * Improves performance by avoiding sub-pixel rendering
   */
  renderByPixels: boolean;
  
  /**
   * Allow outer scrollbars to continue scrolling when this reaches edge
   * Affects momentum transfer to parent scrollable elements
   */
  continuousScrolling: boolean;
}

Usage Examples:

// Ultra-smooth momentum (more CPU intensive)
const smoothScrollbar = Scrollbar.init(container, {
  damping: 0.05,  // Very low damping for long momentum
  renderByPixels: false  // Sub-pixel rendering for smoothness
});

// Performance-optimized momentum
const fastScrollbar = Scrollbar.init(container, {
  damping: 0.2,   // Higher damping for quicker stops
  renderByPixels: true,  // Integer pixels for performance
  continuousScrolling: false  // Contain momentum within this scrollbar
});

Advanced Momentum Patterns

Custom Momentum Easing

Creating custom momentum behavior through easing functions and momentum manipulation.

// Custom elastic momentum effect
function addElasticMomentum(scrollbar, targetY, elasticity = 0.8) {
  const currentY = scrollbar.scrollTop;
  const distance = targetY - currentY;
  
  // Apply elastic easing
  const momentum = distance * elasticity;
  
  scrollbar.addTransformableMomentum(0, momentum, new Event("custom"), function(willScroll) {
    if (willScroll && Math.abs(distance) > 1) {
      // Continue elastic animation
      setTimeout(() => {
        addElasticMomentum(scrollbar, targetY, elasticity * 0.9);
      }, 16);
    }
  });
}

// Usage
addElasticMomentum(scrollbar, 500);

Momentum-Based Gestures

Implementing swipe gestures and momentum-based interactions.

class SwipeGestureHandler {
  private startY = 0;
  private lastY = 0;
  private velocity = 0;
  private lastTime = 0;
  
  constructor(private scrollbar: Scrollbar) {
    this.setupGestureListeners();
  }
  
  private setupGestureListeners() {
    const container = this.scrollbar.containerEl;
    
    container.addEventListener("touchstart", (e) => {
      this.startY = e.touches[0].clientY;
      this.lastY = this.startY;
      this.velocity = 0;
      this.lastTime = Date.now();
    });
    
    container.addEventListener("touchmove", (e) => {
      const currentY = e.touches[0].clientY;
      const currentTime = Date.now();
      const deltaTime = currentTime - this.lastTime;
      
      if (deltaTime > 0) {
        this.velocity = (currentY - this.lastY) / deltaTime;
      }
      
      this.lastY = currentY;
      this.lastTime = currentTime;
    });
    
    container.addEventListener("touchend", (e) => {
      // Convert velocity to momentum
      const momentum = this.velocity * 300; // Scale factor
      
      this.scrollbar.addTransformableMomentum(0, -momentum, e, function(willScroll) {
        if (willScroll) {
          // Add momentum-based visual feedback
          this.containerEl.style.transition = "transform 0.1s ease-out";
          this.containerEl.style.transform = `translateY(${momentum > 0 ? -2 : 2}px)`;
          
          setTimeout(() => {
            this.containerEl.style.transform = "";
            this.containerEl.style.transition = "";
          }, 100);
        }
      });
    });
  }
}

// Usage
const gestureHandler = new SwipeGestureHandler(scrollbar);

Momentum Monitoring

Tracking and analyzing momentum for performance optimization and user experience.

class MomentumMonitor {
  private momentumHistory: Array<{time: number, momentum: Data2d}> = [];
  
  constructor(private scrollbar: Scrollbar) {
    this.setupMonitoring();
  }
  
  private setupMonitoring() {
    // Override addMomentum to track all momentum changes
    const originalAddMomentum = this.scrollbar.addMomentum.bind(this.scrollbar);
    
    this.scrollbar.addMomentum = (x: number, y: number) => {
      this.recordMomentum(x, y);
      return originalAddMomentum(x, y);
    };
  }
  
  private recordMomentum(x: number, y: number) {
    this.momentumHistory.push({
      time: Date.now(),
      momentum: { x, y }
    });
    
    // Keep only recent history
    if (this.momentumHistory.length > 100) {
      this.momentumHistory.shift();
    }
  }
  
  getMomentumStats() {
    if (this.momentumHistory.length === 0) return null;
    
    const totalMagnitude = this.momentumHistory.reduce((sum, entry) => {
      return sum + Math.sqrt(entry.momentum.x ** 2 + entry.momentum.y ** 2);
    }, 0);
    
    return {
      averageMagnitude: totalMagnitude / this.momentumHistory.length,
      peakMomentum: this.momentumHistory.reduce((max, entry) => {
        const magnitude = Math.sqrt(entry.momentum.x ** 2 + entry.momentum.y ** 2);
        return Math.max(max, magnitude);
      }, 0),
      momentumEvents: this.momentumHistory.length
    };
  }
}

// Usage
const monitor = new MomentumMonitor(scrollbar);

// Later, get performance insights
setInterval(() => {
  const stats = monitor.getMomentumStats();
  console.log("Momentum stats:", stats);
}, 5000);

Momentum Callback Types

interface AddTransformableMomentumCallback {
  /**
   * Callback function called after momentum transformation
   * @param willScroll - Whether scrolling will actually occur after transformation
   */
  (this: Scrollbar, willScroll: boolean): void;
}

interface Data2d {
  /** Horizontal component */
  x: number;
  
  /** Vertical component */
  y: number;
}

Install with Tessl CLI

npx tessl i tessl/npm-smooth-scrollbar

docs

core-management.md

index.md

instance-control.md

momentum-control.md

plugin-system.md

tile.json