Ir al contenido
Evaluar mi proyecto
Componentes · TarjetasDisponible

Tarjeta que gira

Gira en 3D para mostrar el reverso, con puntero, teclado o toque.

Diseño

Pasa el puntero o toca

Desarrollo

Pasa el puntero o toca

Código completo

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

flip-card.tsx62 líneas
Descargar
"use client";

/**
 * Tarjeta que gira en 3D para mostrar el reverso. Con ratón gira al pasar el puntero o al enfocarla con el teclado;
 * en pantallas táctiles gira al tocarla. Enter o Espacio también la voltean.
 *
 *   <FlipCard front={<h3>Diseño</h3>} back={<p>Interfaces claras y rápidas.</p>} />
 */

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

export type FlipCardProps = {
  front: ReactNode;
  back: ReactNode;
  /** Colores de las dos caras. */
  frontColor?: string;
  backColor?: string;
  /** Nombre accesible de la tarjeta. */
  label?: string;
  className?: string;
  style?: CSSProperties;
};

const CSS = `
.gcx-scene { display: inline-block; width: 280px; height: 360px; perspective: 1100px; font-family: inherit; }
.gcx-card { position: relative; width: 100%; height: 100%; border-radius: 26px; outline: none; cursor: pointer; transform-style: preserve-3d; transition: transform .85s cubic-bezier(.34, 1.25, .5, 1); }
.gcx-card[data-flipped="true"] { transform: rotateY(180deg); }
@media (hover: hover) { .gcx-card:hover { transform: rotateY(180deg); } .gcx-card[data-flipped="true"]:hover { transform: rotateY(180deg); } }
.gcx-card:focus-visible { box-shadow: 0 0 0 3px #fff, 0 0 0 6px #111; }
.gcx-face { position: absolute; inset: 0; display: grid; align-content: end; gap: 10px; box-sizing: border-box; padding: 26px; overflow: hidden; border-radius: inherit; color: #fff; -webkit-backface-visibility: hidden; backface-visibility: hidden; }
.gcx-front { background: var(--gcx-front, #ff6b4a); }
.gcx-back { background: var(--gcx-back, #0f766e); transform: rotateY(180deg); align-content: center; }
.gcx-front::before { content: ""; position: absolute; top: -50px; right: -50px; width: 190px; height: 190px; border-radius: 50%; background: rgba(255, 255, 255, .22); }
.gcx-front::after { content: ""; position: absolute; top: 70px; left: -34px; width: 110px; height: 110px; border-radius: 28px; background: rgba(0, 0, 0, .13); transform: rotate(18deg); }
.gcx-face h3 { position: relative; margin: 0; font-size: 28px; font-weight: 800; line-height: 1.1; letter-spacing: -.02em; }
.gcx-face p { position: relative; margin: 0; font-size: 16px; line-height: 1.55; }
@media (prefers-reduced-motion: reduce) { .gcx-card { transition: none; } }
`;

export function FlipCard({ front, back, frontColor, backColor, label = "Tarjeta con reverso", className, style }: FlipCardProps) {
  const [flipped, setFlipped] = useState(false);

  function onKeyDown(event: KeyboardEvent<HTMLDivElement>) {
    if (event.key === "Enter" || event.key === " ") {
      event.preventDefault();
      setFlipped((value) => !value);
    }
  }

  return (
    <>
      <style>{CSS}</style>
      <div className={["gcx-scene", className].filter(Boolean).join(" ")} style={{ ["--gcx-front" as string]: frontColor, ["--gcx-back" as string]: backColor, ...style } as CSSProperties}>
        <div className="gcx-card" role="button" tabIndex={0} aria-label={label} aria-pressed={flipped} data-flipped={flipped} onClick={() => setFlipped((value) => !value)} onKeyDown={onKeyDown}>
          <div className="gcx-face gcx-front" aria-hidden={flipped}>{front}</div>
          <div className="gcx-face gcx-back" aria-hidden={!flipped}>{back}</div>
        </div>
      </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-volteo

Ejemplo de uso de Tarjeta que gira

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

ejemplo.tsx5 líneas
import { FlipCard } from "./flip-card";

export default function Ejemplo() {
  return <FlipCard frontColor="Ejemplo" />;
}

Propiedades de FlipCard

FlipCard acepta 7 propiedades; 2 son obligatorias.

PropiedadTipoDescripción
frontReactNodeObligatoria.
backReactNodeObligatoria.
frontColor?stringColores de las dos caras.
backColor?stringOpcional.
label?stringNombre accesible de la tarjeta.
className?stringOpcional.
style?CSSPropertiesOpcional.

Personaliza Tarjeta que gira 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
--gcx-front#ff6b4a
--gcx-back#0f766e

Accesibilidad y rendimiento

El archivo tiene 62 líneas (3 KB) y no necesita @keyframes. Esto es lo que hace Tarjeta que gira 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: button.
  • Responde al teclado, no solo al ratón.
  • Es un componente de cliente de Next.js: incluye la directiva "use client".
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React · Next.js (quita la directiva use client fuera de Next.js) · Sin Tailwind

Acerca del producto

Una tarjeta de dos caras que gira en 3D con un pequeño rebote. Con ratón gira al pasar el puntero; en pantallas táctiles, al tocar; y con teclado, con Enter o Espacio. El texto de la cara oculta se oculta a lectores de pantalla.

Incluye

Un solo archivo React + TypeScript, con los estilos dentro. No usa Tailwind ni bibliotecas externas.

  • Colores de las dos caras configurables
  • Teclado y táctil además del puntero
  • Cara oculta con aria-hidden
  • Frente y reverso con cualquier contenido

Cómo usarlo

Pasa front y back como contenido. Cambia frontColor y backColor y el tamaño desde CSS (.gcx-scene).