# Offer Shelf (Moonarc)

What one person sells, on a shelf: a course, a guide, a membership, prints or sessions. Each is a card with a cover drawn on a colour block (its name set large, a drawing in the corner, its kind on a band), then the kind and what it holds, the name, a line, the price and the way to buy it. A course lists its modules under a disclosure. One offer can be featured, twice as wide on a wide box. A pointer on a card lifts its cover off the shelf and leans it a little, and the buy button rises. Zero JavaScript.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/offer-shelf` (license key required)
- Tier B · category section · trigger hover, click
- Readout: `<OfferShelf offers={[{ name, kind, price, href, action, includes }]} />`
- Browser support: widely (Chrome 105 · Firefox 110 · Safari 16); elsewhere: without container units the shelf stays one column and the headline and the names keep the page's text size
- Measured cost: 0 B JS (CSS 18.9 kB raw)
- Page: https://moonarc.dev/components/offer-shelf/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `offers` | `{ name, kind, href, price?, note?, action?, includes?, block?, art?, featured? }[]` | none | The offers, in order. kind is "Course · 8 modules": the part before the first · goes on the cover's band and the whole of it in the mono face over the name. href is where it is bought or booked (your shop's page). action is the button's words ("Enrol"), the name when unset. includes is what it holds, a course's modules, listed under a disclosure with their count. block is the cover's colour (the first four in turn when unset); art is the cover's drawing (Motif), picked from the name when unset; featured makes the card twice as wide where the shelf has three columns. |
| `eyebrow` | `string` | none | A short line above the heading. Slot "eyebrow" wins. |
| `headline` | `string` | none | The heading. Slot "headline" wins and may hold an <em>, set in the emphasis face and colour. |
| `copy` | `string` | none | A line under the heading. |
| `more` | `{ href: string; label: string }` | none | A link beside the heading, e.g. to the whole shop. |
| `includesLabel` | `string` | `'What is inside'` | The disclosure's words over a list of modules. |
| `externalLabel` | `string` | `'(opens the shop)'` | What a screen reader hears after a link with a full http or https address, such as a shop on another site. |
| `level` | `1 | 2 | 3` | `2` | Heading level of the section's heading; the offers' names are one below. |
| `tone` | `'surface' | 'muted' | 'ink' | 'brand'` | `unset (paints nothing)` | The section's ground; the covers keep their blocks on every tone. |
| `density` | `'compact' | 'cozy' | 'roomy'` | `'cozy'` | Block padding ×0.8 / ×1 / ×1.25 through --ma-density. |

## Usage

```astro
---
import OfferShelf from '@/components/moonarc/pro/OfferShelf.astro';
---
<OfferShelf
  eyebrow="Work with me"
  offers={[
    { name: 'The first thousand', kind: 'Course · 8 modules', price: '$149', note: 'Build a list of a thousand readers without ads.', href: 'https://shop.example.com/first-thousand', action: 'Enrol', includes: ['Choosing a topic', 'The welcome email', 'Your first ten issues'], featured: true },
    { name: 'Pricing in public', kind: 'Guide · 64 pages', price: '$19', href: '/shop/pricing-guide/', action: 'Buy the guide' },
    { name: 'One hour', kind: 'Session · 1 hour', price: '$90', href: '/book/', action: 'Book a session' },
  ]}
>
  <span slot="headline">Everything I <em>sell</em></span>
</OfferShelf>
```

## Reduced motion

The hover states apply at once, without the spring on the cover or the rise of the button, and the disclosure's plus turns into a cross at once.

## With ClientRouter

CSS only; nothing to rebind. An open disclosure is the browser's own state and resets with the page.

## Craft

- The cover is a colour block with the offer's name set large on it, a drawing in the corner and the kind on a band, so a shelf of offers is a row of covers with no photograph and no design file.
- The cover lifts and leans from its bottom edge while the pointer is on the card, on the theme's spring, so it reads as a thing taken off a shelf. Touch screens get the still cover.
- The cover repeats what the text under it says, so it is hidden from assistive technology. The kind, the name, the note and the price are real text, and a course's modules sit in a native details element that opens from the keyboard without a script.
- A featured card spans two of the three columns on a wide box, so the rows fill when the featured offer comes first and the offers plus one make a multiple of three: 2, 5 or 8 offers with one featured.

## Replaces

- Creator storefront pages (Gumroad, Teachable)
- Product list sections (Tailwind Plus)

## Source

Pro block. The source is served by the license-gated registry: `npx shadcn@latest add @moonarc-pro/offer-shelf` with a key in components.json (https://moonarc.dev/account/). Everything it composes is free: motif.
