Asi es como va actualmente mi TodoMachine




Mostrar un texto plano de "cargando..." rompe la estética de cualquier aplicación. Crear loading skeletons en React te permite reemplazar ese mensaje aburrido por una versión animada y elegante del componente real, mejorando la experiencia de usuario mientras los datos se cargan desde local storage o una API.
La idea central es refactorizar la lógica de estados (carga, error, vacío) en componentes dedicados y aplicar CSS con gradientes animados para simular el contenido que está por aparecer.
Por qué refactorizar los estados en componentes dedicados
Cuando tu TodoUI mezcla validaciones de loading, error y listas vacías con párrafos sueltos, la maquetación se vuelve frágil. Lo más limpio es extraer cada estado a su propio componente.
En lugar de escribir el texto directamente dentro del render, puedes importar tres componentes específicos:
TodosLoading para el estado de carga.TodosError para cuando algo falla.EmptyTodos para cuando no hay tareas creadas.Cada uno vive en su propia carpeta dentro de src/, con un index.js que exporta el componente y, opcionalmente, un archivo CSS asociado. Esta estructura te deja cambiar la interfaz de un estado sin tocar el resto de la aplicación.
¿Qué es un loading skeleton? Es una versión visual y animada de un componente que imita su estructura final mientras se cargan los datos reales, en vez de mostrar un texto plano de carga. [03:45]
Cómo replicar la estructura del TodoItem para el skeleton
El truco está en copiar la misma estructura HTML del componente real, pero vaciando su contenido. Si tu TodoItem usa un li con un ícono de completado, un párrafo de texto y un ícono de eliminar, tu TodoLoading debe tener exactamente esos tres bloques.
Las clases CSS sugeridas son:
loadingTodoContainer para el contenedor.loadingTodoCompleteIcon para el círculo de la izquierda.loadingTodoText para la barra central que simula el texto.loadingTodoDeleteIcon para el ícono de la derecha.Mantienes el mismo position: relative, display: flex, márgenes y sombras que el componente original, pero agregas un border-radius de 10 pixeles para suavizar los bordes y hacer evidente que es un placeholder.
Cómo animar el gradiente en CSS para simular carga
Aquí viene lo interesante. A todos los elementos del skeleton, excepto al texto, les aplicas un background con gradiente de colores. Para que la animación funcione, ese fondo necesita un tamaño exagerado, alrededor de 400% en alto y ancho.
Luego defines un @keyframes que mueve la posición del background en distintas direcciones, generando ese efecto de gradiente girando y parpadeando suavemente. El elemento permanece quieto en su lugar; lo que se mueve es el fondo gigante detrás de él.
css @keyframes loading-pulse { 0% { background-position: 0% 0%; } 50% { background-position: 100% 100%; } 100% { background-position: 0% 0%; } }
.loadingTodoContainer { background-size: 400% 400%; animation: loading-pulse 2s infinite; border-radius: 10px; }
¿Cuántos skeletons debo mostrar? Renderizar tres
TodoLoadingen lugar de uno solo ocupa más espacio en pantalla y comunica mejor que viene una lista, no un único elemento. [10:20]
Cómo renderizar varios skeletons en App.js
En App.js, dentro del bloque que valida loading, llamas al componente TodosLoading tres veces seguidas. Visualmente da la sensación de una lista en construcción, lo cual es más fiel al resultado final que un solo placeholder.
Este detalle es estético, pero hace una diferencia notable en la percepción del usuario.
Qué otros componentes pueden tener su propio skeleton
El reto opcional es extender el patrón a más partes de la aplicación. Dos candidatos claros:
TodoSearch, el campo de búsqueda, que puede mostrarse como una barra animada antes de habilitarse.TodoCounter, que durante la carga muestra "Has completado 0 de 0 todos" y luego salta al número real.Un skeleton en el contador evita ese parpadeo de cifras, aunque dependiendo de tu criterio de UX puedes decidir dejarlo así si no afecta la experiencia.
Habilidades y conceptos que practicas con este reto
index.js para exportar componentes en React [02:50].background-size exagerado [08:15].@keyframes para mover el background-position [09:00].Con estos cambios, tu aplicación deja de mostrar pantallas blancas o textos genéricos y empieza a comunicar personalidad incluso en los segundos de espera. Cuéntame en los comentarios cómo diseñaste tu propio skeleton y qué animación elegiste.
Mostrar un texto plano de "cargando..." rompe la estética de cualquier aplicación. Crear loading skeletons en React te permite reemplazar ese mensaje aburrido por una versión animada y elegante del componente real, mejorando la experiencia de usuario mientras los datos se cargan desde local storage o una API.
La idea central es refactorizar la lógica de estados (carga, error, vacío) en componentes dedicados y aplicar CSS con gradientes animados para simular el contenido que está por aparecer.
Cuando tu TodoUI mezcla validaciones de loading, error y listas vacías con párrafos sueltos, la maquetación se vuelve frágil. Lo más limpio es extraer cada estado a su propio componente.
En lugar de escribir el texto directamente dentro del render, puedes importar tres componentes específicos:
TodosLoading para el estado de carga.TodosError para cuando algo falla.EmptyTodos para cuando no hay tareas creadas.Cada uno vive en su propia carpeta dentro de src/, con un index.js que exporta el componente y, opcionalmente, un archivo CSS asociado. Esta estructura te deja cambiar la interfaz de un estado sin tocar el resto de la aplicación.
¿Qué es un loading skeleton? Es una versión visual y animada de un componente que imita su estructura final mientras se cargan los datos reales, en vez de mostrar un texto plano de carga. [03:45]
El truco está en copiar la misma estructura HTML del componente real, pero vaciando su contenido. Si tu TodoItem usa un li con un ícono de completado, un párrafo de texto y un ícono de eliminar, tu TodoLoading debe tener exactamente esos tres bloques.
Las clases CSS sugeridas son:
loadingTodoContainer para el contenedor.loadingTodoCompleteIcon para el círculo de la izquierda.loadingTodoText para la barra central que simula el texto.loadingTodoDeleteIcon para el ícono de la derecha.Mantienes el mismo position: relative, display: flex, márgenes y sombras que el componente original, pero agregas un border-radius de 10 pixeles para suavizar los bordes y hacer evidente que es un placeholder.
Aquí viene lo interesante. A todos los elementos del skeleton, excepto al texto, les aplicas un background con gradiente de colores. Para que la animación funcione, ese fondo necesita un tamaño exagerado, alrededor de 400% en alto y ancho.
Luego defines un @keyframes que mueve la posición del background en distintas direcciones, generando ese efecto de gradiente girando y parpadeando suavemente. El elemento permanece quieto en su lugar; lo que se mueve es el fondo gigante detrás de él.
css @keyframes loading-pulse { 0% { background-position: 0% 0%; } 50% { background-position: 100% 100%; } 100% { background-position: 0% 0%; } }
.loadingTodoContainer { background-size: 400% 400%; animation: loading-pulse 2s infinite; border-radius: 10px; }
¿Cuántos skeletons debo mostrar? Renderizar tres
TodoLoadingen lugar de uno solo ocupa más espacio en pantalla y comunica mejor que viene una lista, no un único elemento. [10:20]
En App.js, dentro del bloque que valida loading, llamas al componente TodosLoading tres veces seguidas. Visualmente da la sensación de una lista en construcción, lo cual es más fiel al resultado final que un solo placeholder.
Este detalle es estético, pero hace una diferencia notable en la percepción del usuario.
El reto opcional es extender el patrón a más partes de la aplicación. Dos candidatos claros:
TodoSearch, el campo de búsqueda, que puede mostrarse como una barra animada antes de habilitarse.TodoCounter, que durante la carga muestra "Has completado 0 de 0 todos" y luego salta al número real.Un skeleton en el contador evita ese parpadeo de cifras, aunque dependiendo de tu criterio de UX puedes decidir dejarlo así si no afecta la experiencia.
index.js para exportar componentes en React [02:50].background-size exagerado [08:15].@keyframes para mover el background-position [09:00].Con estos cambios, tu aplicación deja de mostrar pantallas blancas o textos genéricos y empieza a comunicar personalidad incluso en los segundos de espera. Cuéntame en los comentarios cómo diseñaste tu propio skeleton y qué animación elegiste.
Asi es como va actualmente mi TodoMachine




Aun no he visto los cursos de animaciones pero me puse a buscar mas o menos como funciona cada propiedad que usa el profesor para entender y aplicarlo a mi diseno.
Aplique lo mismo solo que con mis colores y le agregue un borde con un color con muy baja opacidad

Yo añadí una animación de puntitos rebotando

Cumpliendo con el reto, he utilizado material UI para la animación de <TodosLoading/>
(
import CircularProgress from "@mui/material/CircularProgress"
import Box from "@mui/material/Box"
function TodosLoading () {
return (
<Box sx={{ display: 'flex' }}>
<CircularProgress />
</Box>
)
}
export { TodosLoading}
Este es el resultado de mi propio, Loading Skeleton, me base en un video de Youtube y me siento orgulloso del resultado.

Aqui dejo una animacion sencilla con dots que hice para el reto !!!
🤗

Así van los míos

Asi va quedando
Y esta es otra version
Para los que ya saben CSS y quieren seguir avanzando con mas conceptos de react, les dejo el CSS de TodosLoading.js y la estructura del componente
COMPONENTE:
import './TodosLoading.css'
function TodosLoading() {
return (
<div className='LoadingTodo-container'>
<span
className='LoadingTodo-completeIcon'>
</span>
<p className='LoadingTodo-text'></p>
<span
className='LoadinTodo-deleteIcon'></span>
</div>
);
};
export { TodosLoading };
CSS:
.LoadingTodo-container {
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin-top: 24px;
box-shadow: 0px 5px 50px rgba(32, 35 41 0.15);
border-radius: 10px;
padding: 12px 0;
}
.LoadingTodo-text {
margin: 24px 0 24px 24px;
Width: calc(100% - 120px);
font-size: 18px;
line-height: 24px;
font-weight: 400;
}
.LoadingTodo-completeIcon,
.LoadinTodo-deleteIcon {
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50px;
height: 48px;
width: 48px;
}
.LoadingTodo-completeIcon {
position: absolute;
left: 12px;
}
.LoadinTodo-deleteIcon {
position: absolute;
top: -24px;
right: 0;
}
.LoadingTodo-container,
.LoadingTodo-completeIcon,
.LoadinTodo-deleteIcon {
background: linear-gradient(90deg, rgba(250, 250, 250, 1), rgb(200, 199, 199));
background-size: 400% 400%;
animation: loadingAnimation 3s ease-in-out infinite;
}
@keyframes loadingAnimation {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
};
Gracias!!!
No creo que se vea tan aburrido 😅
