Installation
pnpm dlx shadcn@latest add https://asciicn.dev/r/san-francisco.jsonUsage
import { SanFrancisco } from "@/components/asciicn/san-francisco";
export function Hero() {
return (
<section className="relative isolate flex min-h-[480px] flex-col items-center justify-center text-white">
<SanFrancisco intensity={0.7} className="absolute inset-0 -z-10" />
<h1>Your headline</h1>
</section>
);
}The view is at an angle across the water at blue hour, just after sunset. The north tower stands near on the left, taller and wider, and the south tower far on the right, smaller and hazier, with the deck and the main cable receding between them. Each tower has two legs, four portal struts above the deck, stepped tops and X bracing below the deck, standing on concrete piers. The faces that turn toward the afterglow are lit warm orange and the far side of each leg falls into deep rust. Fine hangers drop from the cable to the deck and fade as they crowd together toward the far tower. The Marin Headlands rise behind the near tower, and the low hills of the Presidio and the city's lights sit past the far one.
The whole frame is painted. The sky runs from deep blue at the top through mauve to a warm afterglow low behind the bridge, with thin streaks of high cloud. A bank of fog lies under the deck, rises toward the far tower until it hides parts of the far deck and the tower's base, and piles up against the headlands, lit warm on top and blue grey underneath. The bay below mirrors all of it, and the afterglow lays a path of glints on the water. Dark areas stay quiet: the deep sky, the fog's shadow and the far water draw the smallest dots in colours a shade above the paper, and the large bright dots are kept for the bridge, the glow and its reflection.
Nothing built moves, and the pointer has no effect. The motion is slow: the fog drifts east under the deck, ripples break the reflections into streaks, the red aircraft lights on the tower tops blink softly out of step with each other, a few stars twinkle, and one boat crosses the bay every few minutes.
Wide boxes keep the angled view and spread it with the box. In a portrait box, narrower than about 0.85 wide to 1 tall, the view turns square on: the towers stand at the left and right edges with their tops near half height, the deck runs low at about three quarters of the way down, and the afterglow is held back, so a centred headline and its buttons sit between the towers and above the span instead of over the bridge. Tower legs, struts, the cable, the hangers and the deck are laid out on whole cells, so they come out as clean lines of dots at any size.
It draws in dots by default, on square 7px cells so the dots lay an even halftone lattice, with bayer4 dithering so the dot sizes blend into smooth gradients. In truecolor mode, also the default, every dot takes its own colour and the scene paints its own dusk 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.
fog sets how thick the bank is, from none at 0. traffic sets how many cars cross the deck as single dots of light, up to six. boat={false} takes the boat off the water. intensity thins every dot at once. Around 0.7 keeps the bridge clear behind a headline; lower it under body text.
Examples
Behind a headline
The bridge full-bleed behind a centred headline and two buttons, at intensity={0.7}. The scene stays dark in both themes, so the copy on top is white.
Amber terminal
phosphor="p3" draws the scene in amber on dark glass. braille dots, fog={0.9} and a CRT finish from fx make it look like a night camera on an old monitor.
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 |
| fog How thick the fog bank under the deck and over the headlands is, from 0 (none) to 1. | Type: number | Default 0.6 |
| traffic How many cars cross the bridge, from 0 (none) to 1 (six). | Type: number | Default 0.2 |
| boat The boat crossing the bay. | Type: boolean | Default true |
| paper The surface behind the glyphs. truecolor, ansi16 and duotone paint the scene's own dusk; mono and palette keep the theme's paper. Ignored when a phosphor brings its own glass. | Type: AsciiColor | Default the scene's dusk, 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 Ordered dithering between neighbouring glyph levels. On dots it keeps the sky a smooth gradient. | Type: "none" | "bayer2" | "bayer4" | "bayer8" | "blue-noise" | Default "bayer4", 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 20 |
| 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.
- With reduced motion turned on, it draws one still frame at
stillTimeand stops. - It pauses when scrolled out of view or when the tab is hidden. Without WebGL it shows a CSS gradient in the scene's colours.
- The whole scene is drawn on the GPU in one pass, and the water reads the scene above it a second time for the reflection. See Performance.