Installation
pnpm dlx shadcn@latest add https://asciicn.dev/r/sydney.jsonUsage
import { Sydney } from "@/components/asciicn/sydney";
export function Hero() {
return (
<section className="relative isolate flex min-h-[480px] flex-col items-center justify-center text-white">
<Sydney intensity={0.75} className="absolute inset-0 -z-10" />
<h1>Your headline</h1>
</section>
);
}The harbour is seen from the east at blue hour, just after sunset. The Opera House stands on the left on its podium: two halls of overlapping curved shells, the taller hall behind and the lower one in front, with heights and leans that differ from shell to shell and the tallest tip at the north end. Each shell is shaded as a volume: the face toward the afterglow is lit warm cream with a soft ridge, its back turns away into cool lavender, the underside shows in shadow under the overhang, and every shell in front throws a soft shadow on the one behind it. Glass walls under the tallest tips glow amber, and the restaurant's two small shells sit at the south end above the stairs.
The Harbour Bridge spans the right of the frame: a granite pylon at each end, lit on the face toward the glow, and the arch between its two chords, with a hazy truss, hangers down to the deck and lamps along the arch and the deck. The city's towers stand behind in cool haze, with a needle tower among them and North Sydney past the bridge.
The whole frame is painted. The sky runs from deep blue at the top through lavender to a peach afterglow low between the house and the bridge. The harbour mirrors the sails, the arch and the glow through slow ripples, and the afterglow lays a path of glints on the water. Far things draw smaller, hazier dots than near ones, and only the lit sails, the glow and its reflection draw the largest.
Nothing built moves, and the pointer has no effect. The motion is slow: ripples break and shift the reflections, a few windows switch on or off, fading over a couple of seconds, red lights on the crown of the arch and the needle tower blink softly, stars twinkle, and one green and cream ferry crosses the harbour every few minutes.
The middle of a wide box stays quiet for a headline: the house sits on the left and the bridge on the right. On a tall box both close in and sit low, the tallest shell just right of centre and the arch rising behind it, so a phone shows them under the copy.
It draws in dots by default, on square 7px cells so the dots lay an even halftone lattice, with blue-noise dithering so the dot sizes blend into smooth gradients without a regular pattern. In truecolor mode, also the default, every dot takes its own colour and the scene paints its own blue hour behind them, so it looks the same on light and dark pages. braille and standard draw the same scene in other glyphs; Braille and quadrants keep their usual tall cells. In mono mode every glyph takes the ink or a phosphor, and in duotone mode the scene runs through a ramp, ember by default.
ferry={false} takes the ferry off the water. intensity thins every dot at once. Around 0.75 keeps the sails clear behind a headline; lower it under body text.
Examples
Behind a headline
The harbour full-bleed behind a centred headline and two buttons, at intensity={0.75}. The scene stays dark in both themes, so the copy on top is white.
Duotone
colorMode="duotone" with ramp="heliograph" runs every tone through one blue ramp, so the scene reads by dot size alone, and ferry={false} leaves the water still.
Props
| Prop | Type | Default |
|---|---|---|
| intensity How much of the scene shows, from 0 (empty paper) to 1. Lower it under text. | Type: number | Default 1 |
| ferry The ferry crossing the harbour, with its wake and reflection. | Type: boolean | Default true |
| paper The surface behind the glyphs. truecolor, ansi16 and duotone paint the scene's own blue hour; mono and palette keep the theme's paper. Ignored when a phosphor brings its own glass. | Type: AsciiColor | Default the scene's blue hour, or the theme's paper |
| charset Which glyphs draw the tones. See Charsets. | Type: CharsetName | Default "dots" |
| chars A custom ramp from empty to dense, such as " .oO@". Wins over charset. | Type: string | Default – |
| colorMode How glyphs are coloured. truecolor keeps the scene's own colours; mono uses the ink or phosphor; duotone runs the tone through a ramp. | Type: "mono" | "truecolor" | "ansi16" | "duotone" | "palette" | Default "truecolor", or "mono" with a phosphor |
| phosphor A CRT ink and glass that replace the ink and paper. | Type: "p1" | "p3" | "ibm" | "blueprint" | Default – |
| ramp In duotone mode, the colour ramp from dark to light. | Type: RampName | string[] | Default "ember" in duotone |
| ansi In ansi16 mode, which 16-colour table. | Type: "vga" | "xterm" | Default "vga" |
| grade Brightness, contrast, gamma and saturation applied to tones before glyphs are picked. | Type: Grade | Default – |
| invert Dense glyphs for dark tones instead of bright ones. | Type: boolean | Default false |
| threshold Braille and quadrants: the tone that lights a dot. | Type: number | Default 0.5 |
| edgeThreshold Edge charset: how strong a change in tone must be to draw - / | or \. | Type: number | Default 0.22 |
| dither Dithering between neighbouring glyph levels. On dots it keeps the sky a smooth gradient without stripes. | Type: "none" | "bayer2" | "bayer4" | "bayer8" | "blue-noise" | Default "blue-noise", or "none" in braille and quadrants |
| background "transparent" draws the glyphs only, over your own surface. | Type: "paper" | "transparent" | Default "paper" |
| fx CRT finish: scanlines, bloom, curvature, glitch, flicker and vignette, each 0 to 1. | Type: PostFx | Default – |
| cell Height of one glyph cell in CSS pixels. With square cells it sets the width too. | Type: number | Default 7 |
| square Cells as wide as they are tall, so the dots lay an even halftone lattice instead of rows. | Type: boolean | Default true, or false in braille and quadrants |
| speed How fast everything moves. | Type: number | Default 1 |
| animate false stops the motion: a still frame if it starts off, the current frame if it was moving. | Type: boolean | Default true |
| fps Frame rate cap. | Type: number | Default 24 |
| stillTime The moment drawn when motion is off or reduced, in seconds. | Type: number | Default 30 |
| fallback Shown without WebGL and until the first frame. | Type: ReactNode | Default a blue-hour gradient |
| handle Filled with a handle that reads back the current frame, for export to text, ANSI, SVG or PNG. | Type: RefObject<AsciiHandle | null> | Default – |
| className Size and position. The background fills this box. | Type: string | Default – |
Notes
- It is decorative and hidden from assistive technology. Put real text on top of it, not inside it.
- It ignores the pointer: no parallax and no hover effect.
- With reduced motion turned on, it draws one still frame at
stillTimeand stops. The default, 30 seconds, puts the ferry on the water below the glow. - It pauses when scrolled out of view or when the tab is hidden, and releases its WebGL context when far offscreen. Without WebGL it shows a blue-hour gradient.
- The whole harbour is one shader pass on the GPU. Water samples also draw the mirrored scene, so the harbour costs about twice as much as the sky. See Performance.