Hero manifiesto tipográfico
Manifiesto de dos líneas en terracota, regla que se despliega y cierre editorial; sin imágenes ni efectos continuos.
Lo esencial.Lo extraordinario.
Ideas claras. Decisiones valientes. Trabajo que tiene algo que decir.
Conoce el estudioEstudio de muestra · edición abierta
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import { type CSSProperties } from "react";
/** Hero manifiesto tipográfico. React + TypeScript, sin dependencias. Personaliza con variables --gcym-*. */
export type HeroManifiestoProps = {
lineOne?: string;
lineTwo?: string;
description?: string;
label?: string;
href?: string;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gcym-root { box-sizing: border-box; min-width: 0; max-width: 100%; color: var(--gcym-fg, #202421); font: 400 15px/1.5 ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
.gcym-root *, .gcym-root *::before, .gcym-root *::after { box-sizing: border-box; }
.gcym-root button, .gcym-root input, .gcym-root textarea, .gcym-root select { font: inherit; }
.gcym-root button, .gcym-root a { -webkit-tap-highlight-color: transparent; }
.gcym-root :focus-visible { outline: 2px solid var(--gcym-accent, #25724b); outline-offset: 4px; }
.gcym-root ::selection { background: var(--gcym-accent, #25724b); color: #fff; }
.gcym-root button:disabled { opacity: .5; cursor: not-allowed; }
.gcym-root svg { flex-shrink: 0; }
@media (prefers-reduced-motion: reduce) { .gcym-root *, .gcym-root *::before, .gcym-root *::after { animation: none !important; transition-duration: .01ms !important; scroll-behavior: auto !important; } }
.gcym-root { width:100%; background:var(--gcym-bg,#d55d3b); color:var(--gcym-fg,#2f201b); padding:64px clamp(24px,6vw,76px) 28px; container-type:inline-size; }
.gcym-root h2 { font-size:clamp(42px,7vw,96px); line-height:1.04; font-weight:650; letter-spacing:-.04em; margin:0; }
.gcym-root h2 span { display:block; overflow-wrap:anywhere; }
.gcym-root h2 span+span { color:#f9e7d9; margin-top:8px; animation:gcym-arrive .8s cubic-bezier(.16,1,.3,1) both; }
.gcym-rule { height:1px; background:#6a301e; margin:42px 0 28px; transform-origin:left; animation:gcym-rule .9s cubic-bezier(.16,1,.3,1); }
.gcym-bottom { display:flex; gap:30px; justify-content:space-between; align-items:flex-end; }
.gcym-bottom p { font-size:18px; line-height:1.55; max-width:30ch; margin:0; }
.gcym-bottom a { display:flex; gap:22px; align-items:center; color:#2f201b; font-size:14px; text-decoration:none; padding:8px 0; border-bottom:1px solid #6a301e; }
.gcym-bottom a svg { transition:transform .3s; }
.gcym-bottom a:hover svg { transform:translate(3px,-3px); }
.gcym-note { font-size:11px; margin:50px 0 0; color:#522c21; }
@keyframes gcym-arrive { from { transform:translateY(18px); opacity:.5; } to { transform:none; opacity:1; } }
@keyframes gcym-rule { from { transform:scaleX(.1); } to { transform:scaleX(1); } }
@container(max-width:560px) { .gcym-root h2 { font-size:42px; }
.gcym-bottom { flex-direction:column; align-items:flex-start; }
.gcym-bottom p { font-size:16px; } }`;
export function HeroManifiesto({
lineOne = "Lo esencial.",
lineTwo = "Lo extraordinario.",
description = "Ideas claras. Decisiones valientes. Trabajo que tiene algo que decir.",
label = "Conoce el estudio",
href = "#estudio",
className = "",
style,
}: HeroManifiestoProps) {
return (
<section className={`gcym-root ${className}`} style={style}>
<style>{CSS}</style>
<h2>
<span>{lineOne}</span>
<span>{lineTwo}</span>
</h2>
<div className="gcym-rule" aria-hidden="true" />
<div className="gcym-bottom">
<p>{description}</p>
<a href={href}>
<span>{label}</span>
<svg
width="36"
height="36"
viewBox="0 0 48 48"
fill="none"
stroke="currentColor"
strokeWidth="1.3"
aria-hidden="true"
>
<path d="M10 38 38 10M10 10h28v28" />
</svg>
</a>
</div>
<p className="gcym-note">Estudio de muestra · edición abierta</p>
</section>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/hero-manifiestoEjemplo de uso de Hero manifiesto tipográfico
Después de copiar hero-manifiesto.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { HeroManifiesto } from "./hero-manifiesto";
export default function Ejemplo() {
return <HeroManifiesto lineOne="Ejemplo" />;
}Propiedades de HeroManifiesto
HeroManifiesto acepta 7 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
lineOne? | string | Opcional. |
lineTwo? | string | Opcional. |
description? | string | Opcional. |
label? | string | Opcional. |
href? | string | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Personaliza Hero manifiesto tipográfico con variables CSS
Define estas variables en el contenedor o en tu hoja de estilos para cambiar los colores sin tocar el componente. Si no las defines, se usa el valor por defecto.
| Variable | Valor por defecto |
|---|---|
--gcym-fg | #202421 |
--gcym-accent | #25724b |
--gcym-bg | #d55d3b |
Accesibilidad y rendimiento
El archivo tiene 81 líneas (4 KB) y define 2 animaciones con @keyframes. Esto es lo que hace Hero manifiesto tipográfico 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-*.
- Es un componente de cliente de Next.js: incluye la directiva "use client".