Hero de aurora
Oscuro y centrado, con auroras en movimiento y un suelo en perspectiva.
Construye más rápido con menos herramientas.
Una plataforma para equipos que prefieren enviar a configurar. Todo lo esencial, nada de lo que sobra.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
/**
* Hero oscuro y centrado con auroras de color en movimiento y un suelo de cuadrícula en perspectiva que avanza hacia el horizonte.
* Solo CSS. Con movimiento reducido las auroras y el suelo se quedan quietos.
*
* <AuroraHero
* announcement={{ label: "Nuevo", text: "Ya disponible la versión 2", href: "/novedades" }}
* title="Construye más rápido con menos herramientas."
* description="Una plataforma para equipos que prefieren enviar a configurar."
* primary={{ label: "Empezar ahora", href: "/registro" }}
* secondary={{ label: "Ver cómo funciona", href: "#demo" }}
* />
*/
import type { CSSProperties } from "react";
type Cta = { label: string; href: string };
export type AuroraHeroProps = {
announcement?: { label: string; text: string; href: string };
title?: string;
description?: string;
primary?: Cta;
secondary?: Cta;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gcha-root { position: relative; isolation: isolate; display: grid; place-items: center; box-sizing: border-box; min-height: 640px; overflow: hidden; padding: clamp(40px, 7vw, 96px) clamp(20px, 5vw, 64px) clamp(120px, 16vw, 200px); background: #05050d; color: #f6f6fb; text-align: center; font-family: inherit; }
.gcha-blob { position: absolute; z-index: -2; border-radius: 50%; filter: blur(90px); opacity: .55; will-change: transform; }
.gcha-blob:nth-child(1) { top: -25%; left: 8%; width: 46vw; height: 46vw; max-width: 640px; max-height: 640px; background: #5b36f2; animation: gcha-a 16s ease-in-out infinite alternate; }
.gcha-blob:nth-child(2) { top: -12%; right: 4%; width: 38vw; height: 38vw; max-width: 520px; max-height: 520px; background: #e8479b; animation: gcha-b 20s ease-in-out infinite alternate; }
.gcha-blob:nth-child(3) { top: 14%; left: 36%; width: 30vw; height: 30vw; max-width: 420px; max-height: 420px; background: #1ca7ec; opacity: .38; animation: gcha-c 18s ease-in-out infinite alternate; }
.gcha-floor { position: absolute; z-index: -1; left: -40%; right: -40%; bottom: -6%; height: 52%; background-image: linear-gradient(rgba(150, 130, 255, .42) 1px, transparent 1px), linear-gradient(90deg, rgba(150, 130, 255, .42) 1px, transparent 1px); background-size: 72px 72px;
transform: perspective(520px) rotateX(64deg); transform-origin: 50% 100%; -webkit-mask-image: linear-gradient(to top, #000 8%, transparent 80%); mask-image: linear-gradient(to top, #000 8%, transparent 80%); animation: gcha-floor 2.6s linear infinite; }
.gcha-horizon { position: absolute; z-index: -1; left: 50%; bottom: 0; width: 120%; height: 38%; transform: translateX(-50%); background: radial-gradient(50% 100% at 50% 100%, rgba(140, 110, 255, .55), transparent 70%); }
.gcha-pill { display: inline-flex; align-items: center; gap: 10px; padding: 6px 16px 6px 6px; border: 1px solid rgba(255, 255, 255, .16); border-radius: 999px; background: rgba(255, 255, 255, .06); color: #d9d9ee; font-size: 14px; text-decoration: none; transition: background-color .25s, border-color .25s; }
.gcha-pill:hover { border-color: rgba(255, 255, 255, .35); background: rgba(255, 255, 255, .1); }
.gcha-pill b { padding: 3px 10px; border-radius: 999px; background: #fff; color: #17132f; font-size: 12px; font-weight: 700; }
.gcha-title { margin: 26px auto 0; max-width: 15ch; font-size: clamp(40px, 6.6vw, 92px); font-weight: 700; line-height: 1.02; letter-spacing: -.045em; text-wrap: balance; }
.gcha-desc { margin: 22px auto 0; max-width: 48ch; color: #adadc4; font-size: clamp(16px, 1.5vw, 20px); line-height: 1.6; }
.gcha-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; margin-top: 34px; }
.gcha-btn { display: inline-flex; align-items: center; min-height: 52px; padding: 0 28px; border-radius: 999px; font-size: 16px; font-weight: 600; text-decoration: none; transition: transform .3s cubic-bezier(.16, 1, .3, 1), background-color .25s, border-color .25s; }
.gcha-btn:hover { transform: translateY(-2px); }
.gcha-btn[data-kind="primary"] { background: #fff; color: #120f2b; box-shadow: 0 0 0 0 rgba(255, 255, 255, .5), 0 12px 40px -10px rgba(120, 90, 255, .8); }
.gcha-btn[data-kind="ghost"] { border: 1px solid rgba(255, 255, 255, .22); color: #ececf8; }
.gcha-btn[data-kind="ghost"]:hover { border-color: rgba(255, 255, 255, .5); background: rgba(255, 255, 255, .06); }
.gcha-btn:focus-visible, .gcha-pill:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
@keyframes gcha-a { to { transform: translate(14vw, 12vw) scale(1.15); } }
@keyframes gcha-b { to { transform: translate(-16vw, 10vw) scale(.9); } }
@keyframes gcha-c { to { transform: translate(-8vw, -6vw) scale(1.2); } }
@keyframes gcha-floor { to { background-position: 0 72px; } }
@media (prefers-reduced-motion: reduce) { .gcha-blob, .gcha-floor { animation: none; } }
`;
export function AuroraHero({
announcement = { label: "Nuevo", text: "Ya disponible la versión 2", href: "#novedades" },
title = "Construye más rápido con menos herramientas.",
description = "Una plataforma para equipos que prefieren enviar a configurar. Todo lo esencial, nada de lo que sobra.",
primary = { label: "Empezar ahora", href: "#registro" },
secondary = { label: "Ver cómo funciona", href: "#demo" },
className,
style,
}: AuroraHeroProps) {
return (
<>
<style>{CSS}</style>
<section className={["gcha-root", className].filter(Boolean).join(" ")} style={style}>
<span className="gcha-blob" aria-hidden="true" /><span className="gcha-blob" aria-hidden="true" /><span className="gcha-blob" aria-hidden="true" />
<span className="gcha-floor" aria-hidden="true" /><span className="gcha-horizon" aria-hidden="true" />
<div>
<a className="gcha-pill" href={announcement.href}><b>{announcement.label}</b>{announcement.text}</a>
<h1 className="gcha-title">{title}</h1>
<p className="gcha-desc">{description}</p>
<div className="gcha-actions">
<a className="gcha-btn" data-kind="primary" href={primary.href}>{primary.label}</a>
<a className="gcha-btn" data-kind="ghost" href={secondary.href}>{secondary.label}</a>
</div>
</div>
</section>
</>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/hero-auroraEjemplo de uso de Hero de aurora
Después de copiar aurora-hero.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { AuroraHero } from "./aurora-hero";
export default function Ejemplo() {
return <AuroraHero title="Ejemplo" />;
}Propiedades de AuroraHero
AuroraHero acepta 7 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
announcement? | { label: string; text: string; href: string } | Opcional. |
title? | string | Opcional. |
description? | string | Opcional. |
primary? | Cta | Opcional. |
secondary? | Cta | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Accesibilidad y rendimiento
El archivo tiene 84 líneas (6 KB) y define 4 animaciones con @keyframes. Esto es lo que hace Hero de aurora por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Muestra un anillo de foco visible al navegar con teclado (:focus-visible).
- Expone su estado a tecnologías de apoyo con atributos aria-*.
Acerca del producto
Un hero oscuro y centrado: tres manchas de color desenfocadas que se desplazan, un suelo de cuadrícula en perspectiva que avanza hacia el horizonte con un resplandor, una insignia de anuncio y dos botones.
Incluye
Una sección completa en un solo archivo React + TypeScript, con los estilos dentro. No usa Tailwind ni bibliotecas externas.
- Auroras y suelo animados solo con CSS
- Insignia de anuncio enlazable
- Botón principal y secundario
- Se detiene con movimiento reducido
- Sin JavaScript
Cómo usarlo
Pasa announcement, title, description, primary y secondary. Los colores de las auroras se cambian en el CSS del archivo.