(frontend) enhance document grid

- Updated the layout and styling of the DocsGrid and DocsGridItem
components for improved responsiveness and visual consistency.
- Added a new background prop to the UserAvatar component for
customizable user avatars.
- Enhanced the DocsGridActions component to include a share option,
allowing users to share documents easily.
- Refactored SVG assets for pinned and simple documents to improve their
dimensions and visual representation.
- Improved the SimpleDocItem component to display document update times
and access indicators more effectively.
- Adjusted padding and spacing across various components to enhance
overall user experience.
This commit is contained in:
Nathan Panchout
2024-12-23 10:26:51 +01:00
committed by Anthony LC
parent 72f234027c
commit 78b5e2c1cc
8 changed files with 82 additions and 48 deletions

View File

@@ -19,7 +19,8 @@ export const SeparatedSection = ({
return ( return (
<Box <Box
$css={css` $css={css`
padding: ${spacings['base']} 0; width: 100%;
padding: ${spacings['sm']} 0;
${showSeparator && ${showSeparator &&
css` css`
border-bottom: 1px solid ${colors?.['greyscale-200']}; border-bottom: 1px solid ${colors?.['greyscale-200']};

View File

@@ -1,7 +1,7 @@
<svg width="28" height="34" viewBox="0 0 28 34" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="32" height="36" viewBox="0 0 32 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2.01394" y="1.23611" width="25.9722" height="33.5278" rx="3.54167" fill="white"/> <rect x="2.01394" y="1.23611" width="25.9722" height="33.5278" rx="3.54167" fill="white"/>
<rect x="2.01394" y="1.23611" width="25.9722" height="33.5278" rx="3.54167" stroke="#DCDCFC" stroke-width="0.472222"/> <rect x="2.01394" y="1.23611" width="25.9722" height="33.5278" rx="3.54167" stroke="#E3E3FD" stroke-width="0.472222"/>
<path d="M6.5 8.55556H15" stroke="#6A6AF4" stroke-width="1.88889" stroke-linecap="round"/> <path d="M6.5 8.55554H15" stroke="#6A6AF4" stroke-width="1.88889" stroke-linecap="round"/>
<path d="M6.5 11.3889H23.5M6.5 14.2222H23.5M6.5 17.0556H23.5M6.5 19.8889H23.5M6.5 22.7222H20.6667" stroke="#CACAFB" stroke-width="1.88889" stroke-linecap="round"/> <path d="M6.5 11.3889H23.5M6.5 14.2222H23.5M6.5 17.0556H23.5M6.5 19.8889H23.5M6.5 22.7222H20.6667" stroke="#CACAFB" stroke-width="1.88889" stroke-linecap="round"/>
<rect x="7" y="10" width="16" height="16" rx="8" fill="#6A6AF4"/> <rect x="7" y="10" width="16" height="16" rx="8" fill="#6A6AF4"/>
<rect x="7" y="10" width="16" height="16" rx="8" stroke="white" stroke-width="1.5"/> <rect x="7" y="10" width="16" height="16" rx="8" stroke="white" stroke-width="1.5"/>

Before

Width:  |  Height:  |  Size: 853 B

After

Width:  |  Height:  |  Size: 853 B

View File

@@ -1,6 +1,6 @@
<svg width="28" height="34" viewBox="0 0 28 34" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="32" height="36" viewBox="0 0 32 36" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="1.01394" y="0.236111" width="25.9722" height="33.5278" rx="3.54167" fill="white"/> <rect x="2.01394" y="1.23611" width="25.9722" height="33.5278" rx="3.54167" fill="white"/>
<rect x="1.01394" y="0.236111" width="25.9722" height="33.5278" rx="3.54167" stroke="#DCDCFC" stroke-width="0.472222"/> <rect x="2.01394" y="1.23611" width="25.9722" height="33.5278" rx="3.54167" stroke="#E3E3FD" stroke-width="0.472222"/>
<path d="M5.5 7.55554H14" stroke="#6A6AF4" stroke-width="1.88889" stroke-linecap="round"/> <path d="M6.5 8.55554H15" stroke="#6A6AF4" stroke-width="1.88889" stroke-linecap="round"/>
<path d="M5.5 10.3889H22.5M5.5 13.2222H22.5M5.5 16.0556H22.5M5.5 18.8889H22.5M5.5 21.7222H22.5M5.5 24.5556H22.5M5.5 27.3889H22.5M5.5 30.2222H22.5M5.5 33.0556H22.5" stroke="#CACAFB" stroke-width="1.88889" stroke-linecap="round"/> <path d="M6.5 11.3889H23.5M6.5 14.2222H23.5M6.5 17.0556H23.5M6.5 19.8889H23.5M6.5 22.7222H20.6667" stroke="#CACAFB" stroke-width="1.88889" stroke-linecap="round"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 635 B

After

Width:  |  Height:  |  Size: 568 B

View File

@@ -29,15 +29,16 @@ const getColorFromName = (name: string) => {
type Props = { type Props = {
user: User; user: User;
background?: string;
}; };
export const UserAvatar = ({ user }: Props) => { export const UserAvatar = ({ user, background }: Props) => {
const name = user.full_name || user.email || '?'; const name = user.full_name || user.email || '?';
const splitName = name?.split(' '); const splitName = name?.split(' ');
return ( return (
<Box <Box
$background={getColorFromName(name)} $background={background || getColorFromName(name)}
$width="24px" $width="24px"
$height="24px" $height="24px"
$direction="row" $direction="row"

View File

@@ -53,37 +53,44 @@ export const DocsGrid = ({
return ( return (
<Box $position="relative" $width="100%" $maxWidth="960px"> <Box $position="relative" $width="100%" $maxWidth="960px">
<DocsGridLoader isLoading={isRefetching} /> <DocsGridLoader isLoading={isRefetching} />
<Card data-testid="docs-grid" $padding="md"> <Card
data-testid="docs-grid"
$padding={{
top: 'base',
horizontal: isDesktop ? 'md' : 'xs',
bottom: 'md',
}}
>
<Text <Text
as="h4" as="h4"
$size="h4" $size="h4"
$weight="700" $variation="1000"
$margin={{ top: '0px', bottom: 'xs' }} $margin={{ top: '0px', bottom: '10px' }}
> >
{title} {title}
</Text> </Text>
<Box> <Box $gap="6px">
<Box <Box
$direction="row" $direction="row"
$padding="xs" $padding={{ horizontal: 'xs' }}
$gap="20px" $gap="20px"
data-testid="docs-grid-header" data-testid="docs-grid-header"
> >
<Box $flex={6} $padding="3xs"> <Box $flex={6} $padding="3xs">
<Text $size="xs" $variation="600"> <Text $size="xs" $variation="600" $weight="500">
{t('Name')} {t('Name')}
</Text> </Text>
</Box> </Box>
{isDesktop && ( {isDesktop && (
<Box $flex={1.3} $padding="3xs"> <Box $flex={2} $padding="3xs">
<Text $size="xs" $variation="600"> <Text $size="xs" $weight="500" $variation="600">
{t('Updated at')} {t('Updated at')}
</Text> </Text>
</Box> </Box>
)} )}
<Box $flex={1} $align="flex-end" $padding="3xs" /> <Box $flex={1.15} $align="flex-end" $padding="3xs" />
</Box> </Box>
{/* Body */} {/* Body */}

View File

@@ -13,11 +13,16 @@ import { useDeleteFavoriteDoc } from '../../doc-management/api/useDeleteFavorite
interface DocsGridActionsProps { interface DocsGridActionsProps {
doc: Doc; doc: Doc;
openShareModal?: () => void;
} }
export const DocsGridActions = ({ doc }: DocsGridActionsProps) => { export const DocsGridActions = ({
doc,
openShareModal,
}: DocsGridActionsProps) => {
const { t } = useTranslation(); const { t } = useTranslation();
const deleteModal = useModal(); const deleteModal = useModal();
const removeFavoriteDoc = useDeleteFavoriteDoc({ const removeFavoriteDoc = useDeleteFavoriteDoc({
listInvalideQueries: [KEY_LIST_DOC], listInvalideQueries: [KEY_LIST_DOC],
}); });
@@ -38,6 +43,13 @@ export const DocsGridActions = ({ doc }: DocsGridActionsProps) => {
}, },
testId: `docs-grid-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`, testId: `docs-grid-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
}, },
{
label: t('Share'),
icon: 'group',
callback: () => openShareModal?.(),
testId: `docs-grid-actions-share-${doc.id}`,
},
{ {
label: t('Remove'), label: t('Remove'),
icon: 'delete', icon: 'delete',

View File

@@ -36,7 +36,7 @@ export const DocsGridItem = ({ doc }: DocsGridItemProps) => {
$align="center" $align="center"
$gap="20px" $gap="20px"
role="row" role="row"
$padding={{ vertical: 'xs', horizontal: 'sm' }} $padding={{ vertical: '2xs', horizontal: isDesktop ? 'base' : 'xs' }}
$css={css` $css={css`
cursor: pointer; cursor: pointer;
border-radius: 4px; border-radius: 4px;
@@ -46,7 +46,7 @@ export const DocsGridItem = ({ doc }: DocsGridItemProps) => {
`} `}
> >
<StyledLink <StyledLink
$css="flex: 7; align-items: center;" $css="flex: 8; align-items: center;"
href={`/docs/${doc.id}`} href={`/docs/${doc.id}`}
> >
<Box <Box
@@ -57,19 +57,19 @@ export const DocsGridItem = ({ doc }: DocsGridItemProps) => {
<SimpleDocItem isPinned={doc.is_favorite} doc={doc} /> <SimpleDocItem isPinned={doc.is_favorite} doc={doc} />
</Box> </Box>
{isDesktop && ( {isDesktop && (
<Box $flex={1.3}> <Box $flex={2}>
<Text $variation="500" $size="xs"> <Text $variation="600" $size="xs">
{DateTime.fromISO(doc.updated_at).toRelative()} {DateTime.fromISO(doc.updated_at).toRelative()}
</Text> </Text>
</Box> </Box>
)} )}
</StyledLink> </StyledLink>
<Box <Box
$flex={1} $flex={1.15}
$direction="row" $direction="row"
$align="center" $align="center"
$justify="flex-end" $justify="flex-end"
$gap="10px" $gap="32px"
> >
{isDesktop && isPublic && ( {isDesktop && isPublic && (
<Button <Button
@@ -79,6 +79,7 @@ export const DocsGridItem = ({ doc }: DocsGridItemProps) => {
handleShareClick(); handleShareClick();
}} }}
size="nano" size="nano"
fullWidth
icon={<Icon $variation="000" iconName="public" />} icon={<Icon $variation="000" iconName="public" />}
> >
{isShared ? sharedCount : undefined} {isShared ? sharedCount : undefined}
@@ -91,6 +92,7 @@ export const DocsGridItem = ({ doc }: DocsGridItemProps) => {
event.stopPropagation(); event.stopPropagation();
handleShareClick(); handleShareClick();
}} }}
fullWidth
color="tertiary" color="tertiary"
size="nano" size="nano"
icon={<Icon $variation="800" $theme="primary" iconName="group" />} icon={<Icon $variation="800" $theme="primary" iconName="group" />}
@@ -105,13 +107,14 @@ export const DocsGridItem = ({ doc }: DocsGridItemProps) => {
event.stopPropagation(); event.stopPropagation();
handleShareClick(); handleShareClick();
}} }}
fullWidth
size="nano" size="nano"
icon={<Icon $variation="000" iconName="corporate_fare" />} icon={<Icon $variation="000" iconName="corporate_fare" />}
> >
{sharedCount} {sharedCount}
</Button> </Button>
)} )}
<DocsGridActions doc={doc} /> <DocsGridActions doc={doc} openShareModal={handleShareClick} />
</Box> </Box>
</Box> </Box>
{shareModal.isOpen && ( {shareModal.isOpen && (

View File

@@ -1,3 +1,4 @@
import { DateTime } from 'luxon';
import { css } from 'styled-components'; import { css } from 'styled-components';
import { Box, Icon, Text } from '@/components'; import { Box, Icon, Text } from '@/components';
@@ -20,14 +21,12 @@ const ItemTextCss = css`
type SimpleDocItemProps = { type SimpleDocItemProps = {
doc: Doc; doc: Doc;
isPinned?: boolean; isPinned?: boolean;
subText?: string;
showAccesses?: boolean; showAccesses?: boolean;
}; };
export const SimpleDocItem = ({ export const SimpleDocItem = ({
doc, doc,
isPinned = false, isPinned = false,
subText,
showAccesses = false, showAccesses = false,
}: SimpleDocItemProps) => { }: SimpleDocItemProps) => {
const { spacingsTokens } = useCunninghamTheme(); const { spacingsTokens } = useCunninghamTheme();
@@ -51,7 +50,7 @@ export const SimpleDocItem = ({
> >
{isPinned ? <PinnedDocumentIcon /> : <SimpleFileIcon />} {isPinned ? <PinnedDocumentIcon /> : <SimpleFileIcon />}
</Box> </Box>
<Box> <Box $justify="center">
<Text <Text
aria-describedby="doc-title" aria-describedby="doc-title"
aria-label={doc.title} aria-label={doc.title}
@@ -62,23 +61,34 @@ export const SimpleDocItem = ({
> >
{doc.title} {doc.title}
</Text> </Text>
<Box $direction="row" $align="center" $gap={spacings['3xs']}> {(!isDesktop || showAccesses) && (
{(!isDesktop || showAccesses) && ( <Box
<> $direction="row"
{isPublic && <Icon iconName="public" $size="16px" />} $align="center"
{isShared && <Icon iconName="group" $size="16px" />} $gap={spacings['3xs']}
{isSharedOrPublic && accessCount > 0 && ( $margin={{ top: '-2px' }}
<Text $size="12px">{accessCount}</Text> >
)} {isPublic && (
{isSharedOrPublic && <Text $size="12px">·</Text>} <Icon iconName="public" $size="16px" $variation="600" />
</> )}
)} {isShared && (
<Icon iconName="group" $size="16px" $variation="600" />
<Text $size="xs" $variation="500" $weight="500" $css={ItemTextCss}> )}
{subText ?? {isSharedOrPublic && accessCount > 0 && (
'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi vel ante libero. Interdum et malesuada fames ac ante ipsum primis in faucibus. Sed imperdiet neque quam, sed euismod metus mollis ut. '} <Text $size="12px" $weight="bold" $variation="600">
</Text> {accessCount}
</Box> </Text>
)}
{isSharedOrPublic && (
<Text $size="12px" $variation="600">
·
</Text>
)}
<Text $variation="600" $size="xs">
{DateTime.fromISO(doc.updated_at).toRelative()}
</Text>
</Box>
)}
</Box> </Box>
</Box> </Box>
); );