Ir al contenido
Evaluar mi proyecto
Componentes · HerosDisponible

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 estudio

Estudio de muestra · edición abierta

Demostración interactiva

Código completo

Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.

hero-manifiesto.tsx81 líneas
Descargar
"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.

terminal.sh1 líneas
npx shadcn@latest add https://www.gassierconsulting.com/r/hero-manifiesto

Ejemplo 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.

ejemplo.tsx5 líneas
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.

PropiedadTipoDescripción
lineOne?stringOpcional.
lineTwo?stringOpcional.
description?stringOpcional.
label?stringOpcional.
href?stringOpcional.
className?stringOpcional.
style?CSSPropertiesOpcional.

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.

VariableValor 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".
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React 18 y 19 · Next.js (componente de cliente)