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 (
-
+
+
+