Hero neobrutalista en bento
Cajas de colores planos con borde grueso y sombra dura, cinta que corre y piezas que se hunden al pulsar.
Haz cosas que se noten
Una caja para cada idea, bordes que no piden perdón y botones que se sienten. Sin gradientes tímidos.
Empieza yaCódigo completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import type { CSSProperties } from "react";
/** Hero neobrutalista en bento: cajas de colores planos con borde grueso y sombra dura, una cinta que corre y piezas que se hunden al pulsar. React + TypeScript, sin dependencias. */
export type HeroNeobrutalBentoProps = {
title?: string;
description?: string;
cta?: string;
href?: string;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gchnb-root { box-sizing: border-box; position: relative; container-type: inline-size; width: 100%; min-height: 620px; overflow: hidden; padding: clamp(16px, 4cqi, 48px); background: #fff4d1; color: #111; font: 700 16px/1.4 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif; }
.gchnb-root *, .gchnb-root *::before, .gchnb-root *::after { box-sizing: border-box; }
.gchnb-root a { -webkit-tap-highlight-color: transparent; }
.gchnb-root :focus-visible { outline: 4px solid #2f5bff; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .gchnb-root *, .gchnb-root *::before, .gchnb-root *::after { animation: none !important; transition-duration: .01ms !important; } }
.gchnb-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); grid-auto-rows: minmax(120px, auto); gap: 18px; }
.gchnb-box { position: relative; padding: 22px; border: 4px solid #111; background: var(--c, #fff); box-shadow: 8px 8px 0 #111; transition: transform .12s, box-shadow .12s; }
.gchnb-box:hover { transform: translate(4px, 4px); box-shadow: 4px 4px 0 #111; }
.gchnb-main { grid-column: span 4; grid-row: span 2; display: grid; align-content: center; gap: 18px; --c: #ff90e8; }
.gchnb-title { margin: 0; font: 900 clamp(38px, 7.4cqi, 92px)/.92 ui-sans-serif, system-ui, -apple-system, sans-serif; letter-spacing: -.045em; text-transform: uppercase; text-wrap: balance; }
.gchnb-desc { margin: 0; max-width: 40ch; font-weight: 600; font-size: clamp(15px, 1.8cqi, 19px); }
.gchnb-cta { justify-self: start; display: inline-flex; align-items: center; min-height: 54px; padding: 0 26px; border: 4px solid #111; background: #fff; color: #111; font-weight: 900; text-transform: uppercase; letter-spacing: .04em; text-decoration: none; box-shadow: 5px 5px 0 #111; transition: transform .1s, box-shadow .1s, background .1s; }
.gchnb-cta:hover { background: #ffe14d; }
.gchnb-cta:active { transform: translate(5px, 5px); box-shadow: 0 0 0 #111; }
.gchnb-stat { grid-column: span 2; --c: #7cf5c3; display: grid; align-content: space-between; }
.gchnb-stat b { font: 900 clamp(42px, 6cqi, 72px)/1 ui-sans-serif, system-ui, sans-serif; letter-spacing: -.05em; }
.gchnb-sticker { grid-column: span 2; --c: #ffe14d; display: grid; place-items: center; text-align: center; font: 900 24px/1.1 ui-sans-serif, system-ui, sans-serif; text-transform: uppercase; transform: rotate(-3deg); }
.gchnb-sticker:hover { transform: rotate(2deg) translate(4px, 4px); }
.gchnb-tape { grid-column: 1 / -1; padding: 0; overflow: hidden; background: #111; color: #ffe14d; display: flex; }
.gchnb-tape:hover { transform: none; box-shadow: 8px 8px 0 #111; }
.gchnb-run { display: flex; flex-shrink: 0; gap: 36px; padding: 14px 18px; white-space: nowrap; font: 900 22px/1 ui-sans-serif, system-ui, sans-serif; text-transform: uppercase; letter-spacing: .04em; animation: gchnb-run 18s linear infinite; }
@container (max-width: 760px) { .gchnb-main { grid-column: 1 / -1; } .gchnb-stat, .gchnb-sticker { grid-column: span 3; } }
@keyframes gchnb-run { to { transform: translateX(-100%); } }`;
export function HeroNeobrutalBento({ title = "Haz cosas que se noten", description = "Una caja para cada idea, bordes que no piden perdón y botones que se sienten. Sin gradientes tímidos.", cta = "Empieza ya", href = "#", className = "", style }: HeroNeobrutalBentoProps) {
const words = ["Diseño sin miedo", "Código limpio", "Entrega semanal", "Cero relleno"];
return (
<section className={`gchnb-root ${className}`} style={style}>
<style>{CSS}</style>
<div className="gchnb-grid">
<div className="gchnb-box gchnb-main">
<h1 className="gchnb-title">{title}</h1>
<p className="gchnb-desc">{description}</p>
<a className="gchnb-cta" href={href}>
{cta}
</a>
</div>
<div className="gchnb-box gchnb-stat">
<span>Proyectos lanzados</span>
<b>50+</b>
</div>
<div className="gchnb-box gchnb-sticker" aria-hidden="true">
100% a la medida
</div>
<div className="gchnb-box gchnb-tape" aria-hidden="true">
{[0, 1].map((n) => (
<span key={n} className="gchnb-run">
{words.concat(words).map((word, index) => (
<span key={index}>{word} ✺</span>
))}
</span>
))}
</div>
</div>
</section>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/hero-neobrutal-bentoEjemplo de uso de Hero neobrutalista en bento
Después de copiar hero-neobrutal-bento.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { HeroNeobrutalBento } from "./hero-neobrutal-bento";
export default function Ejemplo() {
return <HeroNeobrutalBento title="Ejemplo" />;
}Propiedades de HeroNeobrutalBento
HeroNeobrutalBento acepta 6 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
title? | string | Opcional. |
description? | string | Opcional. |
cta? | string | Opcional. |
href? | string | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Personaliza Hero neobrutalista en bento 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 |
|---|---|
--c | #fff |
Accesibilidad y rendimiento
El archivo tiene 73 líneas (5 KB) y define 1 animación con @keyframes. Esto es lo que hace Hero neobrutalista en bento 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".