click to toggle outfit controls on mobile
On mobile, it was pretty annoying that you had to show the controls by tapping the preview area to simulate a hover—because it could also click the underlying elements, and do bad stuff! Here, I add a click capture to prevent the clicks from going down if the controls aren't visible. And I add a toggle, so that you can dismiss the controls, like how YouTube feels :)
This commit is contained in:
parent
1efc1c0d42
commit
90b4fc8da4
1 changed files with 37 additions and 4 deletions
|
@ -62,6 +62,14 @@ function OutfitControls({ outfitState, dispatchToOutfit }) {
|
||||||
[dispatchToOutfit, toast]
|
[dispatchToOutfit, toast]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const maybeUnlockFocus = (e) => {
|
||||||
|
// We lock focus when a touch-device user taps the area. When they tap
|
||||||
|
// empty space, we treat that as a toggle and release the focus lock.
|
||||||
|
if (e.target === e.currentTarget) {
|
||||||
|
onUnlockFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
role="group"
|
role="group"
|
||||||
|
@ -83,16 +91,40 @@ function OutfitControls({ outfitState, dispatchToOutfit }) {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.2s;
|
transition: opacity 0.2s;
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus-within,
|
&:focus-within,
|
||||||
&.focus-is-locked {
|
&.focus-is-locked {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Ignore simulated hovers, only reveal for _real_ hovers. This helps
|
||||||
|
* us avoid state conflicts with the focus-lock from clicks. */
|
||||||
|
@media (hover: hover) {
|
||||||
|
&:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
focusIsLocked && "focus-is-locked"
|
focusIsLocked && "focus-is-locked"
|
||||||
)}
|
)}
|
||||||
|
onClickCapture={(e) => {
|
||||||
|
const opacity = parseFloat(getComputedStyle(e.currentTarget).opacity);
|
||||||
|
if (opacity < 0.5) {
|
||||||
|
// If the controls aren't visible right now, then clicks on them are
|
||||||
|
// probably accidental. Ignore them! (We prevent default to block
|
||||||
|
// built-in behaviors like link nav, and we stop propagation to block
|
||||||
|
// our own custom click handlers. I don't know if I can prevent the
|
||||||
|
// select clicks though?)
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
// We also show the controls, by locking focus. We'll undo this when
|
||||||
|
// the user taps elsewhere (because it will trigger a blur event from
|
||||||
|
// our child components), in `maybeUnlockFocus`.
|
||||||
|
setFocusIsLocked(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Box gridArea="back">
|
<Box gridArea="back" onClick={maybeUnlockFocus}>
|
||||||
<ControlButton
|
<ControlButton
|
||||||
as={Link}
|
as={Link}
|
||||||
to="/"
|
to="/"
|
||||||
|
@ -106,6 +138,7 @@ function OutfitControls({ outfitState, dispatchToOutfit }) {
|
||||||
alignSelf="flex-end"
|
alignSelf="flex-end"
|
||||||
spacing={{ base: "2", lg: "4" }}
|
spacing={{ base: "2", lg: "4" }}
|
||||||
align="flex-end"
|
align="flex-end"
|
||||||
|
onClick={maybeUnlockFocus}
|
||||||
>
|
>
|
||||||
<Box>
|
<Box>
|
||||||
<DownloadButton outfitState={outfitState} />
|
<DownloadButton outfitState={outfitState} />
|
||||||
|
@ -114,8 +147,8 @@ function OutfitControls({ outfitState, dispatchToOutfit }) {
|
||||||
<CopyLinkButton outfitState={outfitState} />
|
<CopyLinkButton outfitState={outfitState} />
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Box gridArea="space" />
|
<Box gridArea="space" onClick={maybeUnlockFocus} />
|
||||||
<Flex gridArea="picker" justify="center">
|
<Flex gridArea="picker" justify="center" onClick={maybeUnlockFocus}>
|
||||||
{/**
|
{/**
|
||||||
* We try to center the species/color picker, but the left spacer will
|
* We try to center the species/color picker, but the left spacer will
|
||||||
* shrink more than the pose picker container if we run out of space!
|
* shrink more than the pose picker container if we run out of space!
|
||||||
|
|
Loading…
Reference in a new issue