Título 3D retro Y2K
Título extruido con relieve que apunta lejos del puntero; amarillo, rosa y contorno morado al estilo de 2001.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
"use client";
import { useState, type CSSProperties, type PointerEvent } from "react";
/** Título extruido en 3D al estilo Y2K: la profundidad apunta lejos del puntero y el relieve cromado se inclina con él. React + TypeScript, sin dependencias. */
export type TextoRetro3dProps = {
text?: string;
depth?: number;
face?: string;
side?: string;
className?: string;
style?: CSSProperties;
};
const CSS = `
.gctrx-root { display: inline-block; max-width: 100%; padding: .25em .35em .5em; color: var(--f); font: 900 clamp(44px, 11vw, 120px)/.95 "Arial Black", "Impact", ui-sans-serif, system-ui, sans-serif; letter-spacing: -.02em; text-transform: uppercase; text-align: center; -webkit-text-stroke: 3px #19104a; paint-order: stroke fill; touch-action: pan-y; transition: transform .25s cubic-bezier(.16, 1, .3, 1); }
.gctrx-root *, .gctrx-root *::before, .gctrx-root *::after { box-sizing: border-box; }
@media (prefers-reduced-motion: reduce) { .gctrx-root { transition: none; } }`;
export function TextoRetro3d({ text = "Hola mundo", depth = 14, face = "#ffe14d", side = "#ff3fa4", className = "", style }: TextoRetro3dProps) {
const [d, setD] = useState({ x: 0.6, y: 1 });
function move(event: PointerEvent<HTMLSpanElement>) {
if (event.pointerType === "touch") return;
const rect = event.currentTarget.getBoundingClientRect();
const x = (event.clientX - (rect.left + rect.width / 2)) / (rect.width / 2);
const y = (event.clientY - (rect.top + rect.height / 2)) / (rect.height / 2);
setD({ x: -Math.max(-1, Math.min(1, x)), y: -Math.max(-1, Math.min(1, y)) });
}
const extrusion = Array.from({ length: depth }, (_, i) => `${(d.x * (i + 1) * 1.1).toFixed(1)}px ${(d.y * (i + 1) * 1.1).toFixed(1)}px 0 ${i % 3 === 2 ? "#c21f80" : side}`).join(", ");
const shadow = `${extrusion}, ${(d.x * (depth + 8)).toFixed(1)}px ${(d.y * (depth + 8)).toFixed(1)}px 18px rgba(25, 16, 74, .45)`;
return (
<span className={`gctrx-root ${className}`} style={{ "--f": face, textShadow: shadow, ...style } as CSSProperties} onPointerMove={move} onPointerLeave={() => setD({ x: 0.6, y: 1 })} aria-label={text} role="text">
<style>{CSS}</style>
<span aria-hidden="true">{text}</span>
</span>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/texto-retro-3dEjemplo de uso de Título 3D retro Y2K
Después de copiar texto-retro-3d.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { TextoRetro3d } from "./texto-retro-3d";
export default function Ejemplo() {
return <TextoRetro3d text="Ejemplo" />;
}Propiedades de TextoRetro3d
TextoRetro3d acepta 6 propiedades: todas son opcionales y tienen un valor por defecto, así que funciona sin configurar nada.
| Propiedad | Tipo | Descripción |
|---|---|---|
text? | string | Opcional. |
depth? | number | Opcional. |
face? | string | Opcional. |
side? | string | Opcional. |
className? | string | Opcional. |
style? | CSSProperties | Opcional. |
Accesibilidad y rendimiento
El archivo tiene 41 líneas (2 KB) y no necesita @keyframes. Esto es lo que hace Título 3D retro Y2K por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Declara roles ARIA para lectores de pantalla: text.
- Reacciona al puntero con eventos pointer (ratón, lápiz y táctil).
- Es un componente de cliente de Next.js: incluye la directiva "use client".