Ir al contenido
Evaluar mi proyecto
Componentes · TarjetasDisponible

Tarjeta de crédito 3D

Tarjeta skeuomórfica con chip, holograma y relieve que gira para mostrar el reverso con clic o Enter.

Código completo

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

tarjeta-credito.tsx74 líneas
Descargar
"use client";

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

/** Tarjeta de crédito skeuomórfica con giro 3D, holograma y relieve estampado. Se voltea con clic o Enter. React + TypeScript, sin dependencias. */
export type TarjetaCreditoProps = {
  number?: string;
  holder?: string;
  expires?: string;
  brand?: string;
  className?: string;
  style?: CSSProperties;
};

const CSS = `
.gctcr-root { box-sizing: border-box; display: block; width: 100%; max-width: 360px; perspective: 1000px; color: #f4f6ff; }
.gctcr-root *, .gctcr-root *::before, .gctcr-root *::after { box-sizing: border-box; }
.gctcr-root button { font: inherit; }
@media (prefers-reduced-motion: reduce) { .gctcr-root *, .gctcr-root *::before, .gctcr-root *::after { transition-duration: .01ms !important; } }
.gctcr-btn { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; text-align: left; color: inherit; }
.gctcr-btn:focus-visible { outline: 3px solid #fff; outline-offset: 6px; border-radius: 22px; }
.gctcr-card { position: relative; display: block; width: 100%; aspect-ratio: 1.586; transform-style: preserve-3d; transition: transform .8s cubic-bezier(.16, 1, .3, 1); }
.gctcr-btn[aria-pressed="true"] .gctcr-card { transform: rotateY(180deg); }
.gctcr-btn:not([aria-pressed="true"]):hover .gctcr-card { transform: rotateY(-8deg) rotateX(4deg); }
.gctcr-face { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: space-between; padding: 22px 24px; border-radius: 20px; backface-visibility: hidden; -webkit-backface-visibility: hidden; overflow: hidden; background: radial-gradient(130% 120% at 0% 0%, #5a67d8, #2c2f8f 50%, #14154f); box-shadow: inset 0 1px 0 rgba(255, 255, 255, .4), inset 0 -2px 0 rgba(0, 0, 0, .4), 0 26px 40px -16px rgba(0, 0, 0, .6); }
.gctcr-face::before { content: ""; position: absolute; inset: -50%; background: conic-gradient(from 200deg at 50% 50%, transparent 0 20%, rgba(255, 255, 255, .16) 30%, transparent 40% 70%, rgba(255, 255, 255, .1) 80%, transparent); pointer-events: none; }
.gctcr-back { transform: rotateY(180deg); padding: 0; background: linear-gradient(135deg, #2c2f8f, #14154f); }
.gctcr-row { width: 100%; display: flex; justify-content: space-between; align-items: center; position: relative; }
.gctcr-chip { width: 46px; height: 36px; border-radius: 8px; background: linear-gradient(135deg, #f5de92, #b58b2d 50%, #f5de92); box-shadow: inset 0 0 0 1px rgba(80, 55, 0, .45); }
.gctcr-brand { font: italic 800 22px/1 ui-serif, Georgia, serif; letter-spacing: -.02em; }
.gctcr-num { position: relative; font: 600 20px/1 ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: .1em; text-shadow: 0 -1px 0 rgba(0, 0, 0, .55), 0 1px 0 rgba(255, 255, 255, .18); }
.gctcr-info { position: relative; display: flex; justify-content: space-between; font: 600 12px/1.2 ui-monospace, "SF Mono", Menlo, monospace; letter-spacing: .1em; text-transform: uppercase; text-shadow: 0 -1px 0 rgba(0, 0, 0, .5); }
.gctcr-info small { display: block; margin-bottom: 3px; font-size: 8px; opacity: .65; }
.gctcr-holo { position: absolute; right: 24px; bottom: 54px; width: 38px; height: 28px; border-radius: 6px; background: conic-gradient(from 0deg, #ff8ad4, #8ad8ff, #b6ff8a, #ffe08a, #ff8ad4); opacity: .75; mix-blend-mode: screen; }
.gctcr-stripe { height: 46px; margin-top: 28px; background: #06070f; }
.gctcr-sign { margin: 22px 24px 0; padding: 10px 12px; border-radius: 4px; background: repeating-linear-gradient(135deg, #f4f1e8 0 6px, #e6e2d3 6px 12px); color: #222; font: italic 700 15px/1.2 ui-serif, Georgia, serif; text-align: right; }
.gctcr-note { margin: 16px 24px 0; font-size: 11px; line-height: 1.5; opacity: .7; }`;

export function TarjetaCredito({ number = "4242 8891 0042 7731", holder = "Ana Pérez", expires = "09/29", brand = "banco", className = "", style }: TarjetaCreditoProps) {
  const [back, setBack] = useState(false);
  return (
    <div className={`gctcr-root ${className}`} style={style}>
      <style>{CSS}</style>
      <button className="gctcr-btn" type="button" aria-pressed={back} aria-label={back ? "Tarjeta, vista trasera. Pulsa para ver el frente" : `Tarjeta ${brand} terminada en ${number.slice(-4)}. Pulsa para ver el reverso`} onClick={() => setBack((value) => !value)}>
        <span className="gctcr-card">
          <span className="gctcr-face">
            <span className="gctcr-row">
              <span className="gctcr-chip" />
              <span className="gctcr-brand">{brand}</span>
            </span>
            <span className="gctcr-holo" />
            <span className="gctcr-num">{number}</span>
            <span className="gctcr-info">
              <span>
                <small>Titular</small>
                {holder}
              </span>
              <span>
                <small>Vence</small>
                {expires}
              </span>
            </span>
          </span>
          <span className="gctcr-face gctcr-back">
            <span className="gctcr-stripe" />
            <span className="gctcr-sign">•••</span>
            <span className="gctcr-note">Tarjeta de muestra para la demostración. No contiene datos reales.</span>
          </span>
        </span>
      </button>
    </div>
  );
}

Úsalo en tu proyecto

Instálalo con la CLI de shadcn.

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

Ejemplo de uso de Tarjeta de crédito 3D

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

ejemplo.tsx5 líneas
import { TarjetaCredito } from "./tarjeta-credito";

export default function Ejemplo() {
  return <TarjetaCredito number="Ejemplo" />;
}

Propiedades de TarjetaCredito

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

PropiedadTipoDescripción
number?stringOpcional.
holder?stringOpcional.
expires?stringOpcional.
brand?stringOpcional.
className?stringOpcional.
style?CSSPropertiesOpcional.

Accesibilidad y rendimiento

El archivo tiene 74 líneas (5 KB) y no necesita @keyframes. Esto es lo que hace Tarjeta de crédito 3D 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)