From 6d645c3dc062c984c19f72993f9355ae78597f9e Mon Sep 17 00:00:00 2001 From: andrzej Date: Thu, 16 May 2024 13:49:58 +0200 Subject: [PATCH] add loading and error handling for images --- src/App.css | 13 +++-- src/App.tsx | 1 + src/objects/movie-wall.tsx | 14 +++-- src/spinner.css | 105 +++++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 8 deletions(-) create mode 100644 src/spinner.css diff --git a/src/App.css b/src/App.css index 9b3045b..5e4ac4c 100644 --- a/src/App.css +++ b/src/App.css @@ -83,7 +83,7 @@ img { figure { width: 100%; - float: left; + margin: 0; img { aspect-ratio: 2/3; @@ -109,6 +109,9 @@ img { grid-area: 1/1; } +.highlighted { + border: 0.1em solid gold; +} .overlay { @@ -121,10 +124,10 @@ img { opacity: 0; } +.highlighted>.overlay { + background-color: rgba(255, 222, 123, 0.5); +} + .overlay:hover { opacity: 1; } - -.highlighted { - border: 0.1em solid gold; -} diff --git a/src/App.tsx b/src/App.tsx index de21ec7..8c35890 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,5 +1,6 @@ import './defaults.css' import './App.css' +import './spinner.css' import { MovieWall } from './objects/movie-wall' import { useState, useEffect } from 'react' import tmdb from './objects/tmdb' diff --git a/src/objects/movie-wall.tsx b/src/objects/movie-wall.tsx index ed55050..3da4581 100644 --- a/src/objects/movie-wall.tsx +++ b/src/objects/movie-wall.tsx @@ -75,16 +75,24 @@ function Poster({ movie, config, listSimilar, setMovies, setChosenMovie, setSimi setChosenMovie(movie) listSimilar(config, movie, setMovies, setSimilarMoviesAvailable) } + const [isLoading, setIsLoading] = useState(true) + const [hasError, setHasError] = useState(false) const classes = [ "poster", isHighlighted ? "highlighted" : "" ].join(" ") return
-
clickHandler()}> -
+ {isLoading ? +
+
+ :
clickHandler()}> +
+ } + {hasError ??
⚠️
} console.log("LOADED IMG")} + onLoad={() => setIsLoading(false)} + onError={() => setHasError(true)} />
} diff --git a/src/spinner.css b/src/spinner.css new file mode 100644 index 0000000..cdca51d --- /dev/null +++ b/src/spinner.css @@ -0,0 +1,105 @@ +.spinner-container { + margin: auto; + text-align: center; +} + +.lds-spinner, +.lds-spinner div, +.lds-spinner div:after { + box-sizing: border-box; +} + +.lds-spinner { + color: currentColor; + display: inline-block; + position: relative; + width: 80px; + height: 80px; +} + +.lds-spinner div { + transform-origin: 40px 40px; + animation: lds-spinner 1.2s linear infinite; +} + +.lds-spinner div:after { + content: " "; + display: block; + position: absolute; + top: 3.2px; + left: 36.8px; + width: 6.4px; + height: 17.6px; + border-radius: 20%; + background: currentColor; +} + +.lds-spinner div:nth-child(1) { + transform: rotate(0deg); + animation-delay: -1.1s; +} + +.lds-spinner div:nth-child(2) { + transform: rotate(30deg); + animation-delay: -1s; +} + +.lds-spinner div:nth-child(3) { + transform: rotate(60deg); + animation-delay: -0.9s; +} + +.lds-spinner div:nth-child(4) { + transform: rotate(90deg); + animation-delay: -0.8s; +} + +.lds-spinner div:nth-child(5) { + transform: rotate(120deg); + animation-delay: -0.7s; +} + +.lds-spinner div:nth-child(6) { + transform: rotate(150deg); + animation-delay: -0.6s; +} + +.lds-spinner div:nth-child(7) { + transform: rotate(180deg); + animation-delay: -0.5s; +} + +.lds-spinner div:nth-child(8) { + transform: rotate(210deg); + animation-delay: -0.4s; +} + +.lds-spinner div:nth-child(9) { + transform: rotate(240deg); + animation-delay: -0.3s; +} + +.lds-spinner div:nth-child(10) { + transform: rotate(270deg); + animation-delay: -0.2s; +} + +.lds-spinner div:nth-child(11) { + transform: rotate(300deg); + animation-delay: -0.1s; +} + +.lds-spinner div:nth-child(12) { + transform: rotate(330deg); + animation-delay: 0s; +} + +@keyframes lds-spinner { + 0% { + opacity: 1; + } + + 100% { + opacity: 0; + } +}