1 estrella en GitHub = 1 componente nuevo.

Dar una estrella
Secciones Hero

Hero Dashboard Preview

Hero SaaS con maqueta de dashboard en vivo construida con tarjetas KPI y gráfico de líneas del kit.

herosaasdashboardmockupcharts
Vista Previa en Vivo
Analytics, reimagined

See every metric that matters, in real time

Unified revenue, product and infrastructure dashboards. Set up in minutes, no SQL required.

Revenue

+9.2%

$128.4k

vs last month

Active users

+4.1%

24,812

vs last month

Churn

−0.6%

2.3%

vs last month
Revenue by channel

Last 12 weeks

  • Web
  • Mobile
02k4k6k8kW1W3W5W7W9W11
View data
PeriodWebMobile
W14.2k2.1k
W24.6k2.4k
W34.4k2.6k
W45k2.5k
W55.4k3k
W65.2k3.3k
W75.9k3.2k
W86.1k3.6k
W96k3.9k
W106.7k4.2k
W117k4.1k
W127.4k4.6k

Uso

Copia y pega este código directamente en tu componente React:

tsx
import { HeroDashboardPreview } from 'react-component-kit-ui/sections';

<HeroDashboardPreview title="See every metric that matters" primary={{ label: 'Start free trial', href: '/signup' }} variant="floating" />

Instalación Manual

Si no estás usando el paquete npm, crea un archivo nuevo y pega el siguiente código: src/components/sections/HeroDashboardPreview.tsx + HeroDashboardPreview.css:

HeroDashboardPreview.tsx
'use client';

import LineChart from '../charts/LineChart';
import KpiStatTile from '../charts/KpiStatTile';
import './HeroDashboardPreview.css';

/**
 * HeroDashboardPreview — SaaS hero with headline, CTAs and a live-rendered
 * product dashboard mockup built from the kit's own SVG charts.
 *
 * @param {string} badge - Eyebrow badge.
 * @param {string} title - Headline.
 * @param {string} subtitle - Supporting paragraph.
 * @param {{label: string, href: string}} primary - Primary CTA.
 * @param {{label: string, href: string}} secondary - Secondary CTA.
 * @param {string} variant - Mockup frame (browser|floating|flat).
 * @param {string} size - Vertical rhythm (sm|md|lg).
 * @param {string} className - Extra CSS class.
 */
export interface HeroDashboardPreviewProps {
  badge?: string;
  title?: string;
  subtitle?: string;
  primary?: { label: string; href: string };
  secondary?: { label: string; href: string };
  variant?: 'browser' | 'floating' | 'flat';
  size?: 'sm' | 'md' | 'lg';
  className?: string;
}

export function HeroDashboardPreview({
  badge = 'Analytics, reimagined',
  title = 'See every metric that matters, in real time',
  subtitle = 'Unified revenue, product and infrastructure dashboards. Set up in minutes, no SQL required.',
  primary = { label: 'Start free trial', href: '#' },
  secondary = { label: 'Book a demo', href: '#' },
  variant = 'browser',
  size = 'md',
  className = '',
}: HeroDashboardPreviewProps) {
  const id = `hdp-${Math.random().toString(36).slice(2, 8)}`;
  return (
    <>
      <div className="cq-hero-dashboard-preview-cq" data-rk-d7155c="">
      <section className={`hdp hdp--${variant} hdp--${size} ${className}`} aria-labelledby={id} data-rk-d7155c="">
        <div className="hdp__glow" aria-hidden="true" data-rk-d7155c=""></div>
        <div className="hdp__copy" data-rk-d7155c="">
          <span className="hdp__badge" data-rk-d7155c="">{badge}</span>
          <h1 id={id} className="hdp__title" data-rk-d7155c="">{title}</h1>
          <p className="hdp__subtitle" data-rk-d7155c="">{subtitle}</p>
          <div className="hdp__actions" data-rk-d7155c="">
            <a className="hdp__btn hdp__btn--primary" href={primary.href} data-rk-d7155c="">{primary.label}</a>
            <a className="hdp__btn hdp__btn--ghost" href={secondary.href} data-rk-d7155c="">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true" data-rk-d7155c=""><circle cx="12" cy="12" r="10" data-rk-d7155c="" /><path d="m10 8 6 4-6 4V8z" fill="currentColor" data-rk-d7155c="" /></svg>
              {secondary.label}
            </a>
          </div>
        </div>
      
        <div className="hdp__mock" role="group" aria-label="Product dashboard preview" data-rk-d7155c="">
          {variant === 'browser' && (
            <div className="hdp__chrome" aria-hidden="true" data-rk-d7155c="">
              <span data-rk-d7155c=""></span><span data-rk-d7155c=""></span><span data-rk-d7155c=""></span>
              <p data-rk-d7155c="">app.example.com/overview</p>
            </div>
          )}
          <div className="hdp__screen" data-rk-d7155c="">
            <div className="hdp__kpis" data-rk-d7155c="">
              <KpiStatTile label="Revenue" value="$128.4k" change={9.2} period="vs last month" size="sm" variant="solid" trend={[80, 84, 90, 88, 96, 102, 110, 118, 128]} />
              <KpiStatTile label="Active users" value="24,812" change={4.1} period="vs last month" size="sm" variant="solid" trend={[20, 21, 21.5, 22, 22.8, 23.1, 23.9, 24.2, 24.8]} />
              <KpiStatTile label="Churn" value="2.3%" change={-0.6} invert period="vs last month" size="sm" variant="solid" trend={[3.1, 3, 2.9, 2.8, 2.7, 2.6, 2.5, 2.4, 2.3]} />
            </div>
            <LineChart title="Revenue by channel" subtitle="Last 12 weeks" variant="solid" size="sm" height={220} />
          </div>
        </div>
      </section>
      </div>
    </>
  );
}

export default HeroDashboardPreview;
HeroDashboardPreview.css
/* HeroDashboardPreview — ported from astro-component-kit (sections/HeroDashboardPreview.astro) */

.cq-hero-dashboard-preview-cq:where([data-rk-d7155c]) { container-type: inline-size; }
.hdp:where([data-rk-d7155c]) {
  --hdp-py: 5.5rem;
  position: relative;
  overflow: hidden;
  padding: var(--hdp-py) var(--sp-6, 1.5rem) 0;
  background: var(--c-bg, #050505);
}
.hdp--sm:where([data-rk-d7155c]) { --hdp-py: 3.5rem; }
.hdp--lg:where([data-rk-d7155c]) { --hdp-py: 7.5rem; }
.hdp__glow:where([data-rk-d7155c]) {
  position: absolute;
  top: 30%;
  left: 50%;
  width: 900px;
  height: 600px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse, rgba(57, 135, 229, 0.16), transparent 65%);
  filter: blur(40px);
  pointer-events: none;
}
.hdp__copy:where([data-rk-d7155c]) { position: relative; max-width: 760px; margin: 0 auto 3.5rem; text-align: center; }
.hdp__badge:where([data-rk-d7155c]) {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: var(--r-full, 999px);
  background: rgba(57, 135, 229, 0.12);
  border: 1px solid rgba(57, 135, 229, 0.3);
  color: #a9cdf7;
  font-size: 0.8125rem;
  font-weight: 600;
}
.hdp__title:where([data-rk-d7155c]) {
  margin: 1.4rem 0 1rem;
  font-size: clamp(2.25rem, 5.5vw, 3.75rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.06;
  color: var(--c-text-1, #fff);
  text-wrap: balance;
}
.hdp__subtitle:where([data-rk-d7155c]) { margin: 0 auto 2rem; max-width: 560px; font-size: 1.0625rem; line-height: 1.6; color: var(--c-text-2, #a3a3a3); }
.hdp__actions:where([data-rk-d7155c]) { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; }
.hdp__btn:where([data-rk-d7155c]) {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 48px;
  padding: 0 1.5rem;
  border-radius: var(--r-md, 12px);
  font-weight: 650;
  text-decoration: none;
  transition: transform 0.2s ease, background 0.2s ease;
}
.hdp__btn:hover:where([data-rk-d7155c]) { transform: translateY(-1px); }
.hdp__btn:focus-visible:where([data-rk-d7155c]) { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 3px; }
.hdp__btn--primary:where([data-rk-d7155c]) { background: var(--chart-1, #3987e5); color: #fff; }
.hdp__btn--primary:hover:where([data-rk-d7155c]) { background: #5598e7; color: #fff; }
.hdp__btn--ghost:where([data-rk-d7155c]) { color: var(--c-text-1, #fff); border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.14); }
.hdp__btn--ghost:hover:where([data-rk-d7155c]) { border-color: rgb(var(--ink-rgb, 255 255 255) / 0.3); color: var(--c-text-1, #fff); }

.hdp__mock:where([data-rk-d7155c]) {
  position: relative;
  max-width: 1080px;
  margin: 0 auto;
  border-radius: var(--r-xl, 24px) var(--r-xl, 24px) 0 0;
  border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1);
  border-bottom: 0;
  background: #0a0a0c;
  overflow: hidden;
  mask-image: linear-gradient(to bottom, #000 70%, transparent);
}
.hdp--floating:where([data-rk-d7155c]) .hdp__mock:where([data-rk-d7155c]) {
  border-radius: var(--r-xl, 24px);
  border-bottom: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1);
  margin-bottom: var(--hdp-py);
  mask-image: none;
  transform: perspective(1600px) rotateX(8deg);
  box-shadow: 0 60px 120px -40px rgba(57, 135, 229, 0.35);
}
.hdp--flat:where([data-rk-d7155c]) .hdp__mock:where([data-rk-d7155c]) { background: transparent; border-color: transparent; }
.hdp__chrome:where([data-rk-d7155c]) {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.8rem 1rem;
  border-bottom: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.06);
}
.hdp__chrome:where([data-rk-d7155c]) span:where([data-rk-d7155c]) { width: 10px; height: 10px; border-radius: 50%; background: rgb(var(--ink-rgb, 255 255 255) / 0.12); }
.hdp__chrome:where([data-rk-d7155c]) p:where([data-rk-d7155c]) {
  margin: 0 auto;
  padding: 0.25rem 1rem;
  border-radius: 6px;
  background: rgb(var(--ink-rgb, 255 255 255) / 0.04);
  font-size: 0.75rem;
  color: var(--c-text-3, #737373);
}
.hdp__screen:where([data-rk-d7155c]) { display: grid; gap: 1rem; padding: 1.25rem; }
.hdp__kpis:where([data-rk-d7155c]) { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1rem; }
@container (max-width: 760px) {
  .hdp__kpis:where([data-rk-d7155c]) { grid-template-columns: 1fr; }
  .hdp__kpis:where([data-rk-d7155c]) > *:nth-child(n + 2) { display: none; }
  .hdp--floating:where([data-rk-d7155c]) .hdp__mock:where([data-rk-d7155c]) { transform: none; }
}