# Hero Bento (Moonarc)

The first screen of one person's work, as a bento. On a strong colour block sit the headline, a line and two actions, and beside them soft tiles in the palette's tints: the person drawn (PortraitArt) or photographed, with a ring of words turning at its corner; the latest piece with its waveform or its drawing; the count of readers, rising as it comes into view (core CountUp); and the places to find them elsewhere. The tiles lean toward the pointer (core Tilt). Zero JavaScript of its own.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/hero-bento` (license key required)
- Tier B · category section · trigger pointer, scroll, always
- Readout: `<HeroBento person={{ name, role }} latest={{ kind, title, href }} count={{ to, label }} />`
- Browser support: newly (Chrome 105 · Firefox 128 · Safari 17); elsewhere: the count shows its final number at once without @property; without :has() the latest piece's link shows no focus ring; without container units the headline keeps the page's text size and the intro and the tiles stay stacked
- Measured cost: 0 B JS of its own · uses Tilt + runtime (with dependencies 2.3 kB raw; CSS 27.1 kB raw)
- Page: https://moonarc.dev/components/hero-bento/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `eyebrow` | `string` | none | A short line above the heading, with a dot before it. Slot "eyebrow" wins. |
| `headline` | `string` | none | The heading. Slot "headline" wins and may hold an <em>, set in the emphasis face and colour. |
| `lede` | `string` | none | A line under the heading. |
| `primary` | `{ href: string; label: string }` | none | The main action, filled, with an arrow. |
| `secondary` | `{ href: string; label: string }` | none | The second action, outlined. |
| `person` | `{ name: string; role?: string; photo?: string }` | none | The person. The name draws the portrait (PortraitArt: the same name, the same drawing), or photo shows their photograph in its place (a path under public/ or a URL). role is the caption, a pill at the portrait's lower left with the name in bold and then the role. The portrait and the photograph are decoration, so without a role the name is not printed in this tile. |
| `badge` | `string` | none | Words that turn in a ring at the portrait's corner (CircularText). End them with a separator so the loop closes: "New issue every Friday · ". Decoration: say it in the lede too. |
| `latest` | `{ kind, title, meta?, href, look?, art? }` | none | The latest piece: its kind in the mono face, its title (the link, stretched over the whole tile), a line of detail and where it is. look is wave (a waveform drawn from the title, for audio and video) or tile (a drawing, the default); art (sun, gate, flower, grid, phone, plate, wave or shapes) picks the drawing, and it is drawn from the title when unset. |
| `count` | `{ to: number; label: string; prefix?: string; suffix?: string; separator?: string }` | none | The count that rises (CountUp, over 1600 ms, as the tile comes into view): readers, listeners, students. separator is the thousands separator, a comma by default. |
| `links` | `{ title?: string; items: { label: string; href: string }[] }` | none | Where else to find them: a short title in the mono face, and the links as outlined pills across the foot of the tiles. A list with no items draws no tile. |
| `externalLabel` | `string` | `'(another site)'` | What a screen reader hears after a link to another site in the links tile. |
| `block` | `1 | 2 | 3 | 4 | 5` | `5` | The colour block the panel paints: the strong one, 5 in every palette. |
| `tiles` | `(1 | 2 | 3 | 4 | 5)[]` | `[1, 2, 3, 4]` | Four colour blocks, one per tile in order: the portrait, the latest piece, the count, the links. |
| `level` | `1 | 2` | `1` | Heading level: 1 as the page's hero, 2 under another h1. |
| `density` | `'compact' | 'cozy' | 'roomy'` | `'cozy'` | Block padding ×0.8 / ×1 / ×1.25 through --ma-density. |

## Usage

```astro
---
import HeroBento from '@/components/moonarc/pro/HeroBento.astro';
---
<HeroBento
  eyebrow="Weekly newsletter"
  lede="One essay a week on making a living from small things. Free, every Friday."
  primary={{ href: '#signup', label: 'Subscribe' }}
  secondary={{ href: '/archive/', label: 'Read the archive' }}
  person={{ name: 'Your Name', role: 'Writer and illustrator' }}
  badge="New issue every Friday · "
  latest={{ kind: 'Issue 42', title: 'The slow way to a first thousand readers', meta: '8 min read · 3 October', href: '/issues/42/' }}
  count={{ to: 12400, suffix: '+', label: 'readers every Friday' }}
  links={{ title: 'Elsewhere', items: [{ label: 'Podcast', href: 'https://example.com/podcast' }, { label: 'Courses', href: '/courses/' }] }}
>
  <span slot="headline">Making a living from <em>small things</em></span>
</HeroBento>
```

## Reduced motion

The tiles do not lean, the ring is still, the count shows its final number without counting, the waveform and the drawing stay at rest, and the buttons and links change without their short lift.

## With ClientRouter

The lean and the count are core Tilt and CountUp, bound by the runtime once per swap; the ring, the waveform and the rest are CSS.

## Craft

- The panel and the four tiles are colour blocks, so the portrait, the latest piece, the count and the links take four tints of the palette on the strong one, and tiles reorders which tint goes where.
- The whole latest tile is its link: the title's pseudo-element stretches over the tile, and the keyboard focus ring is drawn around the tile instead of around the title.
- The portrait tile spans two rows beside the others, and on a wide box the intro and the tiles sit in two columns by container query, so the hero is right in a narrow column as well as at full width.
- The portrait, the ring and the waveform are decoration and hidden from assistive technology. The caption, the piece's title and the count's text carry the words, and the count's final value is in the HTML before it rises.

## Replaces

- Bento grid hero sections (Tailwind Plus, Magic UI)
- Link-in-bio landing pages (Linktree, Beacons)

## Source

Pro block. The source is served by the license-gated registry: `npx shadcn@latest add @moonarc-pro/hero-bento` with a key in components.json (https://moonarc.dev/account/). Everything it composes is free: portrait-art, count-up, circular-text, tilt, motif, waveform.
