calligraph

repository·main·Indexed 17 days ago

https://github.com/raphaelsalaja/calligraph

A React library for fluid text transitions powered by Motion. It provides the <Calligraph> component to animate shared characters sliding to new positions, with fade effects for entering and exiting characters. It supports multiple animation variants including 'text' (LCS character diffing), 'number' (rolling vertical digits), and 'slots' (slot-machine style digit spins), along with specialized renderers like NumberRenderer, SlotsRenderer, and TextRenderer.

Tokens
2.9K
Snippets
9
Records
15
Agent score
64%

What's inside calligraph

  1. Run the Calligraph web demo in development mode

    main

    To start the development environment, run the command from the repository root. This uses Turborepo to simultaneously start the Calligraph library in watch mode and the Next.js development server.

    If you only want to run the web site without watching the library changes, use the --filter flag.

    # Start everything (library + web site)
    pnpm dev
    
    # Start only the web site
    pnpm dev --filter=web
  2. Use the Calligraph component for fluid text transitions

    main

    The <Calligraph> component provides fluid text transitions powered by Motion. When the children (the text content) changes, Calligraph performs the following animations:

    • Shared characters: Slide from their old positions to their new positions.
    • New characters: Fade in.
    • Removed characters: Fade out.
    import { Calligraph } from "calligraph";
    import { useState } from "react";
    
    function App() {
      const [text, setText] = useState("Hello");
    
      return (
        <>
          <Calligraph>{text}</Calligraph>
          <button onClick={() => setText("World")}>Change</button>
        </>
      );
    }
  3. Configure custom transitions in Calligraph

    main

    You can customize the animation behavior of the <Calligraph> component by passing a transition prop. This prop accepts configuration objects compatible with Motion, such as specifying type (e.g., "spring"), stiffness, and damping.

    <Calligraph transition={{ type: "spring", stiffness: 200, damping: 20 }}>
      {text}
    </Calligraph>
  4. Configure SlotsRenderer animation properties

    main

    The SlotsRenderer component relies on motion/react for its animations. You can control the feel of the digit spins and the timing of the sequence using the transition and stagger props.

    • transition: Pass a standard Transition object from motion/react. This controls the spring, duration, or easing of the digit movement.
    • stagger: This value determines the delay between individual digit animations. A higher value increases the time gap between the animation of one digit and the next, creating a more pronounced sequential effect.
  5. Use the Calligraph component for fluid text and number transitions

    main

    The Calligraph component provides fluid transitions for text, numbers, and slot-machine style digits using Motion. It handles character diffing and animations automatically when the children prop changes.

    Variants

    • text: Uses LCS (Longest Common Subsequence) character diffing to animate text changes. (Default)
    • number: Uses rolling vertical digit animations. (Default animation: snappy)
    • slots: Uses a slot-machine style digit spin animation.

    Key Props

    • variant: Determines the animation style ("text" | "number" | "slots").
    • animation: Selects a spring preset. Options are `
  6. Configure NumberRenderer props

    main

    The NumberRenderer component accepts the following props:

    PropTypeDescription
    textstringThe text or number to be rendered.
    transitionTransitionA motion/react transition object that defines the animation behavior (e.g., spring, tween).
    staggernumberThe delay multiplier applied to each character to create a staggered animation effect.
    animateInitialbooleanIf true, the initial animation (like opacity or scale) will play when the component first mounts.
    onComplete() => void (optional)A callback function that is triggered when the animation for the last character in the sequence completes.
  7. Configure Calligraph animation presets and behavior

    main

    You can customize the animation feel and movement behavior of the Calligraph component using the following props:

    Animation Presets

    Pass an animation object (from the Animation type) to override defaults. The default preset depends on the variant:

    • text variant: defaults to animations.default (smooth).
    • number variant: defaults to animations.snappy.

    Text Variant Specifics

    When using variant="text", you can control how characters enter and exit:

    • drift: An object { x?: number; y?: number } defining the maximum pixel spread for entering/exiting characters. Defaults to { x: 15, y: 0 }.
    • trend: Vertical direction for character movement. 1 enters from below, -1 enters from above, and 0 is no vertical trend. Defaults to 0.
    • stagger: The delay in seconds spread across characters. Defaults to 0.02.

    General Behavior

    • as: The HTML element or React component to use as the wrapper. Defaults to "span".
    • initial: If true, characters will animate in immediately upon the first mount. Defaults to false.
    • autoSize: If true, the wrapper element will animate its width to match the content size. Defaults to true.
    • onComplete: A callback function fired when the last character finishes its animation.
  8. Use the SlotsRenderer component

    main

    The SlotsRenderer component is used to display text with animated digit transitions (slot machine style). It handles the reconciliation of text changes, determining the direction of digit spins, and applying staggered animations to numeric characters.

    Props

    PropTypeDescription
    textstringThe text to be rendered. Changing this triggers the digit animations.
    transitionTransitionA motion/react transition object applied to all animations.
    staggernumberThe delay multiplier used to stagger the animation of digits.
    animateInitialbooleanWhether to trigger the initial animation when the component mounts.
    onComplete (optional)() => voidA callback function to execute when animations finish.

    Behavior

    • Digit Animation: Numeric characters are rendered as spinning columns. The component calculates the shortest path (direction) between the old and new digit.
    • Non-digit Characters: Characters that are not digits are treated as static text and use layout="position" for smooth movement during text changes.
    • Masking: The component applies a linear-gradient mask (FADE_MASK) to create a fade effect at the top and bottom of the slot columns.
    import { SlotsRenderer } from 'calligraph';
    
    // Example usage
    <SlotsRenderer
      text="123"
      transition={{ type: 'spring', stiffness: 100 }}
      stagger={0.05}
      animateInitial={true}
    />