Lucas/t 366 on comment drawer when i have comments on the selected (#201)

* Fixed right drawer width and shared in theme

* Added date packages and tooltip

* Added date utils and tests

* Added comment thread components

* Fixed comment chip

* Fix from rebase

* Fix from rebase

* Fix margin right

* Fixed CSS and graphql
This commit is contained in:
Lucas Bordeau
2023-06-07 12:48:44 +02:00
committed by GitHub
parent b1bf050936
commit 5e2673a2a4
30 changed files with 688 additions and 77 deletions

View File

@ -4,7 +4,7 @@ import { CommentChip, CommentChipProps } from './CommentChip';
const StyledCellWrapper = styled.div`
position: relative;
right: 38px;
right: 34px;
top: -13px;
width: 0;
height: 0;

View File

@ -9,18 +9,18 @@ export type CommentChipProps = {
const StyledChip = styled.div`
height: 26px;
min-width: 34px;
width: fit-content;
padding-left: 2px;
padding-right: 2px;
padding-left: 4px;
padding-right: 4px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: row;
gap: 2px;
gap: 4px;
background: ${(props) => props.theme.secondaryBackgroundTransparent};
background: ${(props) => props.theme.primaryBackgroundTransparent};
backdrop-filter: blur(6px);
border-radius: ${(props) => props.theme.borderRadius};
@ -53,7 +53,7 @@ export function CommentChip({ count, onClick }: CommentChipProps) {
return (
<StyledChip data-testid="comment-chip" onClick={onClick}>
<StyledCount>{formattedCount}</StyledCount>
<IconComment size={12} />
<IconComment size={16} />
</StyledChip>
);
}

View File

@ -0,0 +1,80 @@
import { Tooltip } from 'react-tooltip';
import styled from '@emotion/styled';
import { UserAvatar } from '@/users/components/UserAvatar';
import {
beautifyExactDate,
beautifyPastDateRelativeToNow,
} from '@/utils/datetime/date-utils';
type OwnProps = {
avatarUrl: string | null | undefined;
username: string;
createdAt: Date;
};
const StyledContainer = styled.div`
display: flex;
align-items: center;
flex-direction: row;
justify-content: flex-start;
padding: ${(props) => props.theme.spacing(1)};
gap: ${(props) => props.theme.spacing(1)};
`;
const StyledName = styled.div`
font-size: 13px;
font-weight: 400;
color: ${(props) => props.theme.text80};
`;
const StyledDate = styled.div`
font-size: 12px;
font-weight: 400;
color: ${(props) => props.theme.text30};
padding-top: 1.5px;
margin-left: ${(props) => props.theme.spacing(1)};
`;
const StyledTooltip = styled(Tooltip)`
padding: 8px;
`;
export function CommentHeader({ avatarUrl, username, createdAt }: OwnProps) {
const beautifiedCreatedAt = beautifyPastDateRelativeToNow(createdAt);
const exactCreatedAt = beautifyExactDate(createdAt);
const showDate = beautifiedCreatedAt !== '';
const capitalizedFirstUsernameLetter =
username !== '' ? username.toLocaleUpperCase()[0] : '';
return (
<StyledContainer>
<UserAvatar
avatarUrl={avatarUrl}
size={16}
placeholderLetter={capitalizedFirstUsernameLetter}
/>
<StyledName>{username}</StyledName>
{showDate && (
<>
<StyledDate className="comment-created-at">
{beautifiedCreatedAt}
</StyledDate>
<StyledTooltip
anchorSelect=".comment-created-at"
content={exactCreatedAt}
clickable
noArrow
/>
</>
)}
</StyledContainer>
);
}

View File

@ -1,27 +1,37 @@
import styled from '@emotion/styled';
import { CommentThreadForDrawer } from '@/comments/types/CommentThreadForDrawer';
import { CommentTextInput } from './CommentTextInput';
import { CommentThreadItem } from './CommentThreadItem';
type OwnProps = {
commentThread: CommentThreadForDrawer;
};
const StyledContainer = styled.div`
display: flex;
align-items: flex-start;
flex-direction: column;
justify-content: flex-start;
gap: ${(props) => props.theme.spacing(4)};
padding: ${(props) => props.theme.spacing(2)};
`;
export function CommentThread({ commentThread }: OwnProps) {
function handleSendComment(text: string) {
console.log(text);
}
return (
<div>
<StyledContainer>
{commentThread.comments?.map((comment) => (
<div key={comment.id}>
<div>
{comment.author?.displayName} - {comment.createdAt}
</div>
<div>{comment.body}</div>
</div>
<CommentThreadItem key={comment.id} comment={comment} />
))}
<CommentTextInput onSend={handleSendComment} />
</div>
</StyledContainer>
);
}

View File

@ -0,0 +1,40 @@
import styled from '@emotion/styled';
import { CommentForDrawer } from '@/comments/types/CommentForDrawer';
import { CommentHeader } from './CommentHeader';
type OwnProps = {
comment: CommentForDrawer;
};
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
gap: ${(props) => props.theme.spacing(1)};
`;
const StyledCommentBody = styled.div`
font-size: ${(props) => props.theme.fontSizeMedium};
line-height: 19.5px;
text-align: left;
padding-left: 24px;
color: ${(props) => props.theme.text60};
`;
export function CommentThreadItem({ comment }: OwnProps) {
return (
<StyledContainer>
<CommentHeader
avatarUrl={comment.author.avatarUrl}
username={comment.author.displayName}
createdAt={comment.createdAt}
/>
<StyledCommentBody>{comment.body}</StyledCommentBody>
</StyledContainer>
);
}

View File

@ -7,7 +7,7 @@ import { CellCommentChip } from '../CellCommentChip';
import { CommentChip } from '../CommentChip';
const meta: Meta<typeof CellCommentChip> = {
title: 'Components/CellCommentChip',
title: 'Components/Comments/CellCommentChip',
component: CellCommentChip,
};

View File

@ -0,0 +1,67 @@
import type { Meta, StoryObj } from '@storybook/react';
import { DateTime } from 'luxon';
import { mockedUsersData } from '~/testing/mock-data/users';
import { getRenderWrapperForComponent } from '~/testing/renderWrappers';
import { CommentHeader } from '../CommentHeader';
const meta: Meta<typeof CommentHeader> = {
title: 'Components/Comments/CommentHeader',
component: CommentHeader,
};
export default meta;
type Story = StoryObj<typeof CommentHeader>;
const mockUser = mockedUsersData[0];
export const Default: Story = {
render: getRenderWrapperForComponent(
<CommentHeader
avatarUrl={mockUser.avatarUrl ?? ''}
username={mockUser.displayName ?? ''}
createdAt={DateTime.now().minus({ hours: 2 }).toJSDate()}
/>,
),
};
export const FewDaysAgo: Story = {
render: getRenderWrapperForComponent(
<CommentHeader
avatarUrl={mockUser.avatarUrl ?? ''}
username={mockUser.displayName ?? ''}
createdAt={DateTime.now().minus({ days: 2 }).toJSDate()}
/>,
),
};
export const FewMonthsAgo: Story = {
render: getRenderWrapperForComponent(
<CommentHeader
avatarUrl={mockUser.avatarUrl ?? ''}
username={mockUser.displayName ?? ''}
createdAt={DateTime.now().minus({ months: 2 }).toJSDate()}
/>,
),
};
export const FewYearsAgo: Story = {
render: getRenderWrapperForComponent(
<CommentHeader
avatarUrl={mockUser.avatarUrl ?? ''}
username={mockUser.displayName ?? ''}
createdAt={DateTime.now().minus({ years: 2 }).toJSDate()}
/>,
),
};
export const WithoutAvatar: Story = {
render: getRenderWrapperForComponent(
<CommentHeader
avatarUrl={''}
username={mockUser.displayName ?? ''}
createdAt={DateTime.now().minus({ hours: 2 }).toJSDate()}
/>,
),
};

View File

@ -6,7 +6,7 @@ import { getRenderWrapperForComponent } from '~/testing/renderWrappers';
import { CommentTextInput } from '../CommentTextInput';
const meta: Meta<typeof CommentTextInput> = {
title: 'Components/CommentTextInput',
title: 'Components/Comments/CommentTextInput',
component: CommentTextInput,
argTypes: {
onSend: {