Juan Pablo Cortés
Jerson Hernán Uribe Montenegro
Jerson Hernán Uribe Montenegro
¿Cómo se construye una card de órdenes que luzca profesional y conserve consistencia visual con el resto de un e-commerce? Aquí resolvemos el reto de estilizar la página My Orders usando Tailwind CSS y React, aplicando width, padding, flexbox e íconos para lograr una tarjeta clara, ordenada y clickeable.
Esta guía te sirve si estás aprendiendo a maquetar componentes reutilizables y quieres entender cómo distribuir información dentro de una card sin que se vea apretada o desalineada.
¿Cómo defines el contenedor de una OrdersCard en Tailwind?
Lo primero es darle estructura al componente OrdersCard. Una card sin tamaño definido colapsa al ancho de su contenido, así que necesitas asignarle dimensiones y respiro interno [00:18].
w-80 para fijar un ancho cómodo.p-4 para que el contenido no toque los bordes.border y rounded-lg para mantener consistencia con otras tarjetas.Con estas cuatro clases ya tienes un contenedor sólido. La idea es que la tarjeta funcione como una unidad visual independiente dentro del listado.
¿Qué hace
rounded-lgen Tailwind? Aplica un border-radius grande a las esquinas del elemento. Es la clase estándar para tarjetas y botones que buscan un look moderno sin llegar a ser circulares.
¿Cómo distribuyes la información dentro de la card con flexbox?
La card tiene tres datos: fecha, cantidad de artículos y precio total. Si los pones uno tras otro, se amontonan. La solución es agrupar dos a la izquierda y uno a la derecha [01:00].
Estructura con flex y justify-between
Envolvemos los elementos en un div padre con flex justify-between para que se separen a los extremos. Pero hay un detalle: si el contenedor no tiene ancho suficiente, justify-between no separa nada porque no sobra espacio [03:02].
La solución es agregar w-full al contenedor para que ocupe todo el ancho disponible de la card. Ahí sí, los elementos se empujan a los lados.
Dentro del bloque izquierdo usamos flex flex-col para apilar fecha y cantidad de artículos verticalmente. En el bloque derecho dejamos el precio destacado.
Reutilizando estilos del checkout
Para mantener consistencia, copiamos las clases del precio que ya teníamos en la página de checkout y las pegamos en la card de órdenes [02:32]. Reutilizar estilos entre componentes evita inconsistencias visuales y ahorra trabajo.
¿Cómo agregas un ícono clickeable y evitas errores de React?
Para indicar que la card lleva al detalle de la orden, agregamos un cursor pointer y un ícono ChevronRightIcon importado desde la librería de íconos del proyecto [04:30].
¿Por qué React lanza el error "cannot appear as a descendant"? Ocurre cuando anidas elementos de bloque dentro de un
<p>, como meter un<div>dentro de un párrafo. HTML no lo permite y React te avisa para que cambies la estructura.
La solución es reemplazar el <p> padre por un <div> o un <span> y usar párrafos solo para texto plano [05:48]. Aquí cambiamos el contenedor a div y dejamos los <p> únicamente envolviendo texto.
Alineando el ícono con el precio
Queremos que el ícono y el precio estén en la misma línea. Para eso aplicamos al contenedor:
flex para layout horizontal.items-center para alineación vertical.gap-2 para separación entre el número y el ícono.El resultado: precio y chevron alineados a la altura del texto, con un espacio uniforme entre ambos [06:35].
¿Cómo dejas el título de la página consistente con el resto del e-commerce?
El <h1> de My Orders venía sin estilos. Reutilizamos las clases tipográficas que ya aplicamos en la página de checkout, las copiamos al <h1> de My Orders y agregamos mb-4 al contenedor del título para separarlo del listado de cards [04:08].
Un detalle de microcopy: en lugar de mostrar solo el número "2", escribimos "2 articles". Pequeño cambio, gran ganancia en claridad para el usuario [03:35].
¿Qué patrones de Tailwind y React conviene memorizar de este ejercicio?
Este flujo deja varios aprendizajes prácticos que vas a repetir muchas veces:
w-full dentro de un contenedor con padding: necesario para que justify-between funcione como esperas.flex flex-col vs flex por defecto: cambia entre apilar vertical u horizontal sin tocar HTML.div dentro de p; usa span o reestructura.La card final muestra fecha, cantidad de artículos, precio destacado y un chevron que invita al clic, todo dentro de un contenedor redondeado y separado del siguiente. Cuando agregas una segunda orden, ambas tarjetas se apilan con el mismo espaciado y el listado se siente ordenado [07:30].
¿Cómo quedó tu versión de la card? Comparte en los comentarios capturas de tu página de My Orders con elementos agregados, eliminados y mostrados en la orden. Nos vemos en la siguiente clase para empezar con el buscador.
Así quedo My Orders.
const handleCheckout = () => { const orderToAdd = { date: "01.02.23", products: cartProducts, totalProducts: cartProducts.length, totalPrice: totalPrice(cartProducts), }; setOrder([...order, orderToAdd]); setCartProducts([]); closeCheckoutSideMenu(); };
Por otra parte tiene un pequeño bug, si se agrega un producto al carro, no deja ver el detalle de un producto seo se corrige en el componente Card, agregando el closeCheckoutSideMenu();
const showProduct = (productDetail) => { closeCheckoutSideMenu(); openProductDetail(); setProductToShow(productDetail); };
Juan Pablo Cortés
Jerson Hernán Uribe Montenegro
Jerson Hernán Uribe Montenegro
Ingrid Gallegos
Me gusto la idea de colocar los iconos pequeños al interior. Ademas le coloque un shadow a la tarjeta que creo que le va bien :)
Certuit Software
se ve muy bien
Jose Ever Muñoz Muñoz
que elegante
Asi van mi paginas de las ordenes
Luis Felipe Silgado Cortázar
Emily Menchú
Fernando Labastida Vázquez
El tuyo es mi favorito
Alexander Moreno
mi pagina de orders
Johann Camilo Belosareos Colmenares
en mi caso renderizé la palabra article según la cantidad de productos
<span> {totalProducts} {totalProducts === 1 ? 'article' : 'articles'} </span>
kevin antony calderon guabloche
Luis David Perez
Me tomo algo de tiempo pero así voy
Santiago López Alarcón
Emocionado con los avances!!!
Andrés Julian Caro Restrepo
Así me quedó:
CARLOS JARAMILLO
Me lo copie!!
Cristian Acalo
🦄✨Agregando bordes las cards se ven muy bien :D
Elver David Matacea Lopez
Asi va mi diseño.
Juan Camilo Grisales Arias
Así quedo MyOrders.
También agregué una animación al momento en el que se hace click en la orden para desplegar los items de cada orden.
John Malku Córdova Sinchico
Hola Teff tengo una pregunta, ¿como se llama la extensión que usas para que al hacer click en un elemento te desplege los archivos que contienen tal elemento?
Argenis Estefreric Jose Rodriguez Figueroa
Sencillo pero funcional
Humberto Cruz
Bueno, así quedo el mío.
YahirMcGrady ramirez valverde
Gabriel Fernandez
Asi me quedo!
Si quieren poner la fecha actual pueden hacerlo asi:
const currentDate = () => { const date = new Date().toLocaleDateString(); return date }
En el componente seria así:
... <p className='flex flex-col'> <span className='font-light'>{currentDate()}</span> <span className='font-light'>{totalProducts} articles</span> </p> ...
¡Genial!, yo hice algo similar, pero desde utils, usando la librería de date-fns para que genere la fecha del país de donde sería la tienda, porque si luego hacemos un deploy a un hosting cuyo servidor ejecuta el código en una ubicación diferente, tendremos problemas con la fecha./** * This function gets the date in Colombia's time zone. * @returns <u>{date, string}</u>*/ import { formatInTimeZone } from 'date-fns-tz'; export const getDateCol = ()=> { const date = new Date(); const formatDateCol = formatInTimeZone(date, 'America/Bogota', 'yyyy-MM-dd'); return formatDateCol;};
/** * This function gets the date in Colombia's time zone. * @returns {date, string} */ import { formatInTimeZone } from 'date-fns-tz'; export const getDateCol = ()=> { const date = new Date(); const formatDateCol = formatInTimeZone(date, 'America/Bogota', 'yyyy-MM-dd'); return formatDateCol; };
¡Genial!, yo hice algo similar, pero desde utils, usando la librería de date-fns para que genere la fecha del país de donde sería la tienda, porque si luego hacemos un deploy a un hosting cuyo servidor ejecuta el código en una ubicación diferente, tendremos problemas con la fecha.
/** * This function gets the date in Colombia's time zone. * @returns {date, string} */ import { formatInTimeZone } from 'date-fns-tz'; export const getDateCol = ()=> { const date = new Date(); const formatDateCol = formatInTimeZone(date, 'America/Bogota', 'yyyy-MM-dd'); return formatDateCol; };