# ASCII Marquee

> An endless marquee of words or logos, set in glyphs.

Category: Images. Docs: https://asciicn.sumak.dev/docs/ascii-marquee

## Installation

```bash
npx shadcn@latest add @asciicn/ascii-marquee
```

Needs the `@asciicn` registry in components.json: `"registries": { "@asciicn": "https://asciicn.sumak.dev/r/{name}.json" }`.

## Usage

```tsx
import { AsciiMarquee } from "@/components/ascii/ascii-marquee"

<AsciiMarquee
  items={["acme", "northwind", "lumen", "orbital"]}
  className="text-muted-foreground"
/>
```

## Examples

### Opposing rows

Two marquees running in opposite directions make a headline band. A bigger `size` and cell keep the letters crisp at headline scale.

```tsx
<AsciiMarquee
  items={["design", "build", "ship"]}
  size={72}
  fontSize={6}
  className="text-primary"
/>
<AsciiMarquee
  items={["iterate", "measure", "learn"]}
  direction="right"
  size={72}
  fontSize={6}
  className="text-muted-foreground"
/>
```

### Your own items

Pass children to scroll anything, here a strip of ASCII photos. Give each child a fixed width so the loop length is stable.

```tsx
<AsciiMarquee gap={16} speed={24}>
  <AsciiImage src="/meadow.jpg" alt="Meadow" fontSize={6} className="w-36" />
  <AsciiImage src="/cabin.jpg" alt="Cabin" fontSize={6} className="w-36" />
  <AsciiImage src="/arcade.jpg" alt="Arcade" fontSize={6} className="w-36" />
  <AsciiImage src="/garden.jpg" alt="Garden" fontSize={6} className="w-36" />
</AsciiMarquee>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` | `string[]` |  | Words or wordmarks, each rasterised and drawn in glyphs. |
| `children` | `ReactNode` |  | Your own items instead of `items`, e.g. SVG logos or `AsciiImage`s. Each direct child is one item. |
| `speed` | `number` | `40` | Pixels per second, however many items there are. |
| `direction` | `"left" | "right"` | `"left"` | Which way the row travels. |
| `gap` | `number` | `48` | Space between items in pixels. |
| `size` | `number` | `40` | Height of each word in pixels. |
| `fade` | `number` | `64` | Width of the edge fade in pixels. 0 turns it off. |
| `pauseOnHover` | `boolean` | `true` | Pause while hovered or while anything inside has focus. |
| `font` | `string` | `900 sans` | CSS font used to rasterise each word. Every word shares one x-height, ascenders or not. |
| `charset, fontSize, color, dither, opacity` | `AsciiCanvas props` | `braille, 4` | Passed to every word in `items`. |

## Notes

- **Accessibility.** Words form a list, and each canvas is labelled with its word. The copies that make the loop seamless are `aria-hidden` and `inert`, so links inside children aren't read or tabbed to twice.
- **Motion.** A plain CSS animation that pauses on hover and focus. Under `prefers-reduced-motion` the copies are dropped and the items wrap into a centred, still row.
- **Seamless loop.** The row is repeated until each half is wider than the view, then the track slides by exactly one half, so there is never a gap or a jump.
- **Performance.** Each word is a small static canvas that draws once. Movement is a GPU transform, so nothing redraws while it scrolls.
