npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

typingfx

v1.2.0

Published

Customizable, smooth, and snappy typing animations for React — built for natural, human-like effects with minimal config.

Readme

TypingFX

test Maintainability codecov Version Downloads npm bundle size

⚡ Customizable, smooth, and snappy typing animations for React
✨ Animate your text like a pro — fully compatible with React 18/19, Next.js 14/15, and React Server Components.


✨ Features

  • 🎯 Built for modern React (18/19) and Next.js (14/15)
  • ✨ Smooth, realistic word-by-word animation
  • 🔁 Step-based sequences with infinite looping
  • 💅 JSX-ready — animate styled, rich text effortlessly
  • 🧠 Honors prefers-reduced-motion accessibility setting
  • 🚀 Hybrid CSS + JS for best performance
  • ⚡ Smarter performance: animation pauses 💤 when the tab loses focus — saving CPU and improving battery life without breaking the flow.
  • 🎨 Fully customizable cursor with auto-blink
  • 🔁 Infinite/controlled looping
  • 💡 Fully typed with TypeScript
  • 🧩 SSR-safe and RSC-compatible

🚀 Install

pnpm add typingfx

or

npm install typingfx

or

yarn add typingfx

🔧 Usage

① Import Styles

🎨 Required for typing animation and cursor styling.

In JSX (Next.js layout files recommended):

import "typingfx/dist/index.css";

Or in global CSS:

@import "typingfx/dist/index.css";

② Basic Typing Animation

import { TypeOut } from "typingfx";

export default function Example() {
  return (
    <TypeOut
      steps={["Frontend Developer.", "React Enthusiast.", "Open Source Advocate."]}
      speed={25}
      delSpeed={40}
      repeat={Infinity}
    />
  );
}

③ Single-Step Typing

Need a one-off typing effect without using steps?

export default function Example() {
  return (
    <TypeOut>
      I love {500} <strong>typingfx</strong>
    </TypeOut>
  );
}

⏱️ Use numbers inside JSX to insert pauses (in milliseconds) during typing.
➖ Negative numbers delay deletion.
🔤 Want to render the number instead? Wrap it with String() or use template literals.


④ Animate JSX & Rich Text

<TypeOut
  steps={[
    <>
      Building with <strong>React</strong>
    </>,
    <>
      Deploying on <code>Vercel</code>
    </>,
    <>
      Coding like a <span className="emoji">💻</span>
    </>,
  ]}
  speed={30}
  repeat={3}
/>

🧪 Component Animation (Beta)

TypingFX supports animating React components using a typing and deleting effect. This feature is currently in beta, and feedback is welcome.

✨ Default Behavior – Typing Animation

By default, TypingFX assumes the component is pure and attempts to extract and animate its JSX output, treating it like static content. This provides a natural typing effect as if the component was written inline.

<TypingFX>{<MyPureComponent />}</TypingFX>

This enables smooth, character-by-character typing that matches the surrounding text.

🧩 componentAnimation Prop

For components with side effects or dynamic behavior, you can control their animation using the componentAnimation prop:

<TypingFX
  componentAnimation={{
    wrapper: "div",
    props: { className: "custom-wrapper" },
  }}>
  <MyComponent />
</TypingFX>

TypingFX will wrap the component with the specified element and apply:

  • Fade-in (typing): 5s
  • Fade-out (deleting): 3s

This disables JSX extraction and uses a wrapper-based animation strategy.

⚠️ Server-Side Rendering (SSR) Limitation

TypingFX cannot detect components in SSR environments. Thus, by default, SSR-rendered components are treated as normal content and animated using the default typing animation.

However, you can manually mark any DOM element to be treated as a component by adding a data-tfx attribute with any truthy value:

<span data-tfx="true">Server-rendered content</span>

Combined with the componentAnimation prop, this enables custom animation support even for SSR-rendered output.

🎨 CSS Overrides

You can override the fade animation by targeting the default class names:

.tfx_component.tfx_type {
  animation: myCustomFadeIn 2s ease-in;
}

.tfx_component.tfx_del {
  animation: myCustomFadeOut 2s ease-out;
}

💬 API Feedback Welcome

We're exploring the best API design for component animation. If you have ideas or requirements, please open an issue or comment on this discussion.


💡 Tips & Tricks

⏱️ Delays & Pauses with Numbers

You can embed numbers (e.g. {1000}) directly inside JSX (steps or children) to add typing or deleting delays:

<TypeOut
  steps={[
    <>
      Hello{800}
      {-500}
    </>,
    "World!",
  ]}
/>
  • {800} → pauses for 800ms while typing
  • {-500} → pauses for 500ms while deleting

⚠️ Important: Numbers must be embedded directly as JSX expressions — not as strings.

If you want to display a number instead of pausing, convert it to a string:

<>I waited {String(800)} milliseconds.</>

⚠️ Memoization Matters

~~To prevent unintended animation restarts on re-renders, memoize your steps or children using useMemo:~~

~~const steps = useMemo(() => ["One", "Two", "Three"], []);~~

TypeOut is memoized by default to prevent unwanted animation restarts and infinite loops.

<TypeOut steps={steps} />

🔁 It ignores all prop changes after first render, including paused, speed, etc.

  • 🧊 Props are frozen on mount
  • 🧠 Re-renders won't restart animation
  • ✅ To re-run animation with new steps, change the key to remount
<TypeOut key={id} steps={steps} />

🧩 Dynamic Prop Updates (Without Re-renders or Infinite Loops)

Want to update props on the fly (e.g., pause/resume, adjust speed) without triggering full React re-renders or loop traps?

Use the useUpdate() hook with double parentheses:

import { useUpdate } from "typeout";

export function Demo() {
  const [paused, setPaused] = useUpdate("demo")(state => [state.paused, state.setPaused]);
  // if you want to update props globally do not pass any id -> useUpdate()(state => [...])
  return (
    <div className={styles.demo}>
      <button onClick={() => setPaused(!paused)}>{paused ? "Resume" : "Pause"}</button>
      <TypeOut steps={steps} storeId="demo" />
    </div>
  );
}

🎯 useUpdate() returns an isolated reactive store per id. These updates:

  • Take effect immediately
  • Don’t rely on props or re-renders
  • Work perfectly with interactive controls

🔥 Important Caveats

  • ⚠️ steps cannot be updated dynamically — changing them requires a remount via a new key.
  • 💥 remounting via key will kill the current animation and start new one.
  • ✅ All other animation props are supported via useUpdate().

✅ Supported Setters

| Setter | Description | | ------------------------- | -------------------------------------- | | setSpeed(speed) | Typing speed (chars/sec) | | setDelSpeed(delSpeed) | Deletion speed (chars/sec) | | setNoCursor(boolean) | Toggle cursor visibility | | setNoCursorAfterAnimEnd | Hide cursor after animation ends | | setRepeat(count) | How many times to repeat the animation | | setForce(boolean) | Override user’s reduced motion setting | | setPaused(boolean) | Pause or resume | | setComponentAnimation() | Update animation for custom components |

ℹ️ These updates are instance-local, fast, and non-intrusive. Use the storeId prop to group/manage the animation props across TypeOut instances.


🧱 Multi-Line Typing Support

Each step can contain multiple elements like <p>, <div>, or fragments – typingfx will animate them line by line:

<TypeOut
  steps={[
    <>
      <p>Hi there</p>
      <p>Welcome to TypingFX!</p>
    </>,
    <>
      <p>Hi there</p>
      <p>TypingFX is awesome!</p>
    </>,
  ]}
/>

✅ No need to split them into separate steps – group them as one step to animate fluidly across lines.


🚫 Avoid Layout Shifts on Delays

When inserting delays between block elements, prefer placing the delay inside one block, rather than between them:

// ❌ Avoid: causes extra spacing
<>
  <p>Hi</p>
  {5000}
  <p>Hello</p>
</>

// ✅ Recommended
<>
  <p>Hi{5000}</p>
  <p>Hello</p>
</>
// or
<>
  <p>Hi</p>
  <p>{5000}Hello</p>
</>

✨ Control the Cursor

Want to hide the blinking cursor?

<TypeOut noCursor>Hello, no cursor here!</TypeOut>

🌐 Seamless RSC & Next.js Support

No extra setup needed – TypeOut is already marked as a client component.

✅ Works out of the box with Next.js 14/15 and React Server Components (RSC).


⚙️ Props

| Prop | Type | Default | Description | | ---------- | -------------- | ---------- | ---------------------------------------------------------- | | steps | ReactNode[] | [""] | The sequence of text or elements to animate. | | speed | number | 20 | Typing speed (characters per second). | | delSpeed | number | 40 | Deletion speed (characters per second). | | repeat | number | Infinity | Number of times to loop over steps. | | noCursor | boolean | false | Disables the blinking cursor. | | paused | boolean | false | Manually pause or resume animation. | | force | boolean | false | Forces animation even when prefers-reduced-motion is on. | | children | ReactNode | "" | An optional initial step to animate. | | ... | HTMLDivProps | — | Additional props are passed to the container element. |


📦 Framework Compatibility

  • ✅ React 16.8 — React 19
  • ✅ Next.js 12 — Next.js 15
  • ✅ SSR-safe (no window access during render)
  • ✅ RSC-compatible (used as a client component)

❓ FAQ & Gotchas

This usually happens when steps or children are not memoized, causing a new reference on every render.

Fix: Use useMemo to ensure stable references:

const steps = useMemo(() => ["Hello", "World"], []);
<TypeOut steps={steps} />;

Inserting a delay like {500} between block elements (e.g. <p>) creates empty text nodes, leading to layout shifts.

❌ Bad:

<>
  <p>Hi</p>
  {500}
  <p>Hello</p>
</>

✅ Good:

<>
  <p>Hi{500}</p>
  <p>Hello</p>
</>

📌 Tip: Always place delays inside a block to avoid glitches.


Absolutely. TypeOut is already marked as a client component, so it works out of the box with:

  • ✅ React Server Components (RSC)
  • ✅ App Router
  • ✅ Server-side Rendering (SSR)

Use negative numbers like {-500} anywhere in the content.

  • {800} → pause for 800ms while typing
  • {-500} → pause for 500ms while deleting
<TypeOut steps={["Start typing...", -1000, "Deleting now..."]} />

or

<TypeOut>Wait before deleting me{-500}</TypeOut>

TypingFX supports JSX out of the box! You can mix <strong>, <code>, emojis, or even full components.

<TypeOut
  steps={[
    <>
      Writing with <strong>style</strong>
    </>,
    <>
      Deployed via <code>Vercel</code>
    </>,
    <>💻 Happy Coding!</>,
  ]}
/>

✨ Fully supports React elements, fragments, and inline styles.


Updates

Removed next from peerDependencies 🧼

next was previously listed in optionalPeerDependencies only to indicate compatibility. It has been removed:

  • ✅ TypingFX still works perfectly in Next.js (including App Router, SSR, RSC)
  • 🧼 Avoids triggering npm warnings in non-Next projects
  • 📚 Compatibility now noted in docs + keywords only

📁 License

MPL-2.0 open-source license © Mayank Chaudhari

Please enroll in our courses or sponsor our work.