Skip to content

Components / Sections

Offer Shelf

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.

Live demo

Shop

Guides for a slow weekend

  • Guide · 120 pages

    The small web field guide

    How to plan, build and keep a small site going for years.

    What is inside 4
    1. Picking what to build
    2. A page that loads anywhere
    3. Words before pixels
    4. Forms people finish
  • Guide · 48 pages

    Colour in an afternoon

    One colour to a whole palette, with the contrast checks.

  • Membership · yearly

    The Friday membership

    A second letter each month and the guides as they come out.

Live, from the library itself, at full size: scroll, hover, navigate away and back. The demo is never gated.

Variants · each row writes the attribute the prop writes; the section's own CSS answers

tone
density

Measured

JavaScript of its own

0 B

CSS 18.9 kB raw including the base tokens. Measured from a production build, and again in CI for every change that can move it.

Browser support

Baseline · widely available

Chrome 105 · Firefox 110 · Safari 16; needs container-units. Elsewhere: without container units the shelf stays one column and the headline and the names keep the page's text size.

Install Pro

The demo above is never gated; the source is. With a key in components.json (see account), the registry serves it like any other item:

terminal
npx shadcn@latest add @moonarc-pro/offer-shelf
src/pages/index.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>

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: motif.

Props

PropTypeDefaultDescription
offers{ name, kind, href, price?, note?, action?, includes?, block?, art?, featured? }[]noneThe 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.
eyebrowstringnoneA short line above the heading. Slot "eyebrow" wins.
headlinestringnoneThe heading. Slot "headline" wins and may hold an <em>, set in the emphasis face and colour.
copystringnoneA line under the heading.
more{ href: string; label: string }noneA link beside the heading, e.g. to the whole shop.
includesLabelstring'What is inside'The disclosure's words over a list of modules.
externalLabelstring'(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.
level1 | 2 | 32Heading 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.

Theming and overrides

The section reads the theme contract (shadcn's variable names with the base tokens as fallback), so a pasted theme or one --ma-brand recolours it. Its class names are the override surface and stay stable; a named slot replaces the matching prop with your own markup.

Classes

.ma-shelf.ma-shelf__action.ma-shelf__art.ma-shelf__band.ma-shelf__body.ma-shelf__copy.ma-shelf__cover.ma-shelf__cover-name.ma-shelf__eyebrow.ma-shelf__foot.ma-shelf__head.ma-shelf__headline.ma-shelf__includes.ma-shelf__item.ma-shelf__kind.ma-shelf__list.ma-shelf__more.ma-shelf__n.ma-shelf__name.ma-shelf__note.ma-shelf__price.ma-shelf__titles

Slots

slot="eyebrow"slot="headline"

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.

Why it is built this way

Replaces: Creator storefront pages (Gumroad, Teachable) · Product list sections (Tailwind Plus). See the migration table.

Motif

Backgrounds

A drawn picture for a slot that has no photograph yet: a sun over the sea, a split gate, a flower, a grid of tiles, a phone going live, a plate set for dinner, waves under a moon or three shapes.

every browserhover

Product Art

Backgrounds

A product drawn flat, for a shop slot that has no photograph yet: 29 drawings in six sets (clothes, ceramics, coffee, skincare, furniture and objects, bakery).

every browserhover

Fixed packages with what they cost: each card names a package and who it suits, gives the price and what it is counted in (or "Price on request", for a business that quotes), lists what is included with a tick in a colour block, can carry a bonus line on that block, and ends in an action that asks about that package.

every browserhover

Free

$0/yr

MIT, forever

  • 125 primitives, no account, no token
  • Runtime, GSAP and Lenis adapters
  • Public shadcn registry
  • MCP server
Set up in five minutes

Pro

$129/yr

One person, billed yearly

  • 108 sections and 11 GPU effects, demos never gated
  • Every template: Waitlist, Launch, Agentic, Studio, Agency, Atelier, Gather, Creator, Endpoint, Homescreen, Estate, Practice, and Stay
  • audit_motion and measure_budget, locally and in CI
  • compose_section with a total cost
  • New components monthly, dated changelog
  • Email support within 2 working days
Not open yet: see the plan

Team

$349/yr

Up to 10 people, one invoice

  • Everything in Pro, for the whole team
  • One key for the team, locally and in CI
  • Move up from Pro at any time
  • More than 10 people: email us
Talk to us

Shows pricing plans side by side, with an annual/monthly toggle that rolls every price digit by digit to the other period with zero JavaScript (radios, :has and NumberFlow), the highlighted plan wearing a travelling border beam, cards revealed with a stagger.

newly · Chrome 125 · Firefox 128 · Safari 16.4scrollclick

The shop

Pieces from the current firing

A whole collection on one page, filtered by kind: the products as cards (each drawn on its plate with ProductArt, a hang tag for the price, the name as the card's link and a spec line in the mono face) in two, three or four columns by the box's width, and above them a row of filters with their counts (core FilterGrid: the cards that stay slide into place, and the URL keeps the filter).

newly · Chrome 137 · Firefox 144 · Safari 18.4hoverclick

Sample services

What an imaginary studio does

Brand identity

A name, a mark and the rules that hold them together, for a company that is new or has outgrown its look.

Deliverables

  • Logo and mark
  • Type and colour
  • Guidelines
Websites

Sites designed and built by one team, from the first sketch to the code that ships.

Deliverables

  • Design system
  • Astro build
  • Content model
Product design

Screens for an app or a tool, drawn with the people who will use them and handed over as working components.

Deliverables

  • Flows
  • Interface
  • Components
Motion

The logo in motion, a product film, the interface itself: motion that says one thing each time.

Deliverables

  • Motion identity
  • Product film
  • Interaction specs

What a studio or a freelancer does, as numbered rows at display size that open one at a time: each row names a service, and opens to a short text beside the list of deliverables.

newly · Chrome 131 · Firefox 143 · Safari 18.4clickhover

Also: view transitions · how costs are measured · browser support · accessibility policy · five-minute setup · MCP for agents · this page as Markdown