Skip to content

Commit

Permalink
chore: 리액션 기능을 위한 퍼블리싱 (#191)
Browse files Browse the repository at this point in the history
* chore: CountEmoji 컴포넌트 추가

* chore: 필요한 asset 추가

* chore: Emojis 컴포넌트 추가 (+버튼 클릭시 뜨게 되는 컴포넌트)

* chore: ReactionButton 컴포넌트 추가 (+버튼)

* chore: ReactUserCount 컴포넌트 추가

* chore: ReactedEmojis 컴포넌트 추가

* chore: Reaction 컴포넌트 추가 및 적용

* chore: 필요한 util 함수 및 theme 추가

* chore: 바텀시트를 구성하는 컴포넌트들 추가

* chore: ReactUserBottomSheet 컴포넌트 추가

* chore: Emojis 합성 컴포넌트 추가 및 적용하여 리팩터링

* chore: 지난 번에 수정된 Emoji 컴포넌트 반영하여 스토리 수정

* chore: 누락된 파일 추가

* chore: 네이밍 관련 피드백 반영

* chore: 인라인 → tailwind로 스타일 적용

* chore: Tabs에서 Trigger 컴포넌트만 불러와서 사용

* chore: CountEmoji 스토리에 size 지정

* chore: feature 폴더에 존재하는 MapCard 관련 스토리 제거

* chore: StartMapCard 컴포넌트 - 디자인 변경사항 반영

* chore: 공통으로 쓰이는 emoji 관련 컴포넌트를 features/emoji 폴더로 이동
  • Loading branch information
Doeunnkimm committed Mar 8, 2024
1 parent 017b133 commit 664243a
Show file tree
Hide file tree
Showing 41 changed files with 578 additions and 198 deletions.
5 changes: 5 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,8 @@
@apply max-w-[var(--layout-max-w)] min-h-[var(--layout-min-h)] w-full mx-auto;
}
}

::-webkit-scrollbar {
/* 가로 스크롤바 보이지 않도록 */
display: none;
}
10 changes: 10 additions & 0 deletions src/assets/icons/react-emoji-plus-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/bandiboodi-start.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/images/reaction-members.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions src/components/atoms/emoji/Emoji.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import type { Meta, StoryObj } from '@storybook/react';

import { Emoji } from './Emoji';

const meta: Meta<typeof Emoji> = {
title: 'components/atoms/emoji',
component: Emoji,
};

export default meta;

type Story = StoryObj<typeof Emoji>;

export const Basic: Story = {
args: {
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/5c103242-786d-4700-bf32-b87e4c4a8970',
name: 'like',
size: 56,
},
};
11 changes: 11 additions & 0 deletions src/components/atoms/emoji/Emoji.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Image from 'next/image';

export interface EmojiProps {
size: number;
url: string;
name: string;
}

export const Emoji = ({ size, url, name }: EmojiProps) => {
return <Image src={url} width={size} height={size} alt={`emoji_${name}`} />;
};
2 changes: 2 additions & 0 deletions src/components/atoms/emoji/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type { EmojiProps } from './Emoji';
export { Emoji } from './Emoji';
1 change: 1 addition & 0 deletions src/components/atoms/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export { Avatar } from './avatar';
export { BottomSheet } from './bottomSheet';
export { Button } from './button';
export { Emoji } from './emoji';
export { Input } from './input';
export { Span } from './span';
export { Star } from './star';
Expand Down
35 changes: 35 additions & 0 deletions src/components/molecules/countEmoji/CountEmoji.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { Meta, StoryObj } from '@storybook/react';

import { CountEmoji } from './CountEmoji';

const meta: Meta<typeof CountEmoji> = {
title: 'components/molecules/countEmoji',
component: CountEmoji,
};

export default meta;

type Story = StoryObj<typeof CountEmoji>;

export const Basic: Story = {
args: {
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/5c103242-786d-4700-bf32-b87e4c4a8970',
name: 'like',
count: 10,
size: 56,
},
};

export const Selected: Story = {
args: {
...Basic.args,
reacted: true,
},
};

export const OnlyView: Story = {
args: {
...Basic.args,
onlyView: true,
},
};
26 changes: 26 additions & 0 deletions src/components/molecules/countEmoji/CountEmoji.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Emoji } from '@/components';
import type { EmojiProps } from '@/components/atoms/emoji';

interface CountEmojiProps extends EmojiProps {
count: number;
reacted?: boolean;
onlyView?: boolean;
onClick?: VoidFunction;
}

export const CountEmoji = ({ count, reacted = false, onlyView = false, onClick, ...props }: CountEmojiProps) => {
return (
<button
className={`p-[3px] rounded-[8px] ${!reacted ? 'bg-white' : 'bg-blue-10'} ${
!onlyView && 'transition-shadow duration-500 hover:shadow-thumb'
}`}
disabled={onlyView}
onClick={onClick}
>
<Emoji {...props} />
<p className={`text-[12px] ${!reacted ? 'text-gray-70' : 'text-blue-50'} leading-[155%] tracking-[-0.6px]`}>
{count}
</p>
</button>
);
};
1 change: 1 addition & 0 deletions src/components/molecules/countEmoji/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CountEmoji } from './CountEmoji';
58 changes: 58 additions & 0 deletions src/components/molecules/emojis/Emojis.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { StoryObj } from '@storybook/react';

import { EmojisContainer, EmojisItem } from '../emojis';

const meta = {
title: 'components/molecules/emojis',
};

export default meta;

type Story = StoryObj;

const emojis = [
{
id: 1,
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/3727715a-a778-4630-82b7-663662516ecc',
name: '좋아요',
},
{
id: 2,
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/0515378c-b6cc-47cd-850d-837c8ed91080',
name: '응원해요',
},
{
id: 3,
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/f7b0d37e-c514-4c02-8b49-8b65e3e28ec9',
name: '놀라워요',
},
{
id: 4,
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/75a0d5d4-6988-4952-b105-24ecb77af270',
name: '열받아요',
},
{
id: 5,
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/c0d0e892-34e7-4a6d-ae06-0a8faf142ae6',
name: '슬퍼요',
},
{
id: 6,
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/9e10e382-3ace-4923-b6a3-f96b7830164d',
name: '대단해요',
},
];

const ExampleEmojis = () => {
return (
<EmojisContainer className="absolute top-0">
{emojis.map((emoji) => (
<EmojisItem key={emoji.name} {...emoji} size={56} onClick={() => alert('예를 들어 mutate?')} />
))}
</EmojisContainer>
);
};

export const Example: Story = {
render: () => <ExampleEmojis />,
};
35 changes: 35 additions & 0 deletions src/components/molecules/emojis/Emojis.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import type { PropsWithChildren } from 'react';
import type { AnimationProps } from 'framer-motion';
import { m } from 'framer-motion';

import { Emoji, Typography } from '@/components';
import type { EmojiProps } from '@/components/atoms/emoji';

interface EmojisContainerProps {
animate?: AnimationProps;
className?: string;
}

interface EmojisItemProps extends EmojiProps {
onClick?: VoidFunction;
}

export const EmojisContainer = ({ className, animate, children }: PropsWithChildren<EmojisContainerProps>) => {
return (
<m.div className={className} {...animate}>
<div className="flex gap-6xs px-5xs py-4xs rounded-[20px] bg-white shadow-thumbStrong">{children}</div>
</m.div>
);
};

export const EmojisItem = ({ onClick, ...emoji }: EmojisItemProps) => {
return (
<button
className="flex flex-col gap-6xs items-center transition-transform duration-300 hover:-translate-y-1"
onClick={onClick}
>
<Emoji {...emoji} size={emoji.size} />
<Typography type="body3">{emoji.name}</Typography>
</button>
);
};
1 change: 1 addition & 0 deletions src/components/molecules/emojis/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { EmojisContainer, EmojisItem } from './Emojis';
2 changes: 2 additions & 0 deletions src/components/molecules/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export { ContentWrapper } from './contentWrapper';
export { CountEmoji } from './countEmoji';
export { EmojisContainer, EmojisItem } from './emojis';
export { InfiniteScroller } from './infiniteScroll';
export { LimitedLengthInput } from './limitedLengthInput';
export { LoginIconSet } from './loginIconSet';
Expand Down
33 changes: 33 additions & 0 deletions src/features/emoji/BottomSheet/Content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as Tabs from '@radix-ui/react-tabs';

import { ReactUser } from './ReactUser';

interface ContentProps {
reactedEmojis: {
id: number;
url: string;
name: string;
reactCount: number;
reactUsers: ReactedUserProps[];
}[];
}

export interface ReactedUserProps {
username: string;
image: string;
nickname: string;
}

export const Content = ({ reactedEmojis }: ContentProps) => {
return (
<>
{reactedEmojis.map((emoji) => (
<Tabs.Content value={emoji.name} key={emoji.id} className="px-xs pt-[13px]">
{emoji.reactUsers.map((user) => (
<ReactUser key={`${emoji.id}-${user.username}`} {...user} />
))}
</Tabs.Content>
))}
</>
);
};
36 changes: 36 additions & 0 deletions src/features/emoji/BottomSheet/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import * as Tabs from '@radix-ui/react-tabs';

import { Emoji, Typography } from '@/components';
import { addSuffixIfExceedsLimit } from '@/utils/suffix';

import { Tab } from './Tab';

interface HeaderProps {
totalReactedEmojisCount: number;
reactedEmojis: {
id: number;
url: string;
name: string;
reactCount: number;
}[];
}

export const Header = ({ totalReactedEmojisCount, reactedEmojis }: HeaderProps) => {
return (
<div className="flex flex-col gap-[11px]">
<Typography type="body3" className="px-xs pt-5xs">
{addSuffixIfExceedsLimit(totalReactedEmojisCount, 999)}
</Typography>
<Tabs.List className="flex items-center gap-4xs py-5xs overflow-scroll px-xs scrollbar-width-none">
{reactedEmojis.map((emoji) => (
<Tab key={emoji.id} value={emoji.name}>
<div className="flex gap-6xs items-center">
<Emoji name={emoji.name} url={emoji.url} size={24} />
<Typography type="caption1">{addSuffixIfExceedsLimit(emoji.reactCount, 999)}</Typography>
</div>
</Tab>
))}
</Tabs.List>
</div>
);
};
19 changes: 19 additions & 0 deletions src/features/emoji/BottomSheet/ReactUser.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import Image from 'next/image';
import Link from 'next/link';

import { Typography } from '@/components';

import type { ReactedUserProps } from './Content';

export const ReactUser = ({ username, image, nickname }: ReactedUserProps) => {
return (
<Link href={{ pathname: `/home/${username}` }}>
<button className="w-full flex flex-col gap-xs">
<div className="flex gap-4xs items-center">
<Image src={image} width={50} height={50} alt="user-profile" />
<Typography type="body1">{nickname}</Typography>
</div>
</button>
</Link>
);
};
41 changes: 41 additions & 0 deletions src/features/emoji/BottomSheet/ReactUserBottomSheet.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as Tabs from '@radix-ui/react-tabs';

import { BottomSheet } from '@/components';

import { Content } from './Content';
import { Header } from './Header';

interface ReactUserBottomSheetProps {
open: boolean;
onClose: VoidFunction;
}

export const ReactUserBottomSheet = ({ open, onClose }: ReactUserBottomSheetProps) => {
const data = {
totalReactedEmojisCount: 1000,
reactedEmojis: [
{
id: 1,
name: '좋아요',
url: 'https://github.com/depromeet/amazing3-fe/assets/112946860/8f87efc3-ec65-4650-b763-74501bc2e1c0',
reactCount: 1000,
reactUsers: [
{
username: 'BANDIBOODI-10',
image: 'https://github.com/depromeet/amazing3-fe/assets/112946860/0ab4b6f0-ebaf-4212-a79a-edf0f50a5d62',
nickname: '누민경',
},
],
},
],
};

return (
<BottomSheet open={open} onDismiss={onClose} fixedMaxHeight={450}>
<Tabs.Root>
<Header {...data} />
<Content reactedEmojis={data.reactedEmojis} />
</Tabs.Root>
</BottomSheet>
);
};
14 changes: 14 additions & 0 deletions src/features/emoji/BottomSheet/Tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { PropsWithChildren } from 'react';
import type { TabsTriggerProps } from '@radix-ui/react-tabs';
import { Trigger } from '@radix-ui/react-tabs';

export const Tab = ({ children, ...props }: PropsWithChildren<TabsTriggerProps>) => {
return (
<Trigger
{...props}
className="flex-shrink-0 pb-4xs data-[state=active]:text-purple-40 data-[state=active]:shadow-[inset_0_-1px_0_0,0_1px_0_0]"
>
{children}
</Trigger>
);
};
1 change: 1 addition & 0 deletions src/features/emoji/BottomSheet/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ReactUserBottomSheet } from './ReactUserBottomSheet';
Loading

0 comments on commit 664243a

Please sign in to comment.