diff --git a/src/assets/icon/emoji_smile.svg b/src/assets/icon/emoji_smile.svg new file mode 100644 index 0000000..994cb95 --- /dev/null +++ b/src/assets/icon/emoji_smile.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/assets/icon/index.tsx b/src/assets/icon/index.tsx index de25293..f3c46c1 100644 --- a/src/assets/icon/index.tsx +++ b/src/assets/icon/index.tsx @@ -10,6 +10,7 @@ export { ReactComponent as Computer } from './emoji_computer.svg'; export { ReactComponent as HandsUp } from './emoji_hands_up.svg'; export { ReactComponent as Paint } from './emoji_paint.svg'; export { ReactComponent as Paper } from './emoji_paper.svg'; +export { ReactComponent as Smile } from './emoji_smile.svg'; export { ReactComponent as ThumbsUp } from './emoji_thumbs_up.svg'; export { ReactComponent as Image } from './image.svg'; export { ReactComponent as Logo } from './logo.svg'; diff --git a/src/components/common/ShareIcon/ShareIcon.stories.tsx b/src/components/common/ShareIcon/ShareIcon.stories.tsx new file mode 100644 index 0000000..0803dd3 --- /dev/null +++ b/src/components/common/ShareIcon/ShareIcon.stories.tsx @@ -0,0 +1,26 @@ +import styled from '@emotion/styled'; +import { ComponentMeta, ComponentStory } from '@storybook/react'; + +import ShareIcon from '.'; + +export default { + title: 'common/ShareIcon', + component: ShareIcon, + argTypes: {}, +} as ComponentMeta; + +const Container = styled.div` + display: flex; + justify-content: end; +`; + +const Template: ComponentStory = (args) => ( + + + +); + +export const Default = Template.bind({}); +Default.args = { + url: 'http://localhost:3000/topics/1', +}; diff --git a/src/components/common/ShareIcon/ShareIcon.styles.tsx b/src/components/common/ShareIcon/ShareIcon.styles.tsx new file mode 100644 index 0000000..ecf0b8f --- /dev/null +++ b/src/components/common/ShareIcon/ShareIcon.styles.tsx @@ -0,0 +1,35 @@ +import styled from '@emotion/styled'; + +import Icon from '@src/components/common/Icon'; +import theme from '@src/styles/theme'; + +export const Container = styled.div` + width: 24px; + height: 24px; + + position: relative; +`; + +export const Share = styled(Icon)` + cursor: pointer; +`; + +export const Toast = styled.div` + display: flex; + justify-content: center; + align-items: center; + gap: 2px; + + position: absolute; + width: 200px; + height: 48px; + top: calc(100% + 8px); + right: 0; + + background-color: ${theme.color.G6}; + border-radius: 8px; + + font-weight: ${theme.fontWeight.bold}; + font-size: ${theme.textSize.T3}; + line-height: ${theme.lineHeight.B}; +`; diff --git a/src/components/common/ShareIcon/ShareIcon.tsx b/src/components/common/ShareIcon/ShareIcon.tsx new file mode 100644 index 0000000..f0a7de4 --- /dev/null +++ b/src/components/common/ShareIcon/ShareIcon.tsx @@ -0,0 +1,42 @@ +import React, { MouseEvent, useState } from 'react'; + +import Icon from '@src/components/common/Icon'; + +import * as S from './ShareIcon.styles'; + +interface ShareIconProps { + url: string; +} + +const ShareIcon: React.FC = (props) => { + const { url } = props; + const [isCopied, setIsCopied] = useState(false); + + const handleShare = async (e: MouseEvent) => { + e.stopPropagation(); + e.nativeEvent.preventDefault(); + + if (isCopied) return; + if (!navigator.clipboard) return; + + await navigator.clipboard.writeText(url); + setIsCopied(true); + setTimeout(() => { + setIsCopied(false); + }, 1000); + }; + + return ( + + + {isCopied && ( + + + 링크가 복사되었습니다! + + )} + + ); +}; + +export default ShareIcon; diff --git a/src/components/common/ShareIcon/index.ts b/src/components/common/ShareIcon/index.ts new file mode 100644 index 0000000..53c2e1b --- /dev/null +++ b/src/components/common/ShareIcon/index.ts @@ -0,0 +1 @@ +export { default } from './ShareIcon'; diff --git a/src/components/common/TopicCard/TopicCard.tsx b/src/components/common/TopicCard/TopicCard.tsx index 1e657be..e02a2f8 100644 --- a/src/components/common/TopicCard/TopicCard.tsx +++ b/src/components/common/TopicCard/TopicCard.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; +import ShareIcon from '@src/components/common/ShareIcon'; import Topic, { TopicOption } from '@src/types/Topic'; import Icon from '../Icon'; @@ -15,7 +16,7 @@ interface TopicCardProps extends Topic { } const TopicCard = (props: TopicCardProps, ref: React.ForwardedRef) => { - const { title, contents, options: defaultOptions, member, comments, badge, type, onClick } = props; + const { id, title, contents, options: defaultOptions, member, comments, badge, type, onClick } = props; const [options, setOptions] = useState(defaultOptions); const [selectedOptionId, setSelectedOptionId] = useState(null); // TODO: 초기 선택 여부 확인해야함 @@ -56,7 +57,7 @@ const TopicCard = (props: TopicCardProps, ref: React.ForwardedRef{title} - {isFeed && } + {isFeed && } {contents} diff --git a/src/components/topic/TopicDetailMain/TopicDetailMain.styles.tsx b/src/components/topic/TopicDetailMain/TopicDetailMain.styles.tsx index ef71e4c..c4ee2b3 100644 --- a/src/components/topic/TopicDetailMain/TopicDetailMain.styles.tsx +++ b/src/components/topic/TopicDetailMain/TopicDetailMain.styles.tsx @@ -1,7 +1,5 @@ import styled from '@emotion/styled'; -import Icon from '@src/components/common/Icon'; - export const Wrapper = styled.main` margin-top: -20px; display: flex; @@ -15,7 +13,7 @@ export const TopicCardWrapper = styled.div` gap: 12px; `; -export const ShareIcon = styled(Icon)` - align-self: flex-end; - cursor: pointer; +export const ShareIcon = styled.div` + display: flex; + justify-content: end; `; diff --git a/src/components/topic/TopicDetailMain/TopicDetailMain.tsx b/src/components/topic/TopicDetailMain/TopicDetailMain.tsx index 04f7751..d894127 100644 --- a/src/components/topic/TopicDetailMain/TopicDetailMain.tsx +++ b/src/components/topic/TopicDetailMain/TopicDetailMain.tsx @@ -1,6 +1,7 @@ import { FC } from 'react'; import { Topic } from '@src/apis'; +import ShareIcon from '@src/components/common/ShareIcon'; import TopicCard from '@src/components/common/TopicCard'; import CommentForm from '@src/components/topic/CommentForm'; import CommentList from '@src/components/topic/CommentList'; @@ -24,7 +25,9 @@ const TopicDetailMain: FC = (props) => { return ( - + + +