Card Deck Web Component

Recientemente publiqué la primera versión estable de <card-deck>, un Web Component para interfaces de cartas deslizables inspirado en el modelo de interacción icónico de Tinder.

Este componente es:

  • ✅ Totalmente nativo (usa el estándar de Web Components)
  • ⚡️ Ligero y rápido
  • 📦 Sin dependencias
  • 💅 Personalizable mediante variables CSS
  • 🧠 Controlable desde JavaScript

En este artículo, te mostraré cómo usar el componente, y también te daré una mirada a cómo fue diseñado y construido.

🛠️ Instalación y Configuración

Para comenzar, solo necesitas incluir los estilos y el script en tu HTML:

<link rel="stylesheet" href="@salvador/card-deck/dist/style.min.css" />
<script type="module" src="@salvador/card-deck/index.min.js"></script>

O si estás usando un sistema moderno con bundling, impórtalo en tu JavaScript:

import "@salvadorsru/card-deck";

⚠️ Nota: La importación JS no incluye estilos — debes agregar el CSS manualmente desde la carpeta dist.

🚀 Uso Básico

Crear un mazo de cartas es tan simple como envolver elementos dentro de <card-deck>:

<card-deck>
  <div class="card">Carta 1</div>
  <div class="card">Carta 2</div>
  <div class="card">Carta 3</div>
</card-deck>

Cada hijo dentro del mazo se trata como una carta deslizable. Puedes deslizar las cartas a la izquierda, derecha, arriba o abajo — y se animan fuera de la vista.

🧩 Control Programático

También puedes controlar el mazo desde tu código. El componente exporta funciones auxiliares mediante el módulo emulate:

import { discardToRight, discardToLeft } from "@salvadorsru/card-deck/emulate";

const $deck = document.querySelector("card-deck");

discardToRight($deck);
// o
discardToLeft($deck);

Esto es útil en escenarios como quizzes o juegos donde las acciones del usuario controlan el comportamiento del deslizamiento.

📡 Eventos

El componente <card-deck> emite dos eventos principales:

discard

Se emite inmediatamente cuando el usuario desliza una carta.

cardRemoved

Se emite después de que la carta ha sido eliminada completamente (animación incluida y retirada del DOM).

deck.addEventListener("discard", (e) => {
  console.log("¡Deslizado!", e.detail);
});

deck.addEventListener("cardRemoved", (e) => {
  console.log("Carta eliminada", e.detail.card);
});

e.detail incluye:

  • goRight: true si la carta fue deslizada a la derecha
  • goDown: true si fue deslizada hacia abajo
  • card: referencia al elemento HTML de la carta

🎨 Personalización con Variables CSS

La apariencia y el comportamiento pueden ajustarse mediante variables CSS:

card-deck {
  --card-width: 200px;
  --card-height: 280px;
  --transition-time: 0.4s;
}

Variables disponibles:

  • --card-width, --card-height, --card-ratio
  • --transition-time, --transition-opacity, --transition-rotation

Esto te da control completo sobre el tamaño y velocidad de animación sin tocar el código fuente.

🧱 Cómo Funciona Internamente

Este componente está construido usando JavaScript puro y la API nativa de Custom Elements. Aquí un resumen de los conceptos clave:

  • Cada carta escucha los movimientos del puntero (arrastrar/deslizar)
  • La carta superior recibe clases como dragged y direccionales como .to-left, .to-right, etc.
  • Las animaciones se activan mediante transiciones CSS
  • Al soltar la carta, el componente decide si la reposiciona o la descarta
  • Las cartas descartadas se animan fuera y se eliminan del DOM
  • Todo el estado se maneja internamente, lo que lo hace muy fácil de usar en cualquier página HTML

Sin frameworks, sin dependencias, y funciona en cualquier navegador moderno.

📺 Demo en Vivo

Pruébalo aquí:
👉 swipeable-card-deck.vercel.app

🤝 Conclusión

<card-deck> sigue evolucionando, pero ya está listo para usarse en aplicaciones reales donde se necesite una interfaz deslizable — ideal para selectores de productos, quizzes, juegos o cartas de perfil.

Me encantaría recibir tu feedback, reportes de bugs o ideas de nuevas funciones — siéntete libre de abrir un issue o contactarme por redes sociales.

¡Gracias por leer!