Pluto UIpluto/ui
Components

Split Flap Display

A split-flap display component with smooth flip animations using motion, like airport displays. Works with any text or content.

// Code for split-flap-display/basic

Installation

Loading installation instructions...

Usage

import { SplitFlapDisplay } from "@/components/pluto-ui/split-flap-display"
import { SplitFlapDisplay } from "@/components/pluto-ui/split-flap-display"

<SplitFlapDisplay text="HELLO WORLD" />

Props

PropTypeDefaultDescription
textstring-Text to display
classNamestring-Additional CSS classes
characterSetstringSee belowAvailable characters for display
flipDurationnumber1Duration of flip animation in seconds
size"sm" | "md" | "lg""md"Size of the display

Default Character Set

The default character set includes: 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ :!?.,-

Characters not in the character set will be displayed as spaces.

Examples

Basic Usage

// Code for split-flap-display/basic

Countdown Timer

// Code for split-flap-display/countdown

Features

  • Smooth Flip Animations: Powered by motion for realistic split-flap display effects
  • Airport-style Design: Authentic split-flap display appearance with 4-panel animation system
  • Any Text Support: Works with any text, not just numbers or timers
  • Individual Character Animation: Each character flips independently when it changes
  • 3D Flip Effect: Uses 3D transforms with perspective for authentic split-flap appearance
  • Customizable Character Set: Define which characters are available
  • Multiple Sizes: Small, medium, and large display sizes
  • Theme-aware: Fully supports light and dark themes using CSS variables
  • No CSS File Required: All styling handled with Tailwind and motion

How It Works

The component displays text character by character, with each character in its own flap. When a character changes, a sophisticated 4-panel animation system creates the split-flap effect:

  1. Text Input: Accepts any string as input
  2. Character Tracking: Tracks previous text to detect character changes
  3. 4-Panel Animation: When a character changes, four panels work together:
    • Unfold Top: New character's top half fades in (brightness 0 → 1)
    • Unfold Bottom: New character's bottom half rotates from behind (180° → 0°)
    • Fold Top: Old character's top half rotates up (0° → -180°)
    • Fold Bottom: Old character's bottom half fades out (brightness 1 → 0)
  4. 3D Transform: Uses CSS 3D transforms with perspective for realistic depth
  5. Smooth Transitions: Motion handles all animations with proper timing and easing

Animation Details

  • Flip Duration: Configurable (default 1s) for each flip animation
  • 4-Panel System: Uses four separate panels (unfold top/bottom, fold top/bottom) for authentic split-flap effect
  • Brightness Transitions: Top and bottom panels use brightness filters for smooth fade in/out
  • Rotation Transitions: Top panel rotates -180°, bottom panel rotates 180° → 0°
  • 3D Perspective: 1000px perspective for depth effect
  • Transform Origin: Top panels rotate from bottom edge, bottom panels rotate from top edge
  • Clip Path: Each panel is clipped to show only its half (top or bottom)

Styling

The component uses Tailwind CSS for all styling and can be customized through:

  • Tailwind Classes: Pass custom classes via the className prop
  • CSS Variables: Uses theme variables for colors (e.g., --muted, --foreground, --border)
  • Motion Props: Customize animations by modifying the motion component props
  • Gradient Backgrounds: Uses gradient backgrounds for depth and dimension

Customization

Custom Character Set

// Only numbers and basic punctuation
<SplitFlapDisplay
  text="12345"
  characterSet="0123456789:."
/>

Different Sizes

<SplitFlapDisplay text="SMALL" size="sm" />
<SplitFlapDisplay text="MEDIUM" size="md" />
<SplitFlapDisplay text="LARGE" size="lg" />

Custom Flip Speed

<SplitFlapDisplay
  text="FAST"
  flipDuration={0.15}
/>

Dynamic Text

const [message, setMessage] = useState("HELLO")

useEffect(() => {
  const interval = setInterval(() => {
    setMessage((prev) => prev === "HELLO" ? "WORLD" : "HELLO")
  }, 2000)
  return () => clearInterval(interval)
}, [])

<SplitFlapDisplay text={message} />

Use Cases

  • Countdown Timers: Display time remaining (see countdown example)
  • Status Messages: Show status updates with visual flair
  • Scores/Stats: Display numbers that change frequently
  • Announcements: Airport-style announcements
  • Any Dynamic Text: Any text that changes over time

Notes

  • Requires motion as a dependency
  • Characters not in the character set will be displayed as spaces
  • The component automatically handles text length changes by padding with spaces
  • Each character is displayed in a separate flap for individual animation
  • The component uses monospace font for consistent character width
  • Text is automatically converted to uppercase for consistency
  • The component works best with short to medium length text (1-20 characters)
  • The 4-panel animation system ensures both old and new characters are visible during the flip