# ASCII card

A card framed in box-drawing glyphs, with its title set into the top border and an optional glyph glow lighting it from an edge or a corner.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. The asciicn agent skill, for building any ASCII effect on the engine, is at [/.well-known/agent-skills/asciicn/SKILL.md](/.well-known/agent-skills/asciicn/SKILL.md).

> **This is an example, not the only option.** It is one component built on the asciicn engine. Install it when it is what you were asked for. For any other look, don't stretch its props to fit: write your own field on `AsciiShader` ([Write your own](/docs/engine/write-your-own.md)), or draw a CPU grid with `AsciiGrid`, and read this example's source for technique. Its full source is in [https://asciicn.dev/r/ascii-card.json](https://asciicn.dev/r/ascii-card.json), under `files[].content`.

## Installation [#installation]

```bash
npx shadcn@latest add https://asciicn.dev/r/ascii-card.json
```

This also installs [`ascii-box`](/docs/interface/ascii-box), which draws the frame, and `ascii-glow`, which draws the glow.

## Usage [#usage]

```tsx
import { AsciiCard } from "@/components/asciicn/ascii-card";

export function RuntimeCard() {
  return (
    <AsciiCard title="edge-runtime" footer="31 regions" glow="top-right">
      <p className="font-semibold">Cold starts under 40 ms</p>
    </AsciiCard>
  );
}
```

`AsciiCard` is an `AsciiBox` that fills its container's width, with a `title` set into the top border (`┌─ Title ─────┐`), an optional `footer` in the bottom border and a `description` line above the content. The title also names the card for screen readers.

`glow` lights the inside of the frame with an `AsciiGlow` from an edge, a corner or any point, drawn in the glyphs of `glowCharset`. The glow sits behind the content and fills the cells inside the frame exactly.

Set `interactive` on a card that holds a link or button. Hover or focus inside it turns the frame heavy and brightens the glow.

## Examples [#examples]

### Glows [#glows]

Three interactive cards lit from different sides in braille, block and katakana glyphs. Hover one, or tab to its link.

```tsx title="examples/ascii-card-glows.tsx"
import { AsciiCard } from "@/components/asciicn/ascii-card";

const CARDS = [
  { charset: "braille", color: "blue", glow: "top-left", title: "ingest" },
  { charset: "blocks", color: "purple", glow: "top", title: "transform" },
  { charset: "katakana", color: "green", glow: "top-right", title: "serve" },
] as const;

export default function AsciiCardGlows() {
  return (
    <div className="grid w-full max-w-4xl gap-4 sm:grid-cols-3">
      {CARDS.map((card) => (
        <AsciiCard
          key={card.title}
          title={card.title}
          glow={card.glow}
          glowCharset={card.charset}
          color={card.color}
          interactive
        >
          <a
            href="#top"
            className="font-display text-base font-semibold outline-offset-2 focus-visible:outline-2 focus-visible:outline-ring"
          >
            {card.charset} glow
          </a>
          <p className="mt-1 text-sm text-muted-foreground">
            Lit from the {card.glow.replace("-", " ")}.
          </p>
        </AsciiCard>
      ))}
    </div>
  );
}
```

### Status panel [#status-panel]

A `double` frame with a `medium` shade shadow, a description and a count in the footer.

```tsx title="examples/ascii-card-status.tsx"
import { AsciiCard } from "@/components/asciicn/ascii-card";

const ROWS = [
  { name: "api", state: "healthy", tone: "text-[var(--ascii-color-green)]" },
  { name: "worker", state: "healthy", tone: "text-[var(--ascii-color-green)]" },
  {
    name: "billing",
    state: "degraded",
    tone: "text-[var(--ascii-color-orange)]",
  },
  { name: "search", state: "healthy", tone: "text-[var(--ascii-color-green)]" },
] as const;

export default function AsciiCardStatus() {
  return (
    <AsciiCard
      title="services"
      description="Checked every 30 seconds from 6 regions."
      footer="3/4 ok"
      frame="double"
      shadow="medium"
      className="max-w-sm"
    >
      <ul className="font-mono text-sm">
        {ROWS.map((row) => (
          <li key={row.name} className="flex justify-between gap-4">
            <span>{row.name}</span>
            <span className={row.tone}>{row.state}</span>
          </li>
        ))}
      </ul>
    </AsciiCard>
  );
}
```

## Props [#props]

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `title` | `ReactNode` |  | Set into the top border. Also names the card for screen readers. |
| `description` | `ReactNode` |  | A line of muted text above the content. |
| `footer` | `ReactNode` |  | Set into the bottom border, such as a status or a count. |
| `glow` | `GlowPosition \| "none"` | `"none"` | Where a glyph glow lights the card from: an edge, a corner, center, or an [x, y] point from 0 to 1. |
| `glowCharset` | `CharsetName` | `"standard"` | Glyphs the glow is drawn with. |
| `glowColor` | `AsciiColor` | `color` | Glow colour. |
| `interactive` | `boolean` | `false` | For clickable cards: hover and focus inside turn the frame heavy and brighten the glow. |
| `frame` | `"light" \| "heavy" \| "double" \| "rounded" \| "ascii"` | `"light"` | Box-drawing set for the frame. |
| `activeFrame` | `"light" \| "heavy" \| "double" \| "rounded" \| "ascii"` | `"heavy"` | The frame while an interactive card is hovered or focused. |
| `color` | `AsciiColor` | `"ink"` | Frame colour, and the glow's unless glowColor is set. |
| `padding` | `number` | `1` | Space inside the frame in rows; columns are doubled. |

`AsciiCard` takes every other [`AsciiBox` prop](/docs/interface/ascii-box#props) (`labelAlign`, `shadow`, `filled`, `cell`) and passes the rest to the wrapping `<div>`.

## Notes [#notes]

* The frame and glow are `aria-hidden`. The card is a `group` named by its title.
* The glow pauses offscreen and in hidden tabs, and holds one still frame with reduced motion.
* The interactive frame swaps glyph sets instantly, as a terminal redraws, with no transition to tune.
* Without `glow`, the card draws no canvas and runs no animation.