A startup office monitor showing a gradient AI hero with a node-graph background, a gray-blue cat watching from the windowsill.

performative-ui: Components That Signal How Oversubscribed Your Round Is

The Gray Cat
The Gray Cat
0 views

There is a certain kind of landing page you have seen a hundred times. The headline shimmers through a gradient. A constellation of connected dots drifts behind it, implying neural networks. A pill above the title whispers "Now with agents." There is a giant input box that just says "ask anything," a marquee of customer logos, a count-up stat that claims ten million tokens served, and a little spinner that cheerfully informs you it is currently Reticulating. performative-ui is the React library that lets you assemble all of it from a parts bin, and its own tagline says the quiet part out loud: these are "AI-native React components that signal how oversubscribed your funding round is."

Here is the twist that makes it worth an article instead of a tweet: the joke is real software. The package is published to npm at version 0.6.0, it is MIT licensed, it is written in strict TypeScript, it ships its own CSS, it weighs about 30 KB, and it works with React 18 or 19. Every component forwards refs and spreads native props. You can npm install it today and ship a hero section before lunch. The parody is the marketing; the engineering is sincere. This is a guide to using it on purpose.

A Parts Bin for the Entire Pitch

The catalog is organized into the exact buckets you would draw on a whiteboard if someone asked you to clone every Series A homepage at once. There are atoms like Sparkle, GradientText, StatusDot, and QuestText. There are primitives like a polymorphic Button, a StickyBanner for the "we just raised" announcement, and an EyebrowPill. There are heroes: Rotator and WordRoll for swapping words in a headline, PromptHero and Prompt for the obligatory giant input, AsciiHero for animated ASCII art, and Goldeneye for a cursor-following magnifier reveal.

Then come the backgrounds (Aurora, NodeGraphBackground, FloatingSparkles), the surfaces (GlassCard, MockIDE), the conversation pieces (ChatBubble, TokenStream, WibblingSpinner, ChatFAB), the social proof (LogoMarquee, LogoRow, SlippyWords, StatCounter, CommunityBadge), and the pricing and waitlist closers (PricingCard, BeforeAfter, WaitlistForm, Popover). For people who want the motion without the markup, four headless hooks — useTypewriter, useCounter, useTokenStream, and useAsciiField — expose the animation logic on its own, and a cn class-merging helper rounds it out.

Crucially, none of this requires Tailwind or a config step on your end. The components are styled with plain, pui--prefixed CSS that ships inside the package, and they read color from CSS custom properties so you can re-theme by overriding variables.

Getting It Into Your Project

Installation is a single command, and the styles come along for the ride.

npm install performative-ui
yarn add performative-ui

The package is ESM-only and lists React and React DOM as peer dependencies (^18.0.0 || ^19.0.0), so make sure those are already in your app. Importing anything through the barrel pulls in the stylesheet automatically, because the entry module imports its own CSS as a side effect.

import { GradientText, NodeGraphBackground } from "performative-ui";

That is genuinely all the setup there is. If your bundler aggressively tree-shakes the CSS side effect away, there is an explicit subpath you can import once at the root of your app:

import "performative-ui/styles.css";

Building the Hero Nobody Asked For

Let's assemble the top of a landing page. The pattern is to drop a background layer behind everything, then stack the headline and the input on top of it. NodeGraphBackground is the canonical "we do AI" canvas — connected particles that drift and brighten near your cursor — and it spreads native div props, so you can position it absolutely.

import {
  NodeGraphBackground,
  EyebrowPill,
  GradientText,
  PromptHero,
} from "performative-ui";

function Hero() {
  return (
    <section style={{ position: "relative", overflow: "hidden", padding: "6rem 1rem" }}>
      <NodeGraphBackground
        density={90}
        linkDistance={160}
        hoverGravity={0.01}
        style={{ position: "absolute", inset: 0 }}
      />
      <div style={{ position: "relative", textAlign: "center" }}>
        <EyebrowPill>✦ Now with agents</EyebrowPill>
        <h1>
          The platform for <GradientText>frontier teams</GradientText>
        </h1>
        <PromptHero
          placeholder="Describe what you want to build…"
          ctaLabel="Generate"
          onSubmit={(value) => console.log("ship it:", value)}
        />
      </div>
    </section>
  );
}

NodeGraphBackground is heavily tunable: density sets the node count, speed controls drift, linkDistance decides when two nodes draw an edge, and a cluster of hover* props (hoverDistance, hoverGravity, hoverBrighten) governs how the field reacts to the cursor. GradientText does the shimmering fill and accepts an as prop if you want it to render as something other than a span, plus a static flag to freeze the animation. PromptHero is an uncontrolled form by default; give it a value and onChange if you want to drive it yourself, and its onSubmit hands you the current text.

The Star of the Show: A Spinner That Wibbles

If performative-ui has a mascot, it is WibblingSpinner. It is a loving recreation of the Claude Code loading indicator, and it ships the entire canonical 186-word verb pool inline — so out of the box it will tell your users it is Bamboozling, Cogitating, Flibbertigibbeting, or, yes, Wibbling. The glyph cycles through the same macOS sparkle frames the real thing uses.

import { WibblingSpinner } from "performative-ui";

function Thinking() {
  return (
    <WibblingSpinner
      verbInterval={3000}
      info="10s · ↓ 193 tokens"
    />
  );
}

By default the spinner picks one verb at mount and holds it; pass verbInterval to make it re-roll on a timer (3000ms gives you the real Claude Code rhythm). You can pin a single verb with verbs={["Hardcoding"]}, swap the glyph set, change glyphInterval, or recolor the glyph with glyphColor. The info slot is the clever bit: it renders a parenthetical after the verb, and because React isolates state inside child components, you can drop a live token counter in there and it will tick without ever resetting the spinner. The exported WIBBLING_SPINNER_VERBS and WIBBLING_SPINNER_GLYPHS constants let you reuse the lists elsewhere.

Pair it with TokenStream to complete the illusion that something profound is being computed:

import { TokenStream } from "performative-ui";

<TokenStream
  text="Synthesizing a multi-agent reasoning trace across your codebase…"
  speedMs={[20, 60]}
/>;

TokenStream renders text as if it were streaming token-by-token, with a blinking caret you can hide via hideCaret. The speedMs prop takes a single number for a fixed cadence or a [min, max] tuple for human-feeling jitter, and you can swap the tokenizer, loop it, or wire an onComplete callback.

Compound Components for Cards and Pricing

Two of the most genuinely useful pieces here are compound components, which means you compose them from named subparts in any order. GlassCard gives you the glassmorphism feature card with a breathing glow and a hover halo.

import { GlassCard } from "performative-ui";

<GlassCard breathing glowOnHover>
  <GlassCard.Icon></GlassCard.Icon>
  <GlassCard.Title>Reason</GlassCard.Title>
  <GlassCard.Body>Multi-step, multi-modal, multi-vendor.</GlassCard.Body>
  <GlassCard.Link href="/learn">Learn more</GlassCard.Link>
</GlassCard>;

PricingCard follows the same shape, with a featured flag for the Pro tier glow and lift, and subparts for the flag, tier, amount, blurb, feature list, and call to action.

import { PricingCard } from "performative-ui";

<PricingCard featured>
  <PricingCard.Flag>Most popular</PricingCard.Flag>
  <PricingCard.Tier>Pro</PricingCard.Tier>
  <PricingCard.Amount unit="/mo">$49</PricingCard.Amount>
  <PricingCard.Blurb>For serious builders.</PricingCard.Blurb>
  <PricingCard.Features>
    <li>Unlimited projects</li>
    <li>Priority inference</li>
  </PricingCard.Features>
  <PricingCard.CTA href="/upgrade">Upgrade</PricingCard.CTA>
</PricingCard>;

The unit prop on Amount renders that "/mo" suffix smaller and dimmer, exactly the way every pricing table you have ever seen does it. Because both roots extend their native element props (an article), your own className and styles merge in cleanly through the library's internal cn helper.

The Cursor Trick and the Lava Lamp

For the two flashiest items, Goldeneye is the cursor-following reveal. A circular "scope" tracks your mouse over a tiled-letter background and swaps the headline underneath it — outside the scope you see one word, inside it you see another.

import { Goldeneye } from "performative-ui";

<Goldeneye
  text_default="HYPE"
  text_reveal="SHIP"
  scopeSize={360}
  pattern="0 1 0 1 "
/>;

Both text_default and text_reveal are required; the rest tunes the lattice pattern size, the scope diameter, and the headline font. The fontSize prop is pleasantly flexible: a bare number is treated as pixels, while a string is passed straight through, so you can hand it a clamp() for responsive type.

For backgrounds with more personality than a gradient, Aurora has a lava-lamp mode. In its default form it is soft drifting color blobs; flip on animated and each blob becomes an independent bubble that wanders, pushes its neighbors away, and springs back home.

import { Aurora } from "performative-ui";

<Aurora
  animated
  repulsion={0.25}
  blur={80}
  blobs={[
    { color: "#7c3aed", x: 20, y: 30, size: 480 },
    { color: "#ec4899", x: 70, y: 60, size: 520 },
  ]}
/>;

Each blob is just a color and a position with an optional size, the repulsion value controls how aggressively they shove each other apart, and a static flag turns the motion off entirely for the reduced-motion crowd. If you want the streaming logic without any of the chrome, reach for the hooks — useTokenStream, useTypewriter, useCounter, and useAsciiField return plain state you can render however you like.

Should You Actually Use It?

Let's be honest about what this is. performative-ui is a brand-new, fast-rising side project from a single author. There is no formal releases page or changelog, it is ESM-only, and it is decidedly a gag — you should not anchor a serious company's design system to it. The conversation components are decorative, too: Prompt, ChatBubble, and TokenStream mimic the look of real AI chat kits like assistant-ui or the Vercel AI SDK, but they do not wire up a model. You bring your own onSubmit.

That said, the things it does, it does for real. The components are typed, ref-forwarded, prop-spreading, and styled with overridable CSS variables. Several of them — Aurora, LogoMarquee, BeforeAfter, FloatingSparkles — overlap with what serious marketing-component libraries like Magic UI or Aceternity ship, just with a wink. If you are prototyping an AI demo, building an internal joke page, or you simply need a node-graph background and a count-up stat without pulling in a heavier kit, it is a delightful and low-risk dependency. And WibblingSpinner alone, with its 186 verbs of cheerful nonsense, is worth the install. Sometimes the most honest thing a UI library can do is admit exactly what it is for.