a1ui
6 new components shipped

ASCII Morph

A cloud of characters that morphs into a globe, a flower, and an A1 monogram.

Read agent guide

Demo

Click, press Enter or Space for the next shape. Arrow keys cycle in either direction.Globe

Installation

pnpm dlx shadcn@latest add https://ui.arjayby1.xyz/r/ascii-morph.json

Code

import { AsciiMorph } from "@/components/ui/ascii-morph";

export function AsciiMorphExample() {
  return <AsciiMorph className="max-w-xl" />;
}

API reference

PropTypeDefaultPurpose
shape"globe" | "flower" | "a1"UncontrolledControlled destination. Update it in onShapeChange to accept user input.
defaultShapeAsciiMorphShape"globe"Initial shape when uncontrolled. Read once on mount.
onShapeChange(shape: AsciiMorphShape) => voidNoneCalled when a click or key requests another shape.
durationnumber1600Approximate settling time in milliseconds. Clamped to 400–4000. Spring velocity and travel distance affect the exact time.
interactivebooleantrueEnables the button and animated transitions. Set to false for a static illustration that follows shape.
ariaLabelstring"Change ASCII shape"Accessible name of the button.
classNamestringNoneOuter layout classes. The illustration fills its container with a 6:5 aspect ratio by default.
styleCSSPropertiesNoneOuter inline styles, including a custom height or color.

AsciiMorphShape and AsciiMorphProps are exported types. The sequence is Globe, Flower, A1, then Globe again. A1 is a fixed monogram; this component does not accept custom images or text.

Controlled shape

Use a Client Component when supplying a callback.

"use client";

import { useState } from "react";
import { AsciiMorph, type AsciiMorphShape } from "@/components/ui/ascii-morph";

export function ControlledAsciiMorphExample() {
  const [shape, setShape] = useState<AsciiMorphShape>("flower");
  return <AsciiMorph shape={shape} onShapeChange={setShape} duration={2000} />;
}

Interaction and motion

Click or tap anywhere on the illustration to advance. Enter and Space activate the focused button. Right and Down go forward; Left and Up go back. The current shape is announced through a live status, and individual glyphs stay hidden from assistive technology.

Each glyph keeps its identity, position, and velocity when you interrupt a transition. The animation updates SVG coordinates without rendering React on every frame. It stops once the shape settles and suspends while the component is offscreen or the document is hidden. Unmounting cancels the frame and removes observers and event listeners.

Reduced motion skips travel and shows the requested silhouette immediately, including when the preference changes during a morph. There is no automatic cycling. The initial silhouette renders on the server, and a fixed SVG viewBox scales every position together when the container resizes. The glyphs inherit the component's color and stay visible across theme changes.