Blocks · Marketing

Marketing 6

Conversion and insight sections: pricing, dashboards, stats, and CTA.

Dashboard — analytics

KPI cards with trend badges over an engagement line chart and a traffic-source donut.

CardChartBadgeButton

Active users24,803 +12.4%
Sessions108,392 +8.1%
Bounce rate31.6% +2.3%
Avg. session4m 12sstable

Traffic sources

Share of sessions

Direct: 435 (45%)Search: 286 (30%)Social: 151 (16%)Referral: 96 (10%)
CategoryShare
Direct435
Search286
Social151
Referral96
---
import { Card, Chart, Badge, Button, Tabs } from "astro-ui";
---

<div class="dash">
  {/* KPI row: value + trend badge per metric */}
  <div class="dash__kpis">
    <Card size="sm">
      <div class="dash__kpi">
        <span class="dash__kpi-label">Active users</span>
        <span class="dash__kpi-value">24,803</span>
        <Badge variant="success" size="sm">+12.4%</Badge>
      </div>
    </Card>
    <Card size="sm">
      <div class="dash__kpi">
        <span class="dash__kpi-label">Sessions</span>
        <span class="dash__kpi-value">108,392</span>
        <Badge variant="success" size="sm">+8.1%</Badge>
      </div>
    </Card>
    <Card size="sm">
      <div class="dash__kpi">
        <span class="dash__kpi-label">Bounce rate</span>
        <span class="dash__kpi-value">31.6%</span>
        <Badge variant="destructive" size="sm">+2.3%</Badge>
      </div>
    </Card>
    <Card size="sm">
      <div class="dash__kpi">
        <span class="dash__kpi-label">Avg. session</span>
        <span class="dash__kpi-value">4m 12s</span>
        <Badge variant="muted" size="sm">stable</Badge>
      </div>
    </Card>
  </div>

  {/* Charts: engagement trend + traffic mix */}
  <div class="dash__charts">
    <Card class="dash__engagement">
      <div class="dash__panel-head">
        <div>
          <h3 class="dash__panel-title">Engagement</h3>
          <p class="dash__panel-sub">Daily active users</p>
        </div>
      </div>
      {/* Range switcher: dissolved into the card grid via display:contents
          (dash__range) — tablist row, then the active chart below. */}
      <Tabs
        class="dash__range"
        variant="pill"
        size="xs"
        ariaLabel="Date range"
        defaultValue="7d"
        items={[
          { value: "7d", label: "7d" },
          { value: "30d", label: "30d" },
          { value: "90d", label: "90d" },
        ]}
      >
        <div data-tab="7d">
          <Chart
            type="area"
            curve
            gradient
            height={220}
            labels={["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]}
            series={[
              { name: "This week", data: [4200, 5100, 4800, 6400, 7200, 5900, 8100] },
              { name: "Last week", data: [3800, 4200, 4500, 4800, 5200, 6100, 7000] },
            ]}
          />
        </div>
        <div data-tab="30d">
          <Chart
            type="area"
            curve
            gradient
            height={220}
            labels={["W1", "W2", "W3", "W4"]}
            series={[
              { name: "This month", data: [31500, 34200, 32800, 38900] },
              { name: "Last month", data: [28400, 30100, 31900, 33400] },
            ]}
          />
        </div>
        <div data-tab="90d">
          <Chart
            type="area"
            curve
            gradient
            height={220}
            labels={["May", "Jun", "Jul"]}
            series={[
              { name: "This quarter", data: [121000, 134600, 147200] },
              { name: "Last quarter", data: [108300, 115900, 124100] },
            ]}
          />
        </div>
      </Tabs>
    </Card>
    <Card>
      <div class="dash__panel-head">
        <div>
          <h3 class="dash__panel-title">Traffic sources</h3>
          <p class="dash__panel-sub">Share of sessions</p>
        </div>
      </div>
      <Chart
        type="donut"
        gradient
        height={220}
        labels={["Direct", "Search", "Social", "Referral"]}
        series={[{ name: "Share", data: [435, 286, 151, 96] }]}
      />
    </Card>
  </div>
</div>

<style is:global>
  .dash { display: grid; gap: var(--ui-space-4); }
  .dash__kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); gap: var(--ui-space-3); }
  .dash__kpi { display: grid; gap: var(--ui-space-1); justify-items: start; }
  .dash__kpi-label { color: var(--ui-muted-foreground); font-size: var(--ui-text-xs); font-weight: var(--ui-font-medium); }
  .dash__kpi-value { color: var(--ui-foreground); font-size: var(--ui-text-2xl); font-weight: var(--ui-font-semibold); letter-spacing: -0.02em; font-variant-numeric: tabular-nums; }
  .dash__charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(20rem, 1fr)); gap: var(--ui-space-3); }
  .dash__panel-head { display: flex; align-items: start; justify-content: space-between; gap: var(--ui-space-2); margin-block-end: var(--ui-space-3); }
  .dash__panel-title { margin: 0; color: var(--ui-foreground); font-size: var(--ui-text-md); font-weight: var(--ui-font-semibold); }
  .dash__panel-sub { margin: 0; color: var(--ui-muted-foreground); font-size: var(--ui-text-xs); }
  .dash__range { display: contents; }
  .dash__engagement .aui-tabs__panels { display: grid; }
</style>

Pricing tiers

Three plan cards with a highlighted middle tier and feature lists.

CardBadgeButton

Starter

$0 forever

Everything you need to evaluate the library.

  • 63 components
  • Tokens & base CSS
  • Community support

Team

$49 per month

For organizations standardizing on astro-ui.

  • Everything in Pro
  • Unlimited projects
  • Shared token themes
  • Slack support
---
import { Card, Badge, Button } from "astro-ui";
---

<div class="block-pricing">
  <Card class="block-plan">
    <h3 slot="header">Starter</h3>
    <div class="block-plan__body">
      <p class="block-price"><strong>$0</strong> <span>forever</span></p>
      <p class="block-hint">Everything you need to evaluate the library.</p>
      <ul class="block-features">
        <li>63 components</li>
        <li>Tokens &amp; base CSS</li>
        <li>Community support</li>
      </ul>
    </div>
    <Button variant="outline" class="block-btn-full block-plan__cta">Start free</Button>
  </Card>

  <Card class="block-plan block-plan--featured">
    <h3 slot="header">Pro <Badge variant="primary" size="sm">Popular</Badge></h3>
    <div class="block-plan__body">
      <p class="block-price"><strong>$19</strong> <span>per month</span></p>
      <p class="block-hint">For teams shipping production sites.</p>
      <ul class="block-features">
        <li>Everything in Starter</li>
        <li>Priority examples</li>
        <li>Blocks library</li>
        <li>Email support</li>
      </ul>
    </div>
    <Button variant="primary" class="block-btn-full block-plan__cta">Get Pro</Button>
  </Card>

  <Card class="block-plan">
    <h3 slot="header">Team</h3>
    <div class="block-plan__body">
      <p class="block-price"><strong>$49</strong> <span>per month</span></p>
      <p class="block-hint">For organizations standardizing on astro-ui.</p>
      <ul class="block-features">
        <li>Everything in Pro</li>
        <li>Unlimited projects</li>
        <li>Shared token themes</li>
        <li>Slack support</li>
      </ul>
    </div>
    <Button variant="outline" class="block-btn-full block-plan__cta">Contact us</Button>
  </Card>
</div>

<style is:global>
  .block-pricing {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
    gap: var(--ui-space-4);
    align-items: stretch;
  }
  .block-plan { display: flex; flex-direction: column; height: 100%; }
  .block-plan .aui-card__header h3 { display: flex; align-items: center; gap: var(--ui-space-2); margin: 0; }
  .block-plan .aui-card__content { display: flex; flex-direction: column; flex: 1; }
  .block-plan__body { display: grid; gap: var(--ui-space-3); align-content: start; flex: 1; }
  .block-plan__cta { margin-block-start: var(--ui-space-4); }
  .aui-card.block-plan.block-plan--featured { border-color: var(--ui-primary); box-shadow: 0 0 0 1px var(--ui-primary), var(--ui-shadow-lg); }
  .block-price { display: flex; align-items: baseline; gap: var(--ui-space-2); margin: 0; }
  .block-price strong { font-size: var(--ui-text-3xl); font-weight: var(--ui-font-bold); letter-spacing: -0.03em; }
  .block-price span { font-size: var(--ui-text-sm); color: var(--ui-muted-foreground); }
  .block-features { display: grid; gap: var(--ui-space-2); margin: 0; padding: 0; list-style: none; font-size: var(--ui-text-sm); color: var(--ui-muted-foreground); }
  .block-features li { display: flex; align-items: start; gap: var(--ui-space-2); }
  .block-features li::before { content: "\2713"; flex-shrink: 0; color: var(--ui-primary); font-weight: var(--ui-font-semibold); }
  .block-btn-full { inline-size: 100%; }
  .block-hint { margin: 0; color: var(--ui-muted-foreground); font-size: var(--ui-text-sm); }
</style>

Stats — band with progress

Metric cards with progress bars and trend badges.

CardProgressBadge

Downloads / month+12%
48.2k
GitHub stars+3.1%
3,214
Open issuesstable
27
---
import { Card, Badge, Progress } from "astro-ui";
---

<div class="block-canvas-grid">
  {[
    { label: "Downloads / month", value: "48.2k", progress: 72, badge: { text: "+12%", variant: "success" as const } },
    { label: "GitHub stars", value: "3,214", progress: 58, badge: { text: "+3.1%", variant: "success" as const } },
    { label: "Open issues", value: "27", progress: 18, badge: { text: "stable", variant: "info" as const } },
  ].map((stat) => (
    <Card>
      <div class="block-stat">
        <div class="block-stat-head">
          <span class="block-stat-label">{stat.label}</span>
          <Badge variant={stat.badge.variant} size="sm">{stat.badge.text}</Badge>
        </div>
        <span class="block-stat-value">{stat.value}</span>
        <Progress value={stat.progress} />
      </div>
    </Card>
  ))}
</div>

<style is:global>
  .block-canvas-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: var(--ui-space-4); }
  .block-stat { display: grid; gap: var(--ui-space-2); }
  .block-stat-head { display: flex; align-items: center; justify-content: space-between; gap: var(--ui-space-2); }
  .block-stat-label { font-size: var(--ui-text-sm); color: var(--ui-muted-foreground); }
  .block-stat-value { font-size: var(--ui-text-2xl); font-weight: var(--ui-font-semibold); letter-spacing: -0.02em; }
</style>

Stats — progress rings

KPI cards with circular progress rings — compact at-a-glance metrics.

CardProgress (circle)Badge

Storage used4.1 GB left
Build success30-day avg
CPU loadnormal
---
import { Card, Badge, Progress } from "astro-ui";
---

<div class="block-canvas-grid">
  {[
    { label: "Storage used", value: 76, badge: { text: "4.1 GB left", variant: "muted" as const }, color: "primary" as const, size: "lg" as const },
    { label: "Build success", value: 98, badge: { text: "30-day avg", variant: "success" as const }, color: "success" as const, size: "lg" as const },
    { label: "CPU load", value: 41, badge: { text: "normal", variant: "info" as const }, color: "warning" as const, size: "lg" as const },
  ].map((stat) => (
    <Card>
      <div class="block-stat block-stat--circle">
        <div class="block-stat-head">
          <span class="block-stat-label">{stat.label}</span>
          <Badge variant={stat.badge.variant} size="sm">{stat.badge.text}</Badge>
        </div>
        <Progress
          variant="circle"
          value={stat.value}
          color={stat.color}
          size={stat.size}
          label={stat.label + " progress"}
          showValue
        />
      </div>
    </Card>
  ))}
</div>

<style is:global>
  .block-canvas-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); gap: var(--ui-space-4); }
  .block-stat { display: grid; gap: var(--ui-space-2); }
  .block-stat--circle { justify-items: center; text-align: center; }
  .block-stat--circle .block-stat-head { inline-size: 100%; }
  .block-stat-head { display: flex; align-items: center; justify-content: space-between; gap: var(--ui-space-2); }
  .block-stat-label { font-size: var(--ui-text-sm); color: var(--ui-muted-foreground); }
</style>

Capital inflows summary

Fund leaderboard: part-to-whole segmented bar, headline total with trend badge, and per-fund rows with values.

CardChartBadge

Capital Inflows

$12.7M↗ $425k

CategoryWaveMark CapitalEnvato FinancesQBridge Tech
WaveMark Capital765200038791001248600
Envato Finances000
QBridge Tech000
  • WaveMark CapitalCapital In$7,652,000
  • Envato FinancesCapital In$3,879,100
  • QBridge TechCapital In$1,248,600
---
import { Card, Chart, Badge, Button, Avatar } from "astro-ui";
---

<div class="capital">
  <Card class="capital__card">
    <div class="capital__head">
      <h3 class="capital__title">Capital Inflows</h3>
      <Button variant="outline" size="sm">Top 3 Funds <span aria-hidden="true">⌄</span></Button>
    </div>
    <p class="capital__total">
      $12.7M
      <Badge variant="success" size="sm">↗ $425k</Badge>
    </p>
    <Chart
      type="hbar"
      stack
      legend={false}
      labels={["WaveMark Capital", "Envato Finances", "QBridge Tech"]}
      series={[
        { name: "WaveMark Capital", data: [7652000], color: "var(--ui-success)" },
        { name: "Envato Finances", data: [3879100], color: "var(--ui-warning)" },
        { name: "QBridge Tech", data: [1248600], color: "var(--ui-error)" },
      ]}
    />
    <ul class="capital__rows">
      {["WaveMark Capital", "Envato Finances", "QBridge Tech"].map((fund: string, i: number) => (
        <li class="capital__row">
          <Avatar name={fund} size="sm" />
          <span class="capital__fund">{fund}</span>
          <span class="capital__right">
            <span class="capital__cap">Capital In</span>
            <span class="capital__val">{["$7,652,000", "$3,879,100", "$1,248,600"][i]}</span>
          </span>
        </li>
      ))}
    </ul>
  </Card>
</div>

<style is:global>
  .capital { display: grid; justify-items: center; }
  .capital__card { inline-size: min(34rem, 100%); }
  .capital__head { display: flex; align-items: center; justify-content: space-between; gap: var(--ui-space-2); padding-block-end: var(--ui-space-2); border-block-end: 1px solid var(--ui-border); }
  .capital__title { margin: 0; color: var(--ui-foreground); font-size: var(--ui-text-md); font-weight: var(--ui-font-semibold); }
  .capital__total { display: flex; align-items: center; gap: var(--ui-space-2); margin: var(--ui-space-3) 0 var(--ui-space-2); color: var(--ui-foreground); font-size: 1.75rem; line-height: 1.1; font-weight: var(--ui-font-semibold); font-variant-numeric: tabular-nums; }
  .capital__rows { display: grid; margin: var(--ui-space-3) 0 0; padding: 0; list-style: none; }
  .capital__row { display: flex; align-items: center; gap: var(--ui-space-2); padding: var(--ui-space-2) 0; }
  .capital__row + .capital__row { border-block-start: 1px solid var(--ui-border); }
  .capital__fund { color: var(--ui-foreground); font-size: var(--ui-text-md); font-weight: var(--ui-font-medium); }
  .capital__right { display: grid; justify-items: end; margin-inline-start: auto; }
  .capital__cap { color: var(--ui-muted-foreground); font-size: var(--ui-text-xs); }
  .capital__val { color: var(--ui-foreground); font-size: var(--ui-text-md); font-variant-numeric: tabular-nums; }
</style>

CTA band

Full-width conversion band with gradient atmosphere.

BadgeButton

v0.1 — first release

Ship your next Astro site faster

Install once, import tokens, compose pages from blocks like this one.

---
import { Badge, Button } from "astro-ui";
---

<div class="block-cta">
  <Badge variant="muted">v0.1 — first release</Badge>
  <h2>Ship your next Astro site faster</h2>
  <p>Install once, import tokens, compose pages from blocks like this one.</p>
  <div class="block-cta-actions">
    <Button href="/docs/get-started/">Get started</Button>
    <Button href="/components/" variant="outline">Components</Button>
  </div>
</div>

<style is:global>
  .block-cta {
    display: grid;
    gap: var(--ui-space-4);
    justify-items: center;
    text-align: center;
    padding: var(--ui-space-10) var(--ui-space-6);
    border: 1px solid var(--ui-border);
    border-radius: var(--ui-radius-xl, var(--ui-radius-lg));
    background: radial-gradient(
      120% 140% at 50% 0%,
      color-mix(in srgb, var(--ui-primary) 14%, var(--ui-background)),
      var(--ui-background)
    );
  }
  .block-cta h2 { margin: 0; max-width: 24ch; font-size: var(--ui-text-2xl); letter-spacing: -0.02em; }
  .block-cta p { margin: 0; max-width: 52ch; color: var(--ui-muted-foreground); }
  .block-cta-actions { display: flex; flex-wrap: wrap; gap: var(--ui-space-3); justify-content: center; }
</style>