embed item page in wardrobe page drawer

This commit is contained in:
Emi Matchu 2020-09-12 19:29:20 -07:00
parent 056b238462
commit dcf2ec6a26
5 changed files with 77 additions and 27 deletions

View file

@ -23,16 +23,24 @@ import OutfitPreview from "./components/OutfitPreview";
function ItemPage() {
const { itemId } = useParams();
return <ItemPageContent itemId={itemId} />;
}
/**
* ItemPageContent is the content of ItemPage, but we also use it as the
* entry point for ItemPageDrawer! When embedded in ItemPageDrawer, the
* `isEmbedded` prop is true, so we know not to e.g. set the page title.
*/
export function ItemPageContent({ itemId, isEmbedded }) {
return (
<VStack spacing="6">
<ItemPageHeader itemId={itemId} />
<ItemPageHeader itemId={itemId} isEmbedded={isEmbedded} />
<ItemPageOutfitPreview itemId={itemId} />
</VStack>
);
}
function ItemPageHeader({ itemId }) {
function ItemPageHeader({ itemId, isEmbedded }) {
const { error, data } = useQuery(
gql`
query ItemPage($itemId: ID!) {
@ -47,7 +55,7 @@ function ItemPageHeader({ itemId }) {
{ variables: { itemId }, returnPartialData: true }
);
usePageTitle(data?.item?.name);
usePageTitle(data?.item?.name, { skip: isEmbedded });
if (error) {
return <Box color="red.400">{error.message}</Box>;
@ -67,7 +75,14 @@ function ItemPageHeader({ itemId }) {
</Skeleton>
<Box>
<Skeleton isLoaded={item?.name}>
<Heading1 lineHeight="1.1">{item?.name || "Item name here"}</Heading1>
<Heading1
lineHeight="1.1"
// Nudge down the size a bit in the embed case, to better fit the
// tighter layout!
size={isEmbedded ? "xl" : "2xl"}
>
{item?.name || "Item name here"}
</Heading1>
</Skeleton>
<ItemPageBadges item={item} />
</Box>
@ -131,7 +146,7 @@ function ItemPageBadges({ item }) {
encodeURIComponent(item.name)
}
>
Trades
Trade Post
</LinkBadge>
)}
</Skeleton>

30
src/app/ItemPageDrawer.js Normal file
View file

@ -0,0 +1,30 @@
import React from "react";
import {
Drawer,
DrawerBody,
DrawerContent,
DrawerCloseButton,
DrawerOverlay,
useBreakpointValue,
} from "@chakra-ui/core";
import { ItemPageContent } from "./ItemPage";
function ItemPageDrawer({ item, isOpen, onClose }) {
const placement = useBreakpointValue({ base: "bottom", lg: "right" });
return (
<Drawer placement={placement} size="md" isOpen={isOpen} onClose={onClose}>
<DrawerOverlay>
<DrawerContent>
<DrawerCloseButton />
<DrawerBody>
<ItemPageContent itemId={item.id} isEmbedded />
</DrawerBody>
</DrawerContent>
</DrawerOverlay>
</Drawer>
);
}
export default ItemPageDrawer;

View file

@ -16,6 +16,7 @@ import {
InfoIcon,
NotAllowedIcon,
} from "@chakra-ui/icons";
import { Link } from "react-router-dom";
import loadable from "@loadable/component";
import {
@ -27,6 +28,7 @@ import {
} from "../components/ItemCard";
import SupportOnly from "./support/SupportOnly";
const LoadableItemPageDrawer = loadable(() => import("../ItemPageDrawer"));
const LoadableItemSupportDrawer = loadable(() =>
import("./support/ItemSupportDrawer")
);
@ -58,6 +60,7 @@ function Item({
onRemove,
isDisabled = false,
}) {
const [infoDrawerIsOpen, setInfoDrawerIsOpen] = React.useState(false);
const [supportDrawerIsOpen, setSupportDrawerIsOpen] = React.useState(false);
return (
@ -97,13 +100,25 @@ function Item({
<ItemActionButton
icon={<InfoIcon />}
label="More info"
href={`https://impress.openneo.net/items/${
item.id
}-${item.name.replace(/ /g, "-")}`}
onClick={(e) => e.stopPropagation()}
to={`/items/${item.id}`}
onClick={(e) => {
const willProbablyOpenInNewTab =
e.metaKey || e.shiftKey || e.altKey || e.ctrlKey;
if (willProbablyOpenInNewTab) {
return;
}
setInfoDrawerIsOpen(true);
e.preventDefault();
}}
/>
</Box>
</ItemContainer>
<LoadableItemPageDrawer
item={item}
isOpen={infoDrawerIsOpen}
onClose={() => setInfoDrawerIsOpen(false)}
/>
<SupportOnly>
<LoadableItemSupportDrawer
item={item}
@ -220,7 +235,7 @@ function ItemBadges({ item }) {
/**
* ItemActionButton is one of a list of actions a user can take for this item.
*/
function ItemActionButton({ icon, label, href, onClick }) {
function ItemActionButton({ icon, label, to, onClick }) {
const theme = useTheme();
const focusBackgroundColor = useColorModeValue(
@ -235,13 +250,12 @@ function ItemActionButton({ icon, label, href, onClick }) {
return (
<Tooltip label={label} placement="top">
<IconButton
as={href ? "a" : "button"}
as={to ? Link : "button"}
icon={icon}
aria-label={label}
variant="ghost"
color="gray.400"
href={href}
target={href ? "_blank" : null}
to={to}
onClick={onClick}
className={css`
opacity: 0;

View file

@ -41,22 +41,12 @@ import useSupport from "./useSupport";
* from another lazy-loaded component!
*/
function ItemSupportDrawer({ item, isOpen, onClose }) {
const placement = useBreakpointValue({
base: "bottom",
lg: "right",
// TODO: There's a bug in the Chakra RC that doesn't read the breakpoint
// specification correctly - we need these extra keys until it's fixed!
// https://github.com/chakra-ui/chakra-ui/issues/1444
0: "bottom",
1: "bottom",
2: "right",
3: "right",
});
const placement = useBreakpointValue({ base: "bottom", lg: "right" });
return (
<Drawer
placement={placement}
size="md"
isOpen={isOpen}
onClose={onClose}
// blockScrollOnMount doesn't matter on our fullscreen UI, but the

View file

@ -111,10 +111,11 @@ export function useDebounce(
/**
* usePageTitle sets the page title!
*/
export function usePageTitle(title) {
export function usePageTitle(title, { skip = false } = {}) {
React.useEffect(() => {
if (skip) return;
document.title = title ? `${title} | Dress to Impress` : "Dress to Impress";
}, [title]);
}, [title, skip]);
}
/**