diff --git a/src/app/WardrobePage/OutfitControls.js b/src/app/WardrobePage/OutfitControls.js index 4da96ef..3ea60be 100644 --- a/src/app/WardrobePage/OutfitControls.js +++ b/src/app/WardrobePage/OutfitControls.js @@ -6,6 +6,7 @@ import { DarkMode, Flex, IconButton, + Portal, Stack, Tooltip, useClipboard, @@ -255,29 +256,111 @@ function CopyLinkButton({ outfitState }) { function PlayPauseButton() { const [isPaused, setIsPaused] = useLocalStorage("DTIOutfitIsPaused", true); + // We show an intro animation if this mounts while paused. Whereas if we're + // not paused, we initialize as if we had already finished. + const [blinkInState, setBlinkInState] = React.useState( + isPaused ? { type: "ready" } : { type: "done" } + ); + const buttonRef = React.useRef(null); + + React.useLayoutEffect(() => { + if (blinkInState.type === "ready" && buttonRef.current) { + setBlinkInState({ + type: "started", + position: { + left: buttonRef.current.offsetLeft, + top: buttonRef.current.offsetTop, + }, + }); + } + }, [blinkInState, setBlinkInState]); + return ( - + <> + + {blinkInState.type === "started" && ( + + setBlinkInState({ type: "done" })} + // Don't disrupt the hover state of the controls! (And the button + // doesn't seem to click correctly, not sure why, but instead of + // debugging I'm adding this :p) + pointerEvents="none" + className={css` + @keyframes fade-in-out { + 0% { + opacity: 0; + } + + 10% { + opacity: 1; + } + + 90% { + opacity: 1; + } + + 100% { + opacity: 0; + } + } + + opacity: 0; + animation: fade-in-out 2s; + `} + /> + + )} + ); } +const PlayPauseButtonContent = React.forwardRef( + ({ isPaused, setIsPaused, ...props }, ref) => { + return ( + + ); + } +); + /** * ControlButton is a UI helper to render the cute round buttons we use in * OutfitControls!