<!-- Protocore Design System — LogoMarquee -->
# LogoMarquee

- **Category:** Media (`media`)
- **Slug:** `media/logo-marquee`
- **Status:** stable
- **Platforms:** web
- **Import:** `import { LogoMarquee } from "@protocore/pds";`
- **Docs:** https://pds.protocore.io/components/media/logo-marquee

> The "trusted by" wall — a masked strip of wordmarks on an infinite loop.

## When to use it

**LogoMarquee** is the social-proof band: a *trusted by / powered by / integrates with* wall on a landing page or footer. Use it when you have **many** peer logos and motion earns attention; for a **single** brand mark use **Logo**, and for ambient section texture use **LineArt**. Keep the set homogeneous — all wordmarks or all real marks at a consistent height — so the loop reads as one system. In production, swap the placeholder wordmarks for actual partner SVGs.

## Props

| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `className` | `string` | no | — | — |
| `duration` | `number` | no | `30` | Seconds for one full loop. Default 30. |
| `eyebrow` | `ReactNode` | no | — | Optional mono eyebrow above the strip, e.g. "Trusted by". |
| `gap` | `number` | no | `64` | Gap between logos in px. Default 64. |
| `logos` | `ReactNode[]` | yes | — | Wordmarks (or nodes) to scroll. The list is duplicated for a seamless loop. |
| `style` | `CSSProperties` | no | — | — |

## Examples

### Basics

Pass an array of `logos` and an optional mono `eyebrow`. The strip is bounded by top/bottom hairlines, its edges faded with a mask gradient, and the track is duplicated for a seamless infinite loop. Hovering pauses it.

```tsx
import { LogoMarquee } from "@protocore/pds";

const NETWORKS = [
  "ETHEREUM",
  "BASE",
  "ARBITRUM",
  "OPTIMISM",
  "SOLANA",
  "POLYGON",
  "UNICHAIN",
  "AVALANCHE",
];

export default function Demo() {
  return <LogoMarquee eyebrow="Settling across 64 networks" logos={NETWORKS} />;
}
```

### Tuning speed & gap

`duration` sets seconds per full loop (default 30 — lower is faster) and `gap` sets the pixel spacing between logos (default 64). Here: no eyebrow, a quicker loop, tighter spacing.

```tsx
import { LogoMarquee } from "@protocore/pds";

const PARTNERS = ["CIRCLE", "CHAINLINK", "FIREBLOCKS", "ANCHORAGE", "LEDGER", "FALCONX", "COPPER"];

export default function Demo() {
  return (
    // No eyebrow, faster loop, tighter gap — a compact partner strip.
    <LogoMarquee logos={PARTNERS} duration={18} gap={40} />
  );
}
```

## Do & don't

**Do**

- Give it enough logos that the loop feels full — a duplicated track needs a decent set to look seamless.
- Keep every logo the same visual weight and height.
- Add a mono `eyebrow` to frame what the wall represents.
- Swap the placeholder wordmarks for real partner marks in production.

**Don't**

- Don't use it for a single logo — use Logo.
- Don't crank `duration` so low the strip becomes a distraction; motion should be ambient.
- Don't mix wildly different logo sizes or weights in one track.
- Don't put critical, must-read information in a moving strip.

## Accessibility

**Notes**

- Under `prefers-reduced-motion` the marquee stops animating and renders a static row instead.
- The track is duplicated for the seamless loop; the duplicate copy is `aria-hidden` so screen readers announce each logo only once.
- Motion pauses on hover, giving pointer users time to read.
- The component is server-safe — the loop is pure CSS animation, no JS timer.

## Related

`logo`, `line-art`, `eyebrow`, `footer`

---

© Protocore. All rights reserved. Use of the Protocore Design System requires prior written authorization from Protocore (contact@protocore.io). These machine-readable materials must not be ingested into ML-training datasets or derivative design systems. See https://pds.protocore.io/legal/
