Skip to content

Components / Sections

Hero Blocks

The opening of a colour-block site: the headline rises line by line out of its masks, its last word turns through a few in the emphasis face (RotatingText), a round badge with text running around it links further down the page, the lede and two pill actions sit under it, and a strip of tiles in the palette's blocks runs across the bottom (Marquee), each a drawing (Motif) or a picture with a caption. The rise is a CSS animation on load, so it needs no script. Zero JavaScript of its own.

Live demo

Sample agency

A feed that lives up to the real thing.

SAMPLE AGENCY • SINCE 2023 •

A sample agency that plans, shoots, designs and posts for restaurants, stays and lifestyle brands.

Start a projectSee the work

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 26.8 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.

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/hero-blocks
src/pages/index.astro
---
import HeroBlocks from '@/components/moonarc/pro/HeroBlocks.astro';
---
<HeroBlocks
  eyebrow="Creative agency"
  lines={['A feed that lives', 'up to the']}
  words={['real thing.', 'dining room.', 'villa.']}
  lede="We plan, shoot, design and post for restaurants, stays and lifestyle brands, and run the ads too."
  primary={{ href: '/contact/', label: 'Start a project' }}
  secondary={{ href: '/work/', label: 'See the work' }}
  badge={{ href: '#work', label: 'See the work', text: 'CREATIVE AGENCY • SINCE 2023 • ' }}
  tiles={[
    { label: 'Reel', motif: 'wave', shape: 'tall' },
    { label: 'Menu design', motif: 'plate' },
    { label: 'Live', motif: 'phone', shape: 'tall' },
  ]}
/>

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: circular-text, magnetic, marquee, motif, rotating-text.

Props

PropTypeDefaultDescription
linesstring[]noneThe headline, one string per line; each line rises from its own mask, a stagger step after the one before.
wordsstring[]noneWords that take turns as the headline's last line, in the emphasis face and colour (--ma-font-em, --ma-em). The first is the one read aloud.
cyclesnumber3Rounds the words turn before the first comes back and stays (WCAG 2.2.2).
eyebrowstringnoneA short line above the headline. Slot "eyebrow" wins; slot "meta" sits at the other end of the same row (a clock, an opening time).
ledestringnoneThe paragraph under the headline. Slot "lede" wins.
primary{ href: string; label: string }noneThe first action: a pill in the action colour; on hover the first colour block wells up from below its label.
secondary{ href: string; label: string }noneThe second action: an outlined pill that fills with the text colour on hover. Slot "actions" replaces both.
magneticbooleantrueThe primary action follows the pointer a little (Magnetic).
badge{ href: string; label: string; text: string }noneThe round badge beside the headline from a 64rem box: where it links, its accessible name, and the text on its ring (CircularText, one turn in 24 s). End the text with a separator so the ring closes.
tiles{ label?, motif?, block?, shape?, image? }[]noneThe strip under the hero. Each tile paints a colour block (the five in turn when unset) with a drawing, or shows a picture; shape is tall (9 : 16), portrait (4 : 5, default) or square. The strip is decoration and is hidden from assistive technology.
durationnumber60Seconds the strip takes for one pass.
level1 | 21Heading level: 1 when the hero opens its page, 2 when it is shown under another h1.
tone'surface' | 'muted' | 'ink' | 'brand'unset (paints nothing)The ground: the page surface, a muted band, an always-dark ink panel, or a deep brand panel; the actions invert on ink and brand.
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-heroblocks.ma-heroblocks__actions.ma-heroblocks__badge.ma-heroblocks__disc.ma-heroblocks__eyebrow.ma-heroblocks__foot.ma-heroblocks__head.ma-heroblocks__inner.ma-heroblocks__lede.ma-heroblocks__line.ma-heroblocks__meta.ma-heroblocks__primary.ma-heroblocks__ring.ma-heroblocks__secondary.ma-heroblocks__strip.ma-heroblocks__tile.ma-heroblocks__title.ma-heroblocks__top.ma-heroblocks__word

Slots

slot="eyebrow"slot="meta"slot="lede"slot="actions"slot="aside"

Reduced motion

Everything is in place from the start: no rise, the first word stays, the strip and the badge stand still.

With ClientRouter

CSS animations and the primitives' own bindings; nothing of its own to rebind. Each visit plays the rise again.

Why it is built this way

Replaces: Agency hero sections (Framer templates). See the migration table.

A ring of text turning slowly around an icon, a logo, or nothing.

every browseralways

Marquee

Ticker

Infinite scrolling strip for logos, quotes or tags in any direction.

every browseralwayshover

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

Cycles through a list of words in place.

newly · Chrome 85 · Firefox 128 · Safari 16.4always

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