ui-animated/README.md
autocommit 0c568f0e60 chore: initial package split from monorepo
Package: @lilith/ui-animated
Split from: lilith/ui.git or lilith/build.git
Publish workflow: calls lilith/workflows/.forgejo/workflows/publish-npm.yml@main
2026-04-20 01:11:15 -07:00

7.3 KiB

@lilith/ui-animated

Animation components and hooks for React applications. Includes scroll-triggered animations, parallax effects, magnetic button interactions, and reusable keyframe animations.

Features

  • FadeIn - Scroll-triggered fade-in animations with direction control
  • ParallaxSection - Sections with parallax scrolling background effects
  • MBAButton - Magnetic Button Animation with hover proximity effects
  • MBACollection - Container for coordinating multiple magnetic buttons
  • Keyframe Animations - Reusable CSS keyframe animations for styled-components
  • Custom Hooks - useScrollTrigger, useParallax, useMagneticEffect, useSmoothScroll

Installation

npm install @lilith/ui-animated
# or
pnpm add @lilith/ui-animated

Peer Dependencies

npm install react react-dom styled-components

Usage

FadeIn

Animate elements when they scroll into view using Intersection Observer.

import { FadeIn } from '@lilith/ui-animated';

// Basic fade in from bottom
<FadeIn>
  <h1>Welcome to our site</h1>
</FadeIn>

// Fade in from different directions
<FadeIn direction="left" delay={200}>
  <p>This slides in from the right</p>
</FadeIn>

<FadeIn direction="right" delay={400}>
  <p>This slides in from the left</p>
</FadeIn>

// Control animation duration
<FadeIn duration="slow" triggerOnce={false}>
  <div>Re-animates when scrolling in and out</div>
</FadeIn>

ParallaxSection

Create sections with parallax scrolling backgrounds.

import { ParallaxSection } from '@lilith/ui-animated';

<ParallaxSection
  backgroundImage="/images/hero-bg.jpg"
  speed={0.5}
  minHeight="600px"
  overlayOpacity={0.6}
>
  <h1>Parallax Hero Section</h1>
  <p>Content appears above the parallax background</p>
</ParallaxSection>

// Without background image (content-only section)
<ParallaxSection minHeight="400px">
  <div>Regular section content</div>
</ParallaxSection>

MBAButton (Magnetic Button Animation)

Buttons with magnetic hover effects that respond to mouse proximity.

import { MBAButton, MBACollection } from '@lilith/ui-animated';

// Use with MBACollection for coordinated effects
<MBACollection>
  <MBAButton onClick={() => console.log('Home')}>
    <HomeIcon />
  </MBAButton>
  <MBAButton onClick={() => console.log('Settings')} active>
    <SettingsIcon />
  </MBAButton>
  <MBAButton size="large" onClick={() => console.log('Profile')}>
    <UserIcon />
  </MBAButton>
</MBACollection>

// Standalone with custom magnetic config
<MBAButton
  size="medium"
  magneticConfig={{
    maxDistance: 150,
    maxScale: 1.2,
    maxOffset: 15,
  }}
>
  Click Me
</MBAButton>

MBACollection

Container that tracks mouse position for child MBAButtons.

import { MBACollection, MBAButton } from '@lilith/ui-animated';

<MBACollection
  className="button-group"
  magneticConfig={{
    maxDistance: 200,
    maxScale: 1.15,
    maxOffset: 10,
  }}
>
  {icons.map((icon, index) => (
    <MBAButton key={index} onClick={icon.onClick}>
      {icon.component}
    </MBAButton>
  ))}
</MBACollection>

Keyframe Animations

Import reusable keyframes for styled-components.

import { cyberpunkGlow, cyberpunkPulse } from '@lilith/ui-animated';
import styled from 'styled-components';

const GlowingButton = styled.button`
  animation: ${cyberpunkGlow} 2s ease-in-out infinite;
`;

const PulsingElement = styled.div`
  animation: ${cyberpunkPulse} 1.5s ease-in-out infinite;
`;

Custom Hooks

useScrollTrigger

Detect when an element enters the viewport.

import { useScrollTrigger } from '@lilith/ui-animated';

function MyComponent() {
  const ref = useRef<HTMLDivElement>(null);
  const isVisible = useScrollTrigger(ref, {
    triggerOnce: true,
    threshold: 0.1,
  });

  return (
    <div ref={ref} style={{ opacity: isVisible ? 1 : 0 }}>
      I fade in when scrolled into view
    </div>
  );
}

useParallax

Create parallax scrolling effects.

import { useParallax } from '@lilith/ui-animated';

function ParallaxBackground() {
  const offset = useParallax({ speed: 0.5, enabled: true });

  return (
    <div style={{ transform: `translateY(${offset}px)` }}>
      Parallax content
    </div>
  );
}

useMagneticEffect

Add magnetic cursor effects to elements.

import { useMagneticEffect } from '@lilith/ui-animated';

function MagneticElement() {
  const ref = useRef<HTMLDivElement>(null);
  const [mousePos, setMousePos] = useState(null);

  const { scale, offsetX, offsetY } = useMagneticEffect(ref, mousePos, {
    maxDistance: 150,
    maxScale: 1.2,
    maxOffset: 20,
  });

  return (
    <div
      ref={ref}
      style={{
        transform: `scale(${scale}) translate(${offsetX}px, ${offsetY}px)`,
      }}
    >
      Magnetic element
    </div>
  );
}

useSmoothScroll

Smooth scroll to elements or positions.

import { useSmoothScroll } from '@lilith/ui-animated';

function Navigation() {
  const scrollTo = useSmoothScroll();

  return (
    <nav>
      <button onClick={() => scrollTo('#about')}>About</button>
      <button onClick={() => scrollTo('#contact')}>Contact</button>
    </nav>
  );
}

API Reference

FadeIn

Prop Type Default Description
direction 'up' | 'down' | 'left' | 'right' | 'none' 'up' Animation direction
delay number 0 Delay in milliseconds
duration 'fast' | 'normal' | 'slow' 'normal' Animation duration
triggerOnce boolean true Only animate once
className string - Custom CSS class
children ReactNode required Content to animate

ParallaxSection

Prop Type Default Description
backgroundImage string - Background image URL
speed number 0.5 Parallax speed (-1 to 1)
minHeight string '500px' Minimum section height
overlayOpacity number 0.5 Overlay darkness (0-1)
className string - Custom CSS class
children ReactNode required Section content

MBAButton

Prop Type Default Description
size 'small' | 'medium' | 'large' 'medium' Button size
active boolean false Active/selected state
mousePosition { x: number; y: number } | null - Mouse position (from MBACollection)
magneticConfig MagneticEffectConfig - Magnetic effect settings
children ReactNode required Button content

MagneticEffectConfig

interface MagneticEffectConfig {
  maxDistance?: number;  // Max distance for effect (default: 150)
  maxScale?: number;     // Max scale factor (default: 1.15)
  maxOffset?: number;    // Max offset in pixels (default: 10)
}

interface MagneticEffectState {
  scale: number;
  offsetX: number;
  offsetY: number;
}

Theme Integration

Animation durations integrate with your theme's transition tokens:

// Your theme
const theme = {
  transitions: {
    fast: '150ms ease',
    normal: '300ms ease',
    slow: '500ms ease',
  },
};

The FadeIn component uses these theme values for consistent animation timing.

Dependencies

  • @lilith/ui-utils - Utility functions
  • @lilith/ui-theme - Theme tokens

License

MIT