diff --git a/app/(app)/project/index.tsx b/app/(app)/project/index.tsx
index df5043f..4515ac1 100644
--- a/app/(app)/project/index.tsx
+++ b/app/(app)/project/index.tsx
@@ -1,12 +1,39 @@
-import { View } from 'react-native';
+import { useRouter } from 'expo-router';
+import { useState } from 'react';
+import { SafeAreaView } from 'react-native';
+import SolidButton from '@/components/common/button/SolidButton';
import Typography from '@/components/common/typography';
+import ProjectInviteModal from '@/components/project/ProjectInviteModal';
function Project() {
+ const [visible, setVisible] = useState(false);
+ const router = useRouter();
+
+ const data = {
+ project_name: '위프로',
+ project_profile: 'https://picsum.photos/200',
+ member_length: 6,
+ };
+
+ const onRequestClose = () => {
+ setVisible(false);
+ router.replace('/project');
+ };
+
return (
-
+
+
+ setVisible(true)}>초대 링크 있음
Project
-
+
);
}
diff --git a/app/(beforeLogin)/onboarding.tsx b/app/(beforeLogin)/onboarding.tsx
index 8135df9..ab327f5 100644
--- a/app/(beforeLogin)/onboarding.tsx
+++ b/app/(beforeLogin)/onboarding.tsx
@@ -68,7 +68,8 @@ function Onboarding() {
다음
diff --git a/src/components/common/button/Button.style.tsx b/src/components/common/button/Button.style.tsx
index ffac483..5e42a32 100644
--- a/src/components/common/button/Button.style.tsx
+++ b/src/components/common/button/Button.style.tsx
@@ -2,9 +2,10 @@ import styled, { type ReactNativeStyle } from '@emotion/native';
import { flexDirectionRowItemsCenter, flexItemCenter } from '@/styles/common';
-export const Container = styled.View<{ $sizeStyle: ReactNativeStyle }>`
- ${({ $sizeStyle }) => $sizeStyle}
+export const Container = styled.View<{ $sizeStyle: ReactNativeStyle; $full: boolean }>`
+ ${({ $sizeStyle }) => $sizeStyle};
position: relative;
+ width: ${({ $full }) => ($full ? '100%' : 'fit-content')};
overflow: hidden;
border-radius: 30px;
`;
diff --git a/src/components/common/button/OutLineButton.stories.tsx b/src/components/common/button/OutLineButton.stories.tsx
index 50c134c..a2b2219 100644
--- a/src/components/common/button/OutLineButton.stories.tsx
+++ b/src/components/common/button/OutLineButton.stories.tsx
@@ -20,7 +20,7 @@ const OutLineButtonMeta: Meta = {
description: '버튼의 사이즈를 결정합니다.',
control: {
type: 'select',
- options: ['full', 'large', 'medium', 'small'],
+ options: ['large', 'medium', 'small'],
},
},
disabled: {
@@ -29,11 +29,17 @@ const OutLineButtonMeta: Meta = {
type: 'boolean',
},
},
+ full: {
+ description: '버튼의 가로 길이 폭을 결정합니다.',
+ control: {
+ type: 'boolean',
+ },
+ },
},
args: {
children: '버튼',
type: 'primary',
- size: 'full',
+ size: 'large',
disabled: false,
},
};
diff --git a/src/components/common/button/OutlineButton.tsx b/src/components/common/button/OutlineButton.tsx
index f9a7fdb..251c5d6 100644
--- a/src/components/common/button/OutlineButton.tsx
+++ b/src/components/common/button/OutlineButton.tsx
@@ -22,20 +22,13 @@ const typeStyle: Record = {
};
const sizeStyle: Record = {
- full: css`
- width: 100%;
- height: 48px;
- `,
large: css`
- width: fit-content;
height: 48px;
`,
medium: css`
- width: fit-content;
height: 40px;
`,
small: css`
- width: fit-content;
height: 32px;
`,
};
@@ -48,19 +41,22 @@ const disabledStyle = {
};
function OutLineButton({
- size = 'full',
+ size = 'large',
type = 'primary',
disabled = false,
LeftIcon,
RightIcon,
children,
+ full = false,
...rest
}: PropsNeedChildren) {
const { textSize, iconSize } = useButtonStyle(size);
const { color } = useButtonTextColor(type, disabled);
return (
-
+
= {
description: '버튼의 사이즈를 결정합니다.',
control: {
type: 'select',
- options: ['large', 'medium', 'small', 'full'],
+ options: ['large', 'medium', 'small'],
},
},
disabled: {
@@ -29,6 +29,12 @@ const PrimaryButtonMeta: Meta = {
type: 'boolean',
},
},
+ full: {
+ description: '버튼의 가로 길이 폭을 결정합니다.',
+ control: {
+ type: 'boolean',
+ },
+ },
},
args: {
children: '버튼',
diff --git a/src/components/common/button/SolidButton.tsx b/src/components/common/button/SolidButton.tsx
index 8c5daad..6c2be3c 100644
--- a/src/components/common/button/SolidButton.tsx
+++ b/src/components/common/button/SolidButton.tsx
@@ -19,20 +19,13 @@ const typeStyle: Record = {
};
const sizeStyle: Record = {
- full: css`
- width: 100%;
- height: 48px;
- `,
large: css`
- width: fit-content;
height: 48px;
`,
medium: css`
- width: fit-content;
height: 40px;
`,
small: css`
- width: fit-content;
height: 32px;
`,
};
@@ -45,9 +38,10 @@ const disabledStyle = {
};
function SolidButton({
- size = 'full',
+ size = 'large',
type = 'primary',
disabled = false,
+ full = false,
LeftIcon,
RightIcon,
children,
@@ -56,7 +50,9 @@ function SolidButton({
const { textSize, iconSize } = useButtonStyle(size);
const color = disabled ? disabledStyle.color : '#FFFFFF';
return (
-
+
{type === 'primary' && !disabled && (
= {
description: '버튼의 사이즈를 결정합니다.',
control: {
type: 'select',
- options: ['full', 'large', 'medium', 'small'],
+ options: ['large', 'medium', 'small'],
},
},
disabled: {
@@ -33,7 +33,7 @@ const TextButtonMeta: Meta = {
args: {
children: '버튼',
type: 'primary',
- size: 'full',
+ size: 'large',
disabled: false,
},
};
diff --git a/src/components/common/button/TextButton.tsx b/src/components/common/button/TextButton.tsx
index 30614a1..e46082c 100644
--- a/src/components/common/button/TextButton.tsx
+++ b/src/components/common/button/TextButton.tsx
@@ -8,14 +8,14 @@ import type { PropsNeedChildren } from '@/types';
import * as S from './Button.style';
function TextButton({
- size = 'full',
+ size = 'large',
type = 'primary',
disabled = false,
LeftIcon,
RightIcon,
children,
...rest
-}: PropsNeedChildren) {
+}: PropsNeedChildren>) {
const { textSize, iconSize } = useButtonStyle(size);
const { color } = useButtonTextColor(type, disabled);
diff --git a/src/components/common/button/button.type.ts b/src/components/common/button/button.type.ts
index e74b278..c990c4b 100644
--- a/src/components/common/button/button.type.ts
+++ b/src/components/common/button/button.type.ts
@@ -5,7 +5,8 @@ import type { IconProps } from '@/types';
export type CustomButtonProps = {
type: 'primary' | 'secondary';
- size: 'large' | 'medium' | 'small' | 'full';
+ size: 'large' | 'medium' | 'small';
+ full: boolean;
disabled: boolean;
};
diff --git a/src/components/common/typography/index.tsx b/src/components/common/typography/index.tsx
index 656c93a..0b1306d 100644
--- a/src/components/common/typography/index.tsx
+++ b/src/components/common/typography/index.tsx
@@ -8,6 +8,7 @@ type Props = TextProps & {
variant: keyof typeof TypographyStyle;
fontWeight: keyof typeof FontWeightStyle;
color: string;
+ breakWord?: boolean;
};
const FontWeightStyle = {
@@ -92,13 +93,19 @@ const TypographyStyle = {
`,
};
+const breakWordText = css`
+ width: 100%;
+ word-wrap: break-word;
+`;
+
const CustomText = styled.Text`
- ${({ variant }) => TypographyStyle[variant]}
+ ${({ variant }) => TypographyStyle[variant]};
${({ fontWeight }) =>
fontWeight === 'semiBold' && !isMobile
? FontWeightStyle['normal']
- : FontWeightStyle[fontWeight]}
- ${({ color }) => (color ? `color: ${color};` : '')}
+ : FontWeightStyle[fontWeight]};
+ ${({ color }) => (color ? `color: ${color};` : '')};
+ ${({ breakWord }) => breakWord && breakWordText}
`;
/**
@@ -107,6 +114,7 @@ const CustomText = styled.Text`
* @param variant 텍스트의 크기, 자간, 줄간 등의 스타일을 지정합니다.
* @param fontWeight 글씨 굵기 속성을 지정합니다.
* @param color 글씨의 색깔을 선택합니다.
+ * @param breakWord 글씨의 줄바꿈을 제거합니다.
* @param rest 나머지 추가 속성들을 받아옵니다.
* @constructor
*/
@@ -115,6 +123,7 @@ function Typography({
variant = 'Label1/Normal',
fontWeight = 'normal',
color = 'black',
+ breakWord = false,
...rest
}: Partial) {
return (
@@ -122,6 +131,7 @@ function Typography({
variant={variant}
fontWeight={fontWeight}
color={color}
+ breakWord={breakWord}
{...rest}>
{children}
diff --git a/src/components/project/ProjectInviteModal.stories.tsx b/src/components/project/ProjectInviteModal.stories.tsx
new file mode 100644
index 0000000..3a4f2da
--- /dev/null
+++ b/src/components/project/ProjectInviteModal.stories.tsx
@@ -0,0 +1,40 @@
+import type { Meta, StoryObj } from '@storybook/react';
+import { useState } from 'react';
+import { View } from 'react-native';
+
+import SolidButton from '@/components/common/button/SolidButton';
+import ProjectInviteModal from '@/components/project/ProjectInviteModal';
+
+const ProjectInviteModalMeta: Meta = {
+ title: 'project/ProjectInviteModal',
+ component: ProjectInviteModal,
+ argTypes: {},
+};
+
+export default ProjectInviteModalMeta;
+
+export const Primary: StoryObj = {
+ args: {
+ project_name: '위프로',
+ project_profile: 'https://picsum.photos/200',
+ member_length: 6,
+ },
+ render: (args) => {
+ const [show, setShow] = useState(false);
+
+ const onRequestClose = () => {
+ setShow(false);
+ };
+
+ return (
+
+ setShow(true)}>버튼 열기
+
+
+ );
+ },
+};
diff --git a/src/components/project/ProjectInviteModal.style.ts b/src/components/project/ProjectInviteModal.style.ts
new file mode 100644
index 0000000..7bb6b78
--- /dev/null
+++ b/src/components/project/ProjectInviteModal.style.ts
@@ -0,0 +1,61 @@
+import styled from '@emotion/native';
+
+import { flexDirectionColumn, flexDirectionColumnItemsCenter } from '@/styles/common';
+import { color } from '@/styles/theme';
+import { getSize } from '@/utils';
+
+export const Container = styled.View`
+ ${flexDirectionColumnItemsCenter};
+ flex: 1;
+ background: ${color.Background.Alternative};
+`;
+
+export const Contents = styled.View`
+ ${flexDirectionColumnItemsCenter};
+ gap: 20px;
+ align-items: center;
+ width: ${getSize.screenWidth - 40 + 'px'};
+ height: fit-content;
+ padding: 36px 32px;
+ background: #fff;
+ border-radius: 8px;
+`;
+
+export const ProjectBox = styled.View`
+ ${flexDirectionColumnItemsCenter};
+ gap: 12px;
+`;
+
+export const ProjectImageBox = styled.View`
+ ${flexDirectionColumnItemsCenter};
+ position: relative;
+ width: 48px;
+ height: 48px;
+ border-radius: 8px;
+`;
+
+export const ProjectImageOutline = styled.View`
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ border: 1px solid rgb(115 112 114);
+ border-radius: 8px;
+`;
+
+export const ProjectImage = styled.Image`
+ position: relative;
+ width: 100%;
+ height: 100%;
+ border-radius: 8px;
+`;
+
+export const TextBox = styled.View`
+ ${flexDirectionColumn};
+ gap: 2px;
+`;
+
+export const ButtonBox = styled.View`
+ ${flexDirectionColumnItemsCenter};
+ gap: 12px;
+ width: 100%;
+`;
diff --git a/src/components/project/ProjectInviteModal.tsx b/src/components/project/ProjectInviteModal.tsx
new file mode 100644
index 0000000..a125c5d
--- /dev/null
+++ b/src/components/project/ProjectInviteModal.tsx
@@ -0,0 +1,72 @@
+import { Modal } from 'react-native';
+
+import SolidButton from '@/components/common/button/SolidButton';
+import Typography from '@/components/common/typography';
+import { color } from '@/styles/theme';
+
+import * as S from './ProjectInviteModal.style';
+
+type ModalType = {
+ visible: boolean;
+ /** 사용자가 뒤로가기 버튼을 눌렀을 때 호출될 함수 */
+ onRequestClose: () => void;
+};
+
+type ProjectType = {
+ project_name: string;
+ project_profile: string;
+ member_length: number;
+} & ModalType;
+
+function ProjectInviteModal({
+ project_name,
+ project_profile,
+ member_length,
+ visible,
+ onRequestClose,
+}: ProjectType) {
+ return (
+
+
+
+ 프로젝트에 초대되었어요!
+
+
+
+ {null}
+
+
+
+ {project_name}
+
+
+ 멤버 {member_length}명
+
+
+
+
+ 수락하기
+
+ 거절하기
+
+
+
+
+
+ );
+}
+
+export default ProjectInviteModal;
diff --git a/src/styles/common.ts b/src/styles/common.ts
index 76ef28a..d185cb7 100644
--- a/src/styles/common.ts
+++ b/src/styles/common.ts
@@ -11,6 +11,19 @@ export const flexDirectionColumn = css`
flex-direction: column;
`;
+export const flexDirectionColumnCenter = css`
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+`;
+
+export const flexDirectionColumnItemsCenter = css`
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+`;
+
export const flexDirectionRow = css`
display: flex;
flex-direction: row;