Skip to content

Components / Sections

Prompt Hero

A hero whose entry point is a prompt box: a small label, a short headline, a lead, a large PromptInput with Enter to send, a status line and example tasks. The placeholder line cycles through example tasks once and settles on the first, a caret in the accent blinks four times and stays, and the status line sweeps a highlight twice while it says the agent is ready. By default the form is a demo that sends nothing: it goes to a demo page with method="get" and the textarea has no name, so a typed prompt never lands in a URL. The section ships no script of its own; Enter to send is PromptInput's measured script.

Live demo

Sample agent · a demo form that sends nothing

Hand the failing build to an agent

Describe a task and press Enter. The examples under the box are links; what you type is never sent.

Ready · sample workspace

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
align

Measured

JavaScript of its own

0 B

Uses PromptInputSubmitOnEnter and the shared runtime (1.9 kB raw, once per site). With those included: 2.0 kB raw.

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 · newly available

Chrome 123 · Firefox 152 · Safari 26.2; needs field-sizing, has, property, bg-clip-text. Elsewhere: without field-sizing the box keeps its rows and a resize handle; without registered properties the example tasks cross-fade in place.

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-prompt
src/pages/index.astro
---
import HeroPrompt from '@/components/moonarc/pro/HeroPrompt.astro';
---
<!-- a demo form: it goes to /demo/ and sends no text. Give it a name and an action of your own to wire it to your app -->
<HeroPrompt
  label="Release 2.1"
  headline="Hand the failing build to an agent"
  lead="Describe the task. The agent reads the logs, changes the code and asks before it merges."
  placeholders={['Fix the failing checkout test', 'Update the lockfile', 'Explain why main is red']}
  status="Ready · 3 repositories connected"
  examples={[
    { label: 'Fix a failing test', href: '/demo/?task=fix-test' },
    { label: 'Update dependencies', href: '/demo/?task=update-deps' },
  ]}
  action="/demo/"
  glow
/>

Without a key the registry answers 401 with an upgrade message. Everything this section composes is free: prompt-input, rotating-text, shiny-text, orb.

Props

PropTypeDefaultDescription
headlinestringnoneThe headline; eight words or fewer read best. The headline slot wins over it.
labelstringnoneThe small line above the headline, in the monospace face and sentence case. The label slot wins over it.
leadstringnoneThe paragraph under the headline. The copy slot wins over it.
placeholdersstring[]['Describe a task']Example tasks for the placeholder line, up to three. With two or more, the line cycles through them once (4.8 s at most) and settles on the first, which is also the textarea's own placeholder.
statusstringnoneThe status line under the box while the agent is ready. A highlight sweeps it twice, then it rests.
examples{ label, href }[]noneExample tasks under the box, up to four: links to a demo page with the task's slug (/demo/?task=refactor), never the typed text.
examplesLabelstring'Try'The word before the examples, which also names their list.
actionstring'/demo/'Where the form goes. The default is a demo page.
method'get' | 'post''get'The form's method.
namestringnoneThe textarea's name. Unset, it has none and the form sends no text, so a typed prompt never lands in a URL. Set it, with an action of your own, to send the prompt to your app.
promptLabelstring'Describe a task'Accessible name of the textarea.
sendLabelstring'Run'Visually hidden name of the send button.
rowsnumber3Rows the box shows when empty; it grows with its text to eight.
glowbooleanfalseA soft light from the accent behind the box.
orbbooleanfalseThe Orb behind the box, still and dimmed, hidden from screen readers. Wins over glow: one depth cue at most.
level1 | 21Heading level of the headline: 1 on the page's own hero, 2 under another h1 (a demo).
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. With theme.css the box and the examples take the tone's card, and their text and edge the tone's text.
density'compact' | 'cozy' | 'roomy''cozy'Block padding and the gap above the box ×0.8 / ×1 / ×1.25 through --ma-density.
align'center' | 'start''center'Alignment of the label, the headline, the lead and the examples.

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-hero-prompt.ma-hero-prompt__aside.ma-hero-prompt__box.ma-hero-prompt__caret.ma-hero-prompt__cycle.ma-hero-prompt__dot.ma-hero-prompt__example.ma-hero-prompt__examples.ma-hero-prompt__examples-label.ma-hero-prompt__field.ma-hero-prompt__glow.ma-hero-prompt__headline.ma-hero-prompt__hint.ma-hero-prompt__inner.ma-hero-prompt__label.ma-hero-prompt__lead.ma-hero-prompt__orb.ma-hero-prompt__shine.ma-hero-prompt__status.ma-hero-prompt__status-text.ma-prompt__area

Slots

slot="label"slot="headline"slot="copy"slot="aside"

Reduced motion

The first example stands still as the textarea's placeholder: no cycle, no blinking caret and no sweep on the status line.

With ClientRouter

CSS only, and PromptInput's Enter script rebinds through the shared runtime; a new page restarts the cycle.

Why it is built this way

Replaces: Hero with AI input (Lovable style) · PlaceholdersAndVanishInput hero (Aceternity). See the migration table.

grows with the text · Enter sends · ⇧Enter breaks the line

The AI prompt box: a form with a textarea that grows with its content through field-sizing, a model select, an attachment button that is a real file input, and a send button that dims until something is typed and spins while the form carries data-pending.

newly · Chrome 123 · Firefox 152 · Safari 26.2click

Cycles through a list of words in place.

newly · Chrome 85 · Firefox 128 · Safari 16.4always

A highlight sweeps across the text every few seconds.

every browseralways

Sample conversation

Ask, watch it work, approve

An imaginary agent on an imaginary repository. Open a call to read what it returned.

Sample agent

Done

  1. You

    Fix the failing checkout test in apps/web

  2. Sample agent

    One assertion fails: the total keeps a fraction of a cent. I will find where it is computed.

    • read_log(job 4182)0.4 s
      FAIL apps/web/cart.test.ts
        total > rounds to cents
        expected 23.99, received 23.988
    • grep("* 1.2" apps/web/src)0.2 s
      apps/web/src/cart/total.ts:3  return sum * 1.2;
    • run_tests(apps/web)38 s
      Tests  48 passed (48)
      Time   37.9 s
  3. Sample agent

    Push the change to fix/checkout-rounding and open a pull request?

    Approved

  4. Sample agent

    Done. The total now rounds to cents after tax, and all 48 tests in apps/web pass. The pull request is open for review.

A conversation with an AI agent, replayed in the page: the reader's message, the agent's reply with its tool calls folded into <details> (the call and its result in the monospace face), a request for approval that is approved, and the final answer, typed, with a button that copies it; a prompt box at the foot as a demo form.

Chrome 116 · not Firefox · Safari 18scrollhoverclick

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