Skip to content
Library · Components

Components

The canonical building blocks, live. Every snippet is copy-pasteable HTML — no JavaScript required except where noted. Styles come from src/styles/design-system.css.

Buttons

Base .btn with variants. Accent is reserved for the single primary action per view; danger only for destructive actions.

html
<button class="btn btn-primary">Primary</button>
<button class="btn">Secondary</button>
<button class="btn btn-ghost">Ghost</button>
<button class="btn btn-danger">Delete</button>
<button class="btn btn-sm">Small</button>
<button class="btn btn-lg">Large</button>
<button class="btn-icon" aria-label="Settings">…</button>

Split-ops hero & terminal card

Public-only composition for ReachOut 2.0.2: status strip, hybrid display heading, flat console actions, and a machine-readable agent transcript.

● reachout consolemcp: connectedaudit: ● rec
Marketing automation · reimagined for AI

Your agent runs your marketing

One operating layer for analytics, campaigns, contacts, and insights.

agent session
you launch spring-digest
segments.resolve engaged_30d OK
Queued 24,188 recipients.
tools: 37● rec
html
<section class="hero-console texture-dots">
  <div class="console-status">…</div>
  <div class="hero-console-grid">
    <div class="hero-console-lead">…</div>
    <div class="hero-console-session">
      <div class="termcard">…</div>
    </div>
  </div>
</section>

Console buttons

Public CTAs only. The sigil is visual; the approved CTA wording and authenticated state remain unchanged.

html
<a class="cbtn cbtn-primary" href="/signup">Get Started</a>
<a class="cbtn cbtn-ghost" href="/demo">See the live demo</a>

Diff compare strip

A compact public comparison. Signs keep the meaning visible without relying on color.

reachout vs legacy automation
+MCP tool calls
+Every agent call logged
Visual journey builders
html
<div class="diff">
  <div class="diff-head">reachout vs legacy automation</div>
  <div class="diff-row plus"><span class="sign">+</span><span class="diff-copy">MCP tool calls</span></div>
  <div class="diff-row minus"><span class="sign">−</span><span class="diff-copy">visual builders</span></div>
</div>

Pricing readout

Homepage pricing summary. The pricing page retains its fuller calculator and FAQ composition.

StarterFree100 MCP calls · 40 insights
Pro$20 / seat / month10k emails · 1k MCP calls · 1k insights
Max$100 / seat / month100k emails · 5k MCP calls · 5k insights
html
<div class="readout">
  <div class="readout-row"><span class="readout-tier">Starter</span>…</div>
  <div class="readout-row selected"><span class="readout-tier">Pro</span>…</div>
  <div class="readout-row"><span class="readout-tier">Max</span>…</div>
</div>

Capability card

Console-framed public feature card with a machine label, readable description, and quiet status footer.

Website analyticsstudio
First-party, identified, no aggregation
status: shipped
html
<article class="capcard">
  <div class="capcard-head"><span>Website analytics</span><span class="capcard-surface">studio</span></div>
  <div class="capcard-body">First-party, identified, no aggregation</div>
  <div class="capcard-foot">status: <span class="capcard-status">shipped</span></div>
</article>

Dotted texture

Use .texture-dots only on the public hero and section dividers. It adapts automatically to both themes.

html
<div class="texture-dots ds-texture-preview"></div>

Badges

Status at a glance — mono, uppercase, optional pulsing dot. Use .badge-live for running things, .badge-done for success, .badge-err for failures, .badge-warn for limits, .badge-draft for inactive.

LiveSentFailedNear capDraftv1.0.1
html
<span class="badge badge-live"><span class="dot"></span>Live</span>
<span class="badge badge-done"><span class="dot"></span>Sent</span>
<span class="badge badge-err"><span class="dot"></span>Failed</span>
<span class="badge badge-warn"><span class="dot"></span>Near cap</span>
<span class="badge badge-draft">Draft</span>
<span class="badge">v1.0.1</span>

Card

The base surface: 1px border, --bg-elev, --radius-lg, never a shadow. Compose with .card-head, .card-body, .card-foot.

Deliverability

Last 30 days across all campaigns

Delivered
98.2%
Bounced
1.1%
Complaints
0.02%
Updated 4 min agosrc: ses-eu-1
html
<div class="card">
  <div class="card-head">
    <div class="card-head-main">
      <h3 class="card-title">Deliverability</h3>
      <p class="card-sub">Last 30 days across all campaigns</p>
    </div>
    <div class="card-head-actions"><button class="btn btn-sm">Export</button></div>
  </div>
  <div class="card-body">…</div>
  <div class="card-foot"><span>Updated 4 min ago</span><span class="mono">src: ses-eu-1</span></div>
</div>

Stat cards

The canonical metric tile: sans label, mono tabular value, semantic delta. Wrap in .stat-grid (4-up, responsive). Mark selectable cards with button.stat-card + .selected.

Emails sent ↗ +18.2%12,408vs 10,498 previous period
Open rate ↗ +2.4 pts41.7%Unique opens / delivered
Bounce rate ↗ +0.3 pts1.1%Hard bounces / sent
MCP calls → 0.0%862Agent tool invocations
html
<div class="stat-grid">
  <div class="stat-card">
    <span class="stat-label">Emails sent <span class="delta up">↗ +18.2%</span></span>
    <span class="stat-value">12,408</span>
    <span class="stat-sub">vs 10,498 previous period</span>
  </div>
  …
</div>

Delta

Signed change indicator. Semantic color, mono, arrow glyph. .delta-framed adds the bordered chip used in selectable stat cards.

↗ +18.2%↗ +0.3 pts→ 0.0%↗ +18.2%↗ +0.3 pts
html
<span class="delta positive">↗ +18.2%</span>
<span class="delta negative">↗ +0.3 pts</span>
<span class="delta neutral">→ 0.0%</span>
<span class="delta positive delta-framed">↗ +18.2%</span>

Forms

.field composes label + control + hint/error. Checkboxes, radios and switches are native inputs, themed.

Shown to your agent in tool calls.
Enter a valid sender address.
html
<div class="field">
  <label class="field-label" for="name">Campaign name <span class="req">*</span></label>
  <input id="name" type="text" placeholder="spring-launch" />
  <span class="field-hint">Shown to your agent in tool calls.</span>
</div>
<div class="field has-error">
  <label class="field-label" for="from">Sender</label>
  <input id="from" type="email" value="not-an-email" />
  <span class="field-error">Enter a valid sender address.</span>
</div>
<label class="check"><input type="checkbox" checked /> GDPR consent stored</label>
<label class="check radio"><input type="radio" name="r" checked /> Immediate send</label>
<label class="switch"><input type="checkbox" checked /> Live tracking</label>

Segmented control & tabs

Segmented for switching a view within a panel (aria-pressed); tabs for page-level navigation.

html
<div class="segmented" role="group" aria-label="Range">
  <button aria-pressed="false">7d</button>
  <button aria-pressed="true">30d</button>
  <button aria-pressed="false">3m</button>
</div>

<nav class="tabs" aria-label="Analytics sections">
  <a href="#" class="active" aria-current="page">Overview</a>
  <a href="#">Deliverability</a>
  <a href="#">Engagement</a>
</nav>

Alerts

Inline feedback. Info = accent, success = positive, warning = warning, danger = negative.

Agent access enabledYour MCP endpoint is reachable at mcp.usereachout.com.
Campaign sent12,408 emails delivered in 4m 12s.
Approaching plan limit8,412 / 10,000 emails used this cycle.
Domain not verifiedDKIM record missing — sends are paused.
html
<div class="alert alert-info">…</div>
<div class="alert alert-success">…</div>
<div class="alert alert-warning">…</div>
<div class="alert alert-danger">…</div>

Modal

The one canonical dialog: .modal-backdrop > .modal > head/body/foot. createModalController() owns focus, isolation, Escape/backdrop close and restoration.

html
<div class="modal-backdrop">
  <div class="modal" role="dialog" aria-modal="true" aria-labelledby="m-title" tabindex="-1">
    <div class="modal-head">
      <div>
        <div class="modal-kicker">contacts.delete</div>
        <h3 id="m-title">Delete 2 contacts?</h3>
      </div>
      <button class="modal-close" aria-label="Close">✕</button>
    </div>
    <div class="modal-body">…</div>
    <div class="modal-foot">
      <span class="modal-foot-note">This cannot be undone.</span>
      <button class="btn">Cancel</button>
      <button class="btn btn-danger">Delete</button>
    </div>
  </div>
</div>

Progress

Thin meters for usage and send progress. Default accent; semantic states for ok/warn/err.

Emails this cycle8,412 / 10,000
html
<div class="progress"><span class="progress-fill" style="width: 64%"></span></div>
<div class="progress progress-ok">…</div>
<div class="progress progress-warn">…</div>
<div class="progress progress-err">…</div>

<div class="progress-labeled">
  <div class="progress-head"><span>Emails this cycle</span><b>8,412 / 10,000</b></div>
  <div class="progress progress-warn"><span class="progress-fill" style="width: 84%"></span></div>
</div>

Loading progress & skeleton

The viewport bar confirms route progress; skeletons preserve the shape and hierarchy of unresolved data. Motion respects reduced-motion preferences.

html
<div class="studio-page-progress" aria-hidden="true">
  <span class="studio-page-progress-fill"></span>
</div>
<div aria-hidden="true">
  <div class="skeleton skeleton-heading"></div>
  <div class="skeleton skeleton-line skeleton-line-wide"></div>
  <div class="skeleton skeleton-chart"></div>
</div>

Empty state

Every list and table needs one. Icon in a dashed frame, sans title, body copy, one primary action, optional mono hint for the agent path.

No segments yet

Segments target campaigns. Create one here, or ask your agent to build it from a natural-language rule.

mcp · segments.create
html
<div class="empty-state">
  <div class="empty-state-icon">⌁</div>
  <h3>No segments yet</h3>
  <p>Segments target campaigns. Create one here, or ask your agent.</p>
  <button class="btn btn-primary">Create segment</button>
  <div class="mono-note">mcp · segments.create</div>
</div>

Key-value list

Dense metadata display — sans keys, mono tabular values, dashed separators.

API key
ro_live_9f2…c41
Created
2026-07-14 09:32
Calls this cycle
862 / 1,000
Last used
4 min ago
html
<dl class="kv">
  <div class="kv-row"><dt>API key</dt><dd>ro_live_9f2…c41</dd></div>
  <div class="kv-row"><dt>Created</dt><dd>2026-07-14 09:32</dd></div>
  <div class="kv-row"><dt>Calls this cycle</dt><dd>862 / 1,000</dd></div>
</dl>

Code & terminal

.code-block with token colors (.tk-*). Machine content stays mono — this is the agent's native tongue.

bash
$ reachout campaigns send --id spring-launch
 validated segment 3,102 contacts
 queued 12,408 emails # est. 4m 12s
html
<div class="code-block">
  <span class="code-lang">bash</span>
  <pre><code><span class="tk-prompt">$</span> <span class="tk-cmd">reachout campaigns send</span> <span class="tk-flag">--id</span> spring-launch
<span class="tk-ok">✓</span> queued 12,408 emails <span class="tk-comment"># 4m 12s</span></code></pre>
</div>

Mockup frames

Product presentation for public pages: .mockup (browser chrome) and .mockup-terminal. Fill the body with a screenshot, a live iframe, or — preferred — real components at reduced scale.

studio.usereachout.com/analytics
Sent12,408
Opens41.7%
Clicks6.2%
agent — mcp session
segments.estimate { "rule": "opened_last_30d" }
{ "contacts": 3102, "confidence": 0.94 }
html
<div class="mockup">
  <div class="mockup-chrome">
    <span class="mockup-dots"><i></i><i></i><i></i></span>
    <span class="mockup-url"><span class="lock">●</span> studio.usereachout.com/analytics</span>
  </div>
  <div class="mockup-body">…screenshot, iframe or CSS miniature…</div>
</div>