Ir al contenido
Evaluar mi proyecto
Componentes · HerosDisponible

Hero de paneles cromáticos

Hero de tres paneles que expanden su composición al seleccionar, enfocar y tocar; formas geométricas y paleta cálida.

Una buena idea cambia el paisaje.

Diseño que sale de la pantalla y mueve tu próximo proyecto.

Descubrir proyectos

Color · composición interactiva de muestra

Código completo

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

hero-paneles.tsx103 líneas
Descargar
"use client";

import { useState, type CSSProperties } from "react";

/** Hero de paneles cromáticos. React + TypeScript, sin dependencias. Personaliza con variables --gcyp-*. */
export type HeroPanelesProps = {
  title?: string;
  description?: string;
  label?: string;
  href?: string;
  className?: string;
  style?: CSSProperties;
};

const CSS = `
.gcyp-root { box-sizing: border-box; min-width: 0; max-width: 100%; color: var(--gcyp-fg, #202421); font: 400 15px/1.5 ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; }
.gcyp-root *, .gcyp-root *::before, .gcyp-root *::after { box-sizing: border-box; }
.gcyp-root button, .gcyp-root input, .gcyp-root textarea, .gcyp-root select { font: inherit; }
.gcyp-root button, .gcyp-root a { -webkit-tap-highlight-color: transparent; }
.gcyp-root :focus-visible { outline: 2px solid var(--gcyp-accent, #25724b); outline-offset: 4px; }
.gcyp-root ::selection { background: var(--gcyp-accent, #25724b); color: #fff; }
.gcyp-root button:disabled { opacity: .5; cursor: not-allowed; }
.gcyp-root svg { flex-shrink: 0; }
@media (prefers-reduced-motion: reduce) { .gcyp-root *, .gcyp-root *::before, .gcyp-root *::after { animation: none !important; transition-duration: .01ms !important; scroll-behavior: auto !important; } }
.gcyp-root { container-type:inline-size; width:100%; background:var(--gcyp-bg,#f6f0e9); padding:48px clamp(24px,5vw,64px) 28px; }
.gcyp-copy { display:flex; align-items:flex-end; gap:30px; flex-wrap:wrap; margin-bottom:40px; }
.gcyp-copy h2 { font-size:clamp(36px,5vw,60px); letter-spacing:-.035em; line-height:1.08; font-weight:600; max-width:14ch; margin:0; text-wrap:balance; }
.gcyp-copy p { flex:1; min-width:180px; max-width:26ch; font-size:14px; color:#635347; margin:0; }
.gcyp-copy a { display:flex; align-items:center; gap:18px; min-height:44px; color:#302821; text-decoration:none; border-bottom:1px solid #928073; font-size:12px; font-weight:600; }
.gcyp-panels { display:flex; height:260px; gap:10px; }
.gcyp-panel { position:relative; overflow:hidden; flex:1; border:0; border-radius:10px; cursor:pointer; min-width:0; padding:0; transition:flex .6s cubic-bezier(.16,1,.3,1); }
.gcyp-panel[aria-pressed="true"] { flex:2.3; }
.gcyp-panel-0 { background:#bbd0ae; color:#27432b; }
.gcyp-panel-1 { background:#e7a27e; color:#65371f; }
.gcyp-panel-2 { background:#cac2e4; color:#44325f; }
.gcyp-shape { position:absolute; width:200px; height:200px; border:1px solid currentColor; top:30px; left:50%; transform:translateX(-50%) rotate(35deg); transition:transform .6s cubic-bezier(.16,1,.3,1); }
.gcyp-panel-1 .gcyp-shape { border-radius:50%; box-shadow:inset 0 0 0 32px #e7a27e,inset 0 0 0 33px currentColor; }
.gcyp-panel-2 .gcyp-shape { border-radius:100px 100px 0 0; }
.gcyp-panel[aria-pressed="true"] .gcyp-shape { transform:translateX(-50%) rotate(0); }
.gcyp-name { position:absolute; bottom:20px; left:20px; font-size:14px; font-weight:600; }
.gcyp-note { margin:18px 0 0; font-size:11px; color:#6f5b4b; }
@container(max-width:580px) { .gcyp-copy { align-items:flex-start; flex-direction:column; gap:20px; }
.gcyp-copy h2 { font-size:40px; }
.gcyp-panels { height:220px; gap:6px; }
.gcyp-name { left:10px; bottom:15px; font-size:11px; }
.gcyp-shape { width:150px; height:150px; } }`;

export function HeroPaneles({
  title = "Una buena idea cambia el paisaje.",
  description = "Diseño que sale de la pantalla y mueve tu próximo proyecto.",
  label = "Descubrir proyectos",
  href = "#proyectos",
  className = "",
  style,
}: HeroPanelesProps) {
  const [selected, setSelected] = useState(1);
  const names = ["Forma", "Color", "Movimiento"];
  return (
    <section className={`gcyp-root ${className}`} style={style}>
      <style>{CSS}</style>
      <div className="gcyp-copy">
        <h2>{title}</h2>
        <p>{description}</p>
        <a href={href}>
          {label}
          <svg
            width="18"
            height="18"
            viewBox="0 0 24 24"
            fill="none"
            stroke="currentColor"
            strokeWidth="1.5"
            aria-hidden="true"
          >
            <path d="M5 12h14m-6-6 6 6-6 6" />
          </svg>
        </a>
      </div>
      <div className="gcyp-panels" aria-label="Explorar composiciones">
        {names.map((name, i) => (
          <button
            type="button"
            key={name}
            aria-pressed={i === selected}
            aria-label={`Explorar ${name.toLowerCase()}`}
            onClick={() => setSelected(i)}
            onPointerEnter={(e) => {
              if (e.pointerType === "mouse") setSelected(i);
            }}
            className={`gcyp-panel gcyp-panel-${i}`}
          >
            <span className="gcyp-shape" aria-hidden="true" />
            <span className="gcyp-name">{name}</span>
          </button>
        ))}
      </div>
      <p className="gcyp-note" role="status">
        {names[selected]} · composición interactiva de muestra
      </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-paneles

Ejemplo de uso de Hero de paneles cromáticos

Después de copiar hero-paneles.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.

ejemplo.tsx5 líneas
import { HeroPaneles } from "./hero-paneles";

export default function Ejemplo() {
  return <HeroPaneles title="Ejemplo" />;
}

Propiedades de HeroPaneles

HeroPaneles acepta 6 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.

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

Personaliza Hero de paneles cromáticos 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
--gcyp-fg#202421
--gcyp-accent#25724b
--gcyp-bg#f6f0e9

Accesibilidad y rendimiento

El archivo tiene 103 líneas (5 KB) y no necesita @keyframes. Esto es lo que hace Hero de paneles cromáticos 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).
  • Declara roles ARIA para lectores de pantalla: status.
  • 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)