# Sticky Features (Moonarc)

Steps on one side and one visual on the other that stays in view and changes with them, under a lead paragraph that brightens word by word as it is read. The current step is at full strength and the others dim. Zero JavaScript: StickyReveal binds each visual to its step's view timeline and SplitText scrub binds each word of the lead.

- Pro block. Install: `npx shadcn@latest add @moonarc-pro/feature-sticky` (license key required)
- Tier B · category section · trigger scroll
- Readout: `<FeatureSticky steps={[…]} lead="…"> <X slot="visual-1" />`
- Browser support: limited (Chrome 116 · not Firefox · Safari 26); elsewhere: one column, each step followed by its own visual, and the lead whole (Firefox, and every browser below 40 rem of the section's width)
- Measured cost: 0 B JS of its own · uses Reveal + runtime (with dependencies 3.0 kB raw; CSS 17.9 kB raw)
- Page: https://moonarc.dev/components/feature-sticky/

## Props

| Prop | Type | Default | Description |
|---|---|---|---|
| `steps` | `{ title, body? }[]` | none | The steps, up to eight: the title is an h3 under the section's h2, the body plain text or HTML. Put each step's visual in slot="visual-{n}", n from 1. |
| `headline` | `string` | none | The section's h2. The headline slot wins over it. |
| `eyebrow` | `string` | none | Small label above the headline. The eyebrow slot wins over it. |
| `lead` | `string` | none | The paragraph under the headline; its words brighten from dim to full as it moves up the screen. The copy slot wins over it and does not brighten. |
| `media` | `'right' | 'left'` | `'right'` | Side of the sticky visual: the inline end (right) or the inline start (left). On a right-to-left page right is on the left. |
| `top` | `string` | `'var(--ma-feature-sticky-top, 5rem)'` | Sticky offset of the visual: your sticky bar's height plus a gap. Set --ma-feature-sticky-top on the page to change every instance. |
| `height` | `string` | `'min(70vh, calc(100svh - top - 1.5rem))'` | Height of each step and of the sticky visual. The default never runs past the bottom of the screen. |
| `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. Each paints --background, --ma-tone-muted (over --muted, with a --border hairline), --ma-tone-ink or --ma-tone-brand (over --primary) with the matching text. With theme.css, a painted tone also re-declares --card, --border, --input and --ring inside the section, so the visual cards follow the ground. |
| `density` | `'compact' | 'cozy' | 'roomy'` | `'cozy'` | Block padding and the gap under the head ×0.8 / ×1 / ×1.25 through --ma-density. |
| `align` | `'start' | 'center'` | `'start'` | Alignment of the eyebrow, the headline and the lead. |

## Usage

```astro
---
import FeatureSticky from '@/components/moonarc/pro/FeatureSticky.astro';
---
<!-- top: the sticky bar's height and a gap. Set --ma-feature-sticky-top once in your global CSS instead, and every
     instance reads it -->
<FeatureSticky
  eyebrow="How it works"
  headline="From a store to a report in three steps"
  lead="Connect a store, set your rules, and read the week in one place. Each step below shows the screen it happens on."
  steps={[
    { title: 'Connect a store', body: 'Orders and stock arrive within a minute of the first sync.' },
    { title: 'Set your rules', body: 'Low stock, late orders and returns each raise their own alert.' },
    { title: 'Read the week', body: 'One report every Monday, with the numbers that moved.' },
  ]}
>
  <img slot="visual-1" src="/features/connect.png" alt="" />
  <img slot="visual-2" src="/features/rules.png" alt="" />
  <img slot="visual-3" src="/features/report.png" alt="" />
</FeatureSticky>
```

## Reduced motion

The visuals hand over in place without travel, every step stays at full strength, and the lead is whole.

## With ClientRouter

Inherits StickyReveal and SplitText; nothing to wire, both are CSS only.

## Craft

- The lead brightens instead of the steps: StickyReveal already dims every step but the current one, and two effects on the same text read as one too many.
- The sticky visual is capped at the screen under its offset, so its bottom edge is never below the fold.
- Visuals are decorative unless they carry text; text a reader needs goes in the step body, where it is real text.

## Replaces

- StickyScroll reveal (Aceternity)
- Feature section with sticky screenshot (Tailwind Plus)

## Source

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