Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 꿀조합 상세 페이지 디자인 마이그레이션 #71

Merged
merged 31 commits into from
Apr 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6ec7c71
feat: 박스 svg icon 추가
xodms0309 Mar 20, 2024
9aaa7cc
style: PageHeader import문 추가
xodms0309 Mar 20, 2024
c33a49f
feat: RecipeFavoriteButton 컴포넌트 디자인 수정
xodms0309 Mar 20, 2024
c9359d4
feat: 꿀조합 상세 페이지 디자인 수정
xodms0309 Mar 20, 2024
ff2ac0d
feat: 댓글 리스트 스타일 마이그레이션
xodms0309 Mar 23, 2024
1fc7105
feat: 댓글작성폼 스타일 마이그레이션
xodms0309 Mar 23, 2024
73207e0
fix: className 수정
xodms0309 Mar 23, 2024
fdd166b
Merge remote-tracking branch 'origin/feat/v2' into feat/issue-59
xodms0309 Mar 23, 2024
f5a7463
feat: 꿀조합 상세 페이지 title 스타일 수정
xodms0309 Mar 23, 2024
9b5c016
feat: line height global style로 적용
xodms0309 Mar 23, 2024
826c9b9
Merge remote-tracking branch 'origin/feat/v2' into feat/issue-59
xodms0309 Apr 1, 2024
24faade
feat: plane 아이콘 교체
xodms0309 Apr 1, 2024
c317c40
style: 린트 적용
xodms0309 Apr 1, 2024
9e9cd24
feat: 댓글창 스타일 마이그레이션
xodms0309 Apr 1, 2024
667b0e5
feat: section title 컴포넌트 디자인 마이그레이션
xodms0309 Apr 1, 2024
d5229c1
feat: 꿀조합 상세페이지 Text 컴포넌트와 SectionTitle 컴포넌트로 교체
xodms0309 Apr 1, 2024
b8274db
feat: RecipeDetail 타입 변경
xodms0309 Apr 1, 2024
c716be5
feat: 사용한 상품 바텀시트 적용
xodms0309 Apr 1, 2024
5c3dcfd
fix: 사진을 사용자의 프로필 사진으로 교체
xodms0309 Apr 7, 2024
5839161
refactor: CommentItem의 텍스트를 Text 컴포넌트로 교체
xodms0309 Apr 7, 2024
ce6c61c
feat: borderRadius 삭제
xodms0309 Apr 7, 2024
adcd805
Merge remote-tracking branch 'origin/feat/v2' into feat/issue-59
xodms0309 Apr 9, 2024
a272d01
feat: svg icon 하나로 교체
xodms0309 Apr 9, 2024
09f99d9
feat: favoriteButton 스타일 수정
xodms0309 Apr 9, 2024
ad18363
style: 린트 적용
xodms0309 Apr 9, 2024
00cc55a
Merge remote-tracking branch 'origin/feat/v2' into feat/issue-59
xodms0309 Apr 13, 2024
8d5990f
feat: 댓글 form 스타일 수정
xodms0309 Apr 13, 2024
feb7e1f
feat: 꿀조합 상세 디자인 변경 적용
xodms0309 Apr 13, 2024
c8a671a
fix: rate->averageRating으로 이름 변경
xodms0309 Apr 13, 2024
5721558
refactor: ProductOverviewItem -> ProductOVerviewList 컴포넌트로 교체
xodms0309 Apr 13, 2024
321cdd2
feat: CommentList, CommentItem 스토리북 추가
xodms0309 Apr 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions .storybook/preview-body.html
Original file line number Diff line number Diff line change
Expand Up @@ -276,10 +276,19 @@
d="M14.485 9.47a.75.75 0 0 0-1.063 1.06c1.164 1.168 1.133 3.279-.303 4.72l-4.847 4.866c-1.435 1.44-3.533 1.47-4.694.304c-1.164-1.168-1.132-3.28.303-4.72l2.424-2.433a.75.75 0 0 0-1.063-1.059l-2.424 2.433c-1.911 1.92-2.151 4.982-.303 6.838c1.85 1.858 4.907 1.615 6.82-.304l4.847-4.867c1.911-1.918 2.151-4.982.303-6.837Z"
></path>
</g>
<symbol id="plane" width="32" height="32" viewBox="0 0 256 256">
<path
d="M232 127.89a16 16 0 0 1-8.18 14L55.91 237.9A16.14 16.14 0 0 1 48 240a16 16 0 0 1-15.05-21.34l27.35-79.95a4 4 0 0 1 3.79-2.71H136a8 8 0 0 0 8-8.53a8.19 8.19 0 0 0-8.26-7.47H64.16a4 4 0 0 1-3.79-2.7l-27.44-80a16 16 0 0 1 22.92-19.23l168 95.89a16 16 0 0 1 8.15 13.93Z"
/>
<symbol id="plane" viewBox="0 0 18 19">
<g clip-path="url(#clip0_4423_13410)">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M15.1975 0.625674C15.5681 0.490352 15.9695 0.4631 16.3553 0.547225C16.7447 0.632193 17.1016 0.827207 17.3834 1.10908C17.6653 1.39096 17.8603 1.74785 17.9453 2.13732C18.0294 2.52293 18.0021 2.92444 17.8669 3.29502L13.2717 17.0676C13.1597 17.4063 12.9624 17.7115 12.6989 17.9522C12.4363 18.1922 12.1165 18.3608 11.7702 18.442C11.4238 18.5265 11.0613 18.5193 10.7185 18.4213C10.3759 18.3235 10.0647 18.1383 9.81533 17.884L7.35018 15.4301L4.76068 16.7692C4.55875 16.8736 4.31669 16.8636 4.12405 16.7428C3.93143 16.6222 3.81686 16.4087 3.82276 16.1815L3.92892 12.0881L12.9867 5.50856C13.3458 5.24774 13.4255 4.74521 13.1646 4.38615C12.9038 4.02708 12.4013 3.94744 12.0422 4.20826L2.83074 10.8994L0.606834 8.67548C0.365991 8.4348 0.188451 8.13786 0.0906127 7.81172C-0.00653 7.48791 -0.0223126 7.14519 0.0446081 6.81389C0.111615 6.45195 0.273411 6.11419 0.513558 5.8351C0.75535 5.5541 1.0678 5.34276 1.4186 5.22295L1.42294 5.22147L15.1975 0.625674Z"
/>
</g>
<defs>
<clipPath id="clip0_4423_13410">
<rect width="18" height="18" fill="white" transform="translate(0 0.5)" />
</clipPath>
</defs>
</symbol>
<symbol id="info" viewBox="0 0 16 16">
<path
Expand Down
3 changes: 2 additions & 1 deletion src/components/Common/SectionTitle/SectionTitle.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ export const Default: Story = {
},
};

export const Bookmarked: Story = {
export const HasSearch: Story = {
args: {
name: '사이다',
hasSearchLink: true,
},
};
66 changes: 23 additions & 43 deletions src/components/Common/SectionTitle/SectionTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,34 @@
import { Button, Heading, Link, theme } from '@fun-eat/design-system';
import { Link as RouterLink } from 'react-router-dom';
import styled from 'styled-components';
import { Link } from 'react-router-dom';

import { SvgIcon } from '@/components/Common';
import { useRoutePage } from '@/hooks/common';
import { container, wrapper } from './sectionTitle.css';

import { SvgIcon, Text } from '@/components/Common';
import { PATH } from '@/constants/path';
import { vars } from '@/styles/theme.css';

interface SectionTitleProps {
name: string;
link?: string;
hasSearchLink?: boolean;
}

const SectionTitle = ({ name, link }: SectionTitleProps) => {
const { routeBack } = useRoutePage();

const SectionTitle = ({ name, hasSearchLink }: SectionTitleProps) => {
return (
<SectionTitleContainer>
<SectionTitleWrapper>
<Button type="button" variant="transparent" onClick={routeBack} aria-label="뒤로 가기">
<SvgIcon variant="arrow" fill={theme.colors.gray5} width={15} height={15} />
</Button>
{link ? (
<Link as={RouterLink} to={link} block>
<ProductName size="xl">{name}</ProductName>
</Link>
) : (
<ProductName size="xl">{name}</ProductName>
)}
{link && <SvgIcon variant="link" width={20} height={20} />}
</SectionTitleWrapper>
</SectionTitleContainer>
<div className={container}>
<div className={wrapper}>
<Link to=".." relative="path">
<SvgIcon variant="arrowLeft" stroke={vars.colors.black} height={24} />
</Link>
<Text size="headline" weight="semiBold">
{name}
</Text>
</div>
{hasSearchLink && (
<Link to={PATH.SEARCH}>
<SvgIcon variant="search2" stroke={vars.colors.black} width={20} height={20} />
</Link>
)}
</div>
);
};

export default SectionTitle;

const SectionTitleContainer = styled.div`
display: flex;
justify-content: space-between;
align-items: center;
`;

const SectionTitleWrapper = styled.div`
display: flex;
align-items: center;

svg {
padding-top: 2px;
}
`;

const ProductName = styled(Heading)`
margin: 0 5px 0 16px;
`;
13 changes: 13 additions & 0 deletions src/components/Common/SectionTitle/sectionTitle.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { style } from '@vanilla-extract/css';

export const container = style({
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
});

export const wrapper = style({
display: 'flex',
gap: 18,
alignItems: 'flex-start',
});
1 change: 1 addition & 0 deletions src/components/Common/Svg/SvgIcon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const SVG_ICON_VARIANTS = [
'arrowUpDown',
'heartEmpty',
'heartFilled',
'box',
'close2',
'disk',
] as const;
Expand Down
15 changes: 13 additions & 2 deletions src/components/Common/Svg/SvgSprite.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,19 @@ const SvgSprite = () => {
<path d="M14.485 9.47a.75.75 0 0 0-1.063 1.06c1.164 1.168 1.133 3.279-.303 4.72l-4.847 4.866c-1.435 1.44-3.533 1.47-4.694.304c-1.164-1.168-1.132-3.28.303-4.72l2.424-2.433a.75.75 0 0 0-1.063-1.059l-2.424 2.433c-1.911 1.92-2.151 4.982-.303 6.838c1.85 1.858 4.907 1.615 6.82-.304l4.847-4.867c1.911-1.918 2.151-4.982.303-6.837Z" />
</g>
</symbol>
<symbol id="plane" viewBox="0 0 256 256">
<path d="M232 127.89a16 16 0 0 1-8.18 14L55.91 237.9A16.14 16.14 0 0 1 48 240a16 16 0 0 1-15.05-21.34l27.35-79.95a4 4 0 0 1 3.79-2.71H136a8 8 0 0 0 8-8.53a8.19 8.19 0 0 0-8.26-7.47H64.16a4 4 0 0 1-3.79-2.7l-27.44-80a16 16 0 0 1 22.92-19.23l168 95.89a16 16 0 0 1 8.15 13.93Z" />
<symbol id="plane" viewBox="0 0 18 19">
<g clipPath="url(#clip0_4423_13410)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M15.1975 0.625674C15.5681 0.490352 15.9695 0.4631 16.3553 0.547225C16.7447 0.632193 17.1016 0.827207 17.3834 1.10908C17.6653 1.39096 17.8603 1.74785 17.9453 2.13732C18.0294 2.52293 18.0021 2.92444 17.8669 3.29502L13.2717 17.0676C13.1597 17.4063 12.9624 17.7115 12.6989 17.9522C12.4363 18.1922 12.1165 18.3608 11.7702 18.442C11.4238 18.5265 11.0613 18.5193 10.7185 18.4213C10.3759 18.3235 10.0647 18.1383 9.81533 17.884L7.35018 15.4301L4.76068 16.7692C4.55875 16.8736 4.31669 16.8636 4.12405 16.7428C3.93143 16.6222 3.81686 16.4087 3.82276 16.1815L3.92892 12.0881L12.9867 5.50856C13.3458 5.24774 13.4255 4.74521 13.1646 4.38615C12.9038 4.02708 12.4013 3.94744 12.0422 4.20826L2.83074 10.8994L0.606834 8.67548C0.365991 8.4348 0.188451 8.13786 0.0906127 7.81172C-0.00653 7.48791 -0.0223126 7.14519 0.0446081 6.81389C0.111615 6.45195 0.273411 6.11419 0.513558 5.8351C0.75535 5.5541 1.0678 5.34276 1.4186 5.22295L1.42294 5.22147L15.1975 0.625674Z"
/>
</g>
<defs>
<clipPath id="clip0_4423_13410">
<rect width="18" height="18" fill="white" transform="translate(0 0.5)" />
</clipPath>
</defs>
</symbol>
<symbol id="info" viewBox="0 0 16 16">
<path d="M8 7a.5.5 0 0 1 .5.5v3a.5.5 0 0 1-1 0v-3A.5.5 0 0 1 8 7zm0-.75a.749.749 0 1 0 0-1.5.749.749 0 0 0 0 1.498zM2 8a6 6 0 1 1 12 0A6 6 0 0 1 2 8zm6-5a5 5 0 1 0 0 10A5 5 0 0 0 8 3z" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ import type { Product } from '@/types/product';

interface ProductOverviewListProps {
products: Product[];
isSearchPage?: boolean;
hasBorder?: boolean;
}

const ProductOverviewList = ({ products, isSearchPage = false }: ProductOverviewListProps) => {
const ProductOverviewList = ({ products, hasBorder = false }: ProductOverviewListProps) => {
return (
<ul className={container}>
{products.map(({ id, image, name, price, averageRating }) => (
<li key={id}>
<Link to={`${PATH.PRODUCT_LIST}/detail/${id}`}>
<ProductOverviewItem image={image} name={name} price={price} rate={averageRating} />
</Link>
{isSearchPage && (
{hasBorder && (
<>
<div style={{ height: '20px' }} />
<hr style={{ border: '0.5px solid #e6e6e6' }} />
Expand Down
102 changes: 51 additions & 51 deletions src/components/Recipe/CommentForm/CommentForm.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Button, Spacing, Text, Textarea, useTheme, useToastActionContext } from '@fun-eat/design-system';
import { useToastActionContext } from '@fun-eat/design-system';
import type { ChangeEventHandler, FormEventHandler, RefObject } from 'react';
import { useState } from 'react';
import styled from 'styled-components';
import { useRef, useState } from 'react';

import { SvgIcon } from '@/components/Common';
import { commentForm, commentTextarea, container, profileImage, sendButton } from './commentForm.css';

import { SvgIcon, Text } from '@/components/Common';
import { useScroll } from '@/hooks/common';
import { useMemberQuery } from '@/hooks/queries/members';
import { useRecipeCommentMutation } from '@/hooks/queries/recipe';
import { vars } from '@/styles/theme.css';

interface CommentFormProps {
recipeId: number;
Expand All @@ -15,16 +18,27 @@ interface CommentFormProps {
const MAX_COMMENT_LENGTH = 200;

const CommentForm = ({ recipeId, scrollTargetRef }: CommentFormProps) => {
const { data: member } = useMemberQuery();

const [commentValue, setCommentValue] = useState('');
const { mutate } = useRecipeCommentMutation(recipeId);

const theme = useTheme();
const { toast } = useToastActionContext();

const { scrollToPosition } = useScroll();

const textAreaRef = useRef<HTMLTextAreaElement>(null);

const autoResizeTextarea = () => {
if (textAreaRef.current) {
textAreaRef.current.style.height = 'auto';
textAreaRef.current.style.height = textAreaRef.current.scrollHeight + 'px';
}
};

const handleCommentInput: ChangeEventHandler<HTMLTextAreaElement> = (e) => {
setCommentValue(e.target.value);
autoResizeTextarea();
};

const handleSubmitComment: FormEventHandler<HTMLFormElement> = (e) => {
Expand All @@ -51,54 +65,40 @@ const CommentForm = ({ recipeId, scrollTargetRef }: CommentFormProps) => {
};

return (
<CommentFormContainer>
<Form onSubmit={handleSubmitComment}>
<CommentTextarea
placeholder="댓글을 입력하세요. (200자)"
value={commentValue}
onChange={handleCommentInput}
maxLength={MAX_COMMENT_LENGTH}
/>
<SubmitButton variant="transparent" disabled={commentValue.length === 0}>
<SvgIcon
variant="plane"
width={30}
height={30}
fill={commentValue.length === 0 ? theme.colors.gray2 : theme.colors.gray4}
<div className={container}>
<img
className={profileImage}
src={member?.profileImage}
width={29}
height={29}
alt={`${member?.nickname}의 프로필 사진`}
/>
<>
<form className={commentForm} onSubmit={handleSubmitComment}>
<textarea
className={commentTextarea}
placeholder="댓글을 남겨보세요! (200자)"
value={commentValue}
onChange={handleCommentInput}
maxLength={MAX_COMMENT_LENGTH}
rows={1}
ref={textAreaRef}
/>
</SubmitButton>
</Form>
<Spacing size={8} />
<Text size="xs" color={theme.textColors.info} align="right">
{commentValue.length}자 / {MAX_COMMENT_LENGTH}자
</Text>
</CommentFormContainer>
<Text size="caption4" color="disabled">
{commentValue.length}/200
</Text>
<button className={sendButton}>
<SvgIcon
variant="plane"
width={18}
height={18}
fill={commentValue.length === 0 ? vars.colors.gray3 : vars.colors.gray5}
/>
</button>
</form>
</>
</div>
);
};

export default CommentForm;

const CommentFormContainer = styled.div`
position: fixed;
bottom: 0;
width: calc(100% - 40px);
max-width: 540px;
padding: 16px 0;
background: ${({ theme }) => theme.backgroundColors.default};
`;

const Form = styled.form`
display: flex;
gap: 4px;
justify-content: space-around;
align-items: center;
`;

const CommentTextarea = styled(Textarea)`
height: 50px;
padding: 8px;
`;

const SubmitButton = styled(Button)`
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
`;
43 changes: 43 additions & 0 deletions src/components/Recipe/CommentForm/commentForm.css.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { vars } from '@/styles/theme.css';
import { style } from '@vanilla-extract/css';

export const container = style({
display: 'flex',
gap: 8,
alignItems: 'flex-end',
marginBottom: 24,
});

export const commentForm = style({
display: 'flex',
gap: 8,
alignItems: 'flex-end',
width: '100%',
padding: '6px 16px 9px 16px',
background: vars.colors.background.category,
borderRadius: 20,
});

export const commentTextarea = style({
width: '100%',
height: '100%',
border: 'none',
outline: 'none',
background: 'none',
fontSize: '1.4rem',
resize: 'none',

selectors: {
'&:placeholder': {
color: '#808080',
},
},
});

export const profileImage = style({
borderRadius: '50%',
});

export const sendButton = style({
display: 'inherit',
});
18 changes: 18 additions & 0 deletions src/components/Recipe/CommentItem/CommentItem.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Meta, StoryObj } from '@storybook/react';

import CommentItem from './CommentItem';

import comments from '@/mocks/data/comments.json';

const meta: Meta<typeof CommentItem> = {
title: 'recipe/CommentItem',
component: CommentItem,
args: {
recipeComment: comments.comments[0],
},
};

export default meta;
type Story = StoryObj<typeof meta>;

export const Default: Story = {};
Loading
Loading