Update Quest Tiles layout

Change LinkOverlay to link
Pass a size to SquareImage
Style of heading matches new design
Take out the read more button and related code
Alignment of description, roles tags, and skills tags
TODO(HHH-GH): the hydration error, look at why a description can be blank
This commit is contained in:
HHH-GH
2023-04-18 11:23:55 +08:00
committed by Alec LaLonde
parent b16f45d8d6
commit 20660aed9e

View File

@@ -2,29 +2,26 @@ import {
Box,
Flex,
Heading,
LinkBox,
LinkOverlay,
MetaButton,
Link,
MetaTile,
MetaTileBody,
MetaTileHeader,
Prose,
Text,
VStack,
} from '@metafam/ds';
import { httpLink, isSGML, Maybe } from '@metafam/utils';
import { httpLink, isSGML } from '@metafam/utils';
import BackgroundImage from 'assets/quests/quest.webp';
import { MarkdownViewer as Markdown } from 'components/MarkdownViewer';
import { RolesTags } from 'components/Quest/Roles';
import { SkillsTags } from 'components/Quest/Skills';
import { SquareImage } from 'components/SquareImage';
import { PlayerRole, QuestFragment, Skill } from 'graphql/autogen/types';
import React, { PropsWithChildren, useEffect, useRef } from 'react';
import React, { PropsWithChildren } from 'react';
import { safelyParseNChakrifyHtml } from 'utils/stringHelpers';
export const TileHeading: React.FC<PropsWithChildren> = ({ children }) => (
<Text as="h3" textStyle="caption" pb={1}>
{children}
</Text>
<Text textStyle="caption">{children}</Text>
);
type Props = {
@@ -37,101 +34,99 @@ export const QuestTile: React.FC<Props> = ({ quest }) => {
const parsedDescription = descIsHtml
? safelyParseNChakrifyHtml(description)
: null;
const descriptionRef = useRef<Maybe<HTMLDivElement>>(null);
const [clamped, setClamped] = React.useState(false);
const descriptionContent = descriptionRef.current?.textContent;
useEffect(() => {
const handleResize = () => {
const desc = descriptionRef.current;
if (desc) {
setClamped(desc.scrollHeight > desc.clientHeight);
}
};
window.addEventListener('resize', handleResize);
handleResize();
return () => window.removeEventListener('resize', handleResize);
}, [descriptionContent]);
return (
<LinkBox>
<LinkOverlay href={`/quest/${quest.id}`} w="full" justifyContent="center">
<MetaTile height="full" width="full">
<MetaTileHeader>
<SquareImage src={httpLink(quest.image) ?? BackgroundImage.src} />
<Flex justify="center" position="absolute" bottom="-15%" w="full">
<Heading
zIndex={3}
size="lg"
color="white"
bgColor="whiteAlpha.300"
backdropFilter="blur(10px)"
lineHeight={1.1}
px={3}
py={1}
mb={8}
textAlign="center"
borderRadius={10}
fontFamily="body"
fontWeight="normal"
noOfLines={3}
>
{quest.title}
</Heading>
</Flex>
</MetaTileHeader>
<MetaTileBody>
<Flex direction="column">
<Box pb={2}>
<Link
role="group"
_hover={{ textDecoration: 'none' }}
href={`/quest/${quest.id}`}
>
<MetaTile minW={'300px'} height="full" width="full" cursor="pointer">
<MetaTileHeader>
<SquareImage
src={httpLink(quest.image) ?? BackgroundImage.src}
size="xl"
/>
<Flex px={5} w="full" pos="absolute" bottom={-6} zIndex={1}>
<Heading
fontSize="3xl"
color="white"
bgColor="whiteAlpha.100"
backdropFilter="blur(10px)"
lineHeight={1.1}
px={4}
py={3}
width="full"
textAlign="center"
borderRadius={10}
fontFamily="body"
fontWeight={400}
textShadow="0 0 8px var(--chakra-colors-blackAlpha-400)" // v. light shadow makes the text readable if the logo/avatar is white
noOfLines={2}
>
{quest.title}
</Heading>
</Flex>
</MetaTileHeader>
<MetaTileBody>
<Flex
direction="column"
gap={4}
mt={2}
px={2}
pb={2}
height="full"
justifyItems="space-between"
>
{(description || parsedDescription) && (
<VStack align="left" spacing={1}>
<TileHeading>Description</TileHeading>
<Box noOfLines={3} ref={descriptionRef}>
<Box fontSize="md" noOfLines={4} mt={0}>
{descIsHtml ? (
<Prose>{parsedDescription}</Prose>
) : (
<Markdown>{description}</Markdown>
)}
</Box>
{clamped && (
<Flex justifyContent="end" mr={5}>
<MetaButton
href={`/quest/${quest.id}`}
h="auto"
size="sm"
px={3}
py={1}
>
Read More
</MetaButton>
</Flex>
)}
</Box>
<Box pb={2}>
<TileHeading>Skills</TileHeading>
<SkillsTags
skills={
quest.quest_skills.map(({ skill }) => skill) as Skill[]
}
/>
</Box>
<Box pb={2}>
<TileHeading>Roles</TileHeading>
{quest.quest_roles.length > 0 ? (
<RolesTags
roles={
quest.quest_roles.map(
({ PlayerRole: r }) => r,
) as PlayerRole[]
}
/>
) : (
<Text>None</Text>
)}
</Box>
</Flex>
</MetaTileBody>
</MetaTile>
</LinkOverlay>
</LinkBox>
</VStack>
)}
<VStack align="left" gap={1} mt="auto">
{quest.quest_skills.length > 0 && (
<>
<VStack align="left" spacing={1}>
<TileHeading>Skills</TileHeading>
<Box>
<SkillsTags
skills={
quest.quest_skills.map(
({ skill }) => skill,
) as Skill[]
}
/>
</Box>
</VStack>
</>
)}
{quest.quest_roles.length > 0 && (
<VStack align="left" spacing={1}>
<TileHeading>Roles</TileHeading>
<Box>
<RolesTags
roles={
quest.quest_roles.map(
({ PlayerRole: r }) => r,
) as PlayerRole[]
}
/>
</Box>
</VStack>
)}
</VStack>
</Flex>
</MetaTileBody>
</MetaTile>
</Link>
);
};