use corner spinner on item page, and fix delay bug

Fading the whole preview to a black overlay for the loading state was feeling aggressive, especially since loading delay wasn't working correctly!

In this change, I fix loading delay, and I add a nice subtle "corner" variant for outfit preview spinners :)
This commit is contained in:
Emi Matchu 2020-09-13 04:12:14 -07:00
parent c11c2b1394
commit 351b9a88bd
4 changed files with 51 additions and 41 deletions

View file

@ -40,7 +40,7 @@ function HomePage() {
colorId={previewState?.colorId} colorId={previewState?.colorId}
pose={previewState?.pose} pose={previewState?.pose}
wornItemIds={[]} wornItemIds={[]}
loadingDelay="1.5s" loadingDelayMs={1500}
placeholder={ placeholder={
<Box <Box
as="img" as="img"

View file

@ -383,6 +383,8 @@ function ItemPageOutfitPreview({ itemId }) {
colorId="8" colorId="8"
pose="HAPPY_FEM" pose="HAPPY_FEM"
wornItemIds={[itemId]} wornItemIds={[itemId]}
spinnerVariant="corner"
loadingDelayMs={2000}
/> />
</Box> </Box>
</AspectRatio> </AspectRatio>

View file

@ -86,12 +86,7 @@ function HangerSpinner({ size = "md", ...props }) {
`} `}
{...props} {...props}
> >
<HangerIcon <HangerIcon boxSize={boxSize} color={color} transition="color 0.2s" />
boxSize={boxSize}
color={color}
transition="color 0.2s"
{...props}
/>
</Box> </Box>
</> </>
); );

View file

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { css, cx } from "emotion"; import { css, cx } from "emotion";
import { CSSTransition, TransitionGroup } from "react-transition-group"; import { CSSTransition, TransitionGroup } from "react-transition-group";
import { Box, Flex, DarkMode, Text } from "@chakra-ui/core"; import { Box, DarkMode, Flex, Text } from "@chakra-ui/core";
import { WarningIcon } from "@chakra-ui/icons"; import { WarningIcon } from "@chakra-ui/icons";
import HangerSpinner from "./HangerSpinner"; import HangerSpinner from "./HangerSpinner";
@ -25,10 +25,11 @@ function OutfitPreview({
speciesId, speciesId,
colorId, colorId,
pose, pose,
appearanceId = null,
wornItemIds, wornItemIds,
appearanceId = null,
placeholder, placeholder,
loadingDelay, loadingDelayMs,
spinnerVariant,
}) { }) {
const { loading, error, visibleLayers } = useOutfitAppearance({ const { loading, error, visibleLayers } = useOutfitAppearance({
speciesId, speciesId,
@ -55,15 +56,14 @@ function OutfitPreview({
} }
return ( return (
<DarkMode> <OutfitLayers
<OutfitLayers loading={loading || loading2}
loading={loading || loading2} visibleLayers={loadedLayers}
visibleLayers={loadedLayers} placeholder={placeholder}
placeholder={placeholder} loadingDelayMs={loadingDelayMs}
loadingDelay={loadingDelay} spinnerVariant={spinnerVariant}
doAnimations doAnimations
/> />
</DarkMode>
); );
} }
@ -75,13 +75,18 @@ export function OutfitLayers({
loading, loading,
visibleLayers, visibleLayers,
placeholder, placeholder,
loadingDelay = "0.5s", loadingDelayMs = 500,
spinnerVariant = "overlay",
doAnimations = false, doAnimations = false,
}) { }) {
const [isMounted, setIsMounted] = React.useState(false); const [loadingDelayHasPassed, setLoadingDelayHasPassed] = React.useState(
React.useLayoutEffect(() => { false
setIsMounted(true); );
}, []);
React.useEffect(() => {
const t = setTimeout(() => setLoadingDelayHasPassed(true), loadingDelayMs);
return () => clearTimeout(t);
}, [loadingDelayMs]);
return ( return (
<Box <Box
@ -164,24 +169,32 @@ export function OutfitLayers({
zIndex="9000" zIndex="9000"
// This is similar to our Delay util component, but Delay disappears // This is similar to our Delay util component, but Delay disappears
// immediately on load, whereas we want this to fade out smoothly. We // immediately on load, whereas we want this to fade out smoothly. We
// also delay the fade-in by 0.5s, but don't delay the fade-out at all. // also use a timeout to delay the fade-in by 0.5s, but don't delay the
// // fade-out at all. (The timeout was an awkward choice, it was hard to
// We also use `isMounted` here to make sure it actually _fades_ in! // find a good CSS way to specify this delay well!)
// (This starts the opacity at 0, then fires an immediate callback to opacity={loading && loadingDelayHasPassed ? 1 : 0}
// set it to 1, triggering the transition.) transition="opacity 0.2s"
opacity={isMounted && loading ? 1 : 0}
transition={`opacity 0.2s ${loading ? loadingDelay : "0s"}`}
> >
<Box {spinnerVariant === "overlay" && (
position="absolute" <>
top="0" <Box
left="0" position="absolute"
right="0" top="0"
bottom="0" left="0"
backgroundColor="gray.900" right="0"
opacity="0.7" bottom="0"
/> backgroundColor="gray.900"
<HangerSpinner /> opacity="0.7"
/>
{/* Against the dark overlay, use the Dark Mode spinner. */}
<DarkMode>
<HangerSpinner />
</DarkMode>
</>
)}
{spinnerVariant === "corner" && (
<HangerSpinner size="sm" position="absolute" bottom="2" right="2" />
)}
</FullScreenCenter> </FullScreenCenter>
</Box> </Box>
); );