diff --git a/app/(tabs)/[teamId]/_layout.tsx b/app/(tabs)/[teamId]/_layout.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/app/(tabs)/[teamId]/calendar.tsx b/app/(tabs)/[teamId]/calendar.tsx deleted file mode 100644 index 40f354a..0000000 --- a/app/(tabs)/[teamId]/calendar.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface CalendarProps {} - -const Calendar = ({}: CalendarProps) => { - return ; -}; - -export default Calendar; diff --git a/app/(tabs)/[teamId]/calendarModal.tsx b/app/(tabs)/[teamId]/calendarModal.tsx deleted file mode 100644 index 427fa9f..0000000 --- a/app/(tabs)/[teamId]/calendarModal.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface CalendarModalProps {} - -const CalendarModal = ({}: CalendarModalProps) => { - return ; -}; - -export default CalendarModal; diff --git a/app/(tabs)/[teamId]/index.tsx b/app/(tabs)/[teamId]/index.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/app/(tabs)/[teamId]/schedule.tsx b/app/(tabs)/[teamId]/schedule.tsx deleted file mode 100644 index bb8d03e..0000000 --- a/app/(tabs)/[teamId]/schedule.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface ScheduleProps {} - -const Schedule = ({}: ScheduleProps) => { - return ; -}; - -export default Schedule; diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index e69de29..e2cdab2 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -0,0 +1,43 @@ +import MainIcon from "@/assets/icons/main"; +import MyPageIcon from "@/assets/icons/mypage"; +import PersonalIcon from "@/assets/icons/personal"; +import { globalGray50, globalGreen300 } from "@/shared/ui"; +import { Tabs } from "expo-router"; + +export default function TabsLayout() { + return ( + + , + }} + /> + , + }} + /> + , + }} + /> + + ); +} diff --git a/app/(tabs)/home/_layout.tsx b/app/(tabs)/home/_layout.tsx new file mode 100644 index 0000000..161589e --- /dev/null +++ b/app/(tabs)/home/_layout.tsx @@ -0,0 +1,16 @@ +import { globalGray50 } from "@/shared/ui"; +import { Stack } from "expo-router"; + +export default function HomeLayout() { + return ( + + + + ); +} diff --git a/app/(tabs)/home/index.tsx b/app/(tabs)/home/index.tsx new file mode 100644 index 0000000..c9fc90f --- /dev/null +++ b/app/(tabs)/home/index.tsx @@ -0,0 +1,15 @@ +import { StyleSheet, Text, View } from "react-native"; + +interface GroupScreenProps {} + +const GroupScreen = ({}: GroupScreenProps) => { + return ( + + GroupPage + + ); +}; + +const styles = StyleSheet.create({}); + +export default GroupScreen; diff --git a/app/(tabs)/homepage.tsx b/app/(tabs)/homepage.tsx deleted file mode 100644 index 8201758..0000000 --- a/app/(tabs)/homepage.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface HomePageProps {} - -const HomePage = ({}: HomePageProps) => { - return ; -}; - -export default HomePage; diff --git a/app/(tabs)/my/_layout.tsx b/app/(tabs)/my/_layout.tsx new file mode 100644 index 0000000..66e8440 --- /dev/null +++ b/app/(tabs)/my/_layout.tsx @@ -0,0 +1,16 @@ +import { globalGray50 } from "@/shared/ui"; +import { Stack } from "expo-router"; + +export default function MyLayout() { + return ( + + + + ); +} diff --git a/app/(tabs)/my/index.tsx b/app/(tabs)/my/index.tsx new file mode 100644 index 0000000..1c6cf08 --- /dev/null +++ b/app/(tabs)/my/index.tsx @@ -0,0 +1,15 @@ +import { StyleSheet, Text, View } from "react-native"; + +interface MyScreenProps {} + +const MyScreen = ({}: MyScreenProps) => { + return ( + + MyScreen + + ); +}; + +const styles = StyleSheet.create({}); + +export default MyScreen; diff --git a/app/(tabs)/mypage.tsx b/app/(tabs)/mypage.tsx deleted file mode 100644 index 00e4b0d..0000000 --- a/app/(tabs)/mypage.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface MyPageProps {} - -const MyPage = ({}: MyPageProps) => { - return ; -}; - -export default MyPage; diff --git a/app/(tabs)/personal/_layout.tsx b/app/(tabs)/personal/_layout.tsx new file mode 100644 index 0000000..d876693 --- /dev/null +++ b/app/(tabs)/personal/_layout.tsx @@ -0,0 +1,15 @@ +import { globalGray50 } from "@/shared/ui"; +import { Stack } from "expo-router"; + +export default function PersonalLayout() { + return ( + + + + ); +} diff --git a/app/(tabs)/personal/index.tsx b/app/(tabs)/personal/index.tsx new file mode 100644 index 0000000..ca22075 --- /dev/null +++ b/app/(tabs)/personal/index.tsx @@ -0,0 +1,15 @@ +import { StyleSheet, Text, View } from "react-native"; + +interface PersonalScreenProps {} + +const PersonalScreen = ({}: PersonalScreenProps) => { + return ( + + PersonalPage + + ); +}; + +const styles = StyleSheet.create({}); + +export default PersonalScreen; diff --git a/app/_layout.tsx b/app/_layout.tsx index db2fa6b..6d9fcd7 100644 --- a/app/_layout.tsx +++ b/app/_layout.tsx @@ -1,5 +1,18 @@ -import { Tabs } from "expo-router"; +import { globalGray50 } from "@/shared/ui"; +import { Stack } from "expo-router"; +import { SafeAreaProvider } from "react-native-safe-area-context"; export default function RootLayout() { - return ; + return ( + + + + + + ); } diff --git a/app/index.tsx b/app/index.tsx index 866b635..517880d 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,15 +1,6 @@ -import { Text, View } from "react-native"; +import { Redirect } from "expo-router"; export default function Index() { - return ( - - Edit app/index.tsx to edit this screen. - - ); + // auth 구현 전, 개발 편의를 위해 초기 진입 시 홈으로 리다이렉트 + return ; } diff --git a/app/sideModal 2.tsx b/app/sideModal 2.tsx deleted file mode 100644 index 6e05ca3..0000000 --- a/app/sideModal 2.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface SideModalProps {} - -const SideModal = ({}: SideModalProps) => { - return ; -}; - -export default SideModal; diff --git a/app/sideModal.tsx b/app/sideModal.tsx deleted file mode 100644 index 6e05ca3..0000000 --- a/app/sideModal.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { View } from "react-native"; - -interface SideModalProps {} - -const SideModal = ({}: SideModalProps) => { - return ; -}; - -export default SideModal; diff --git a/assets/icons/main.tsx b/assets/icons/main.tsx new file mode 100644 index 0000000..b3049c3 --- /dev/null +++ b/assets/icons/main.tsx @@ -0,0 +1,33 @@ +import { globalGray500 } from "@/shared/ui"; +import * as React from "react"; +import Svg, { Path, SvgProps } from "react-native-svg"; + +interface MainIconProps extends SvgProps { + size?: number; + color?: string; +} + +const MainIcon = ({ + size = 24, + color = globalGray500, + ...props +}: MainIconProps) => ( + + + + +); + +export default MainIcon; diff --git a/assets/icons/mypage.tsx b/assets/icons/mypage.tsx new file mode 100644 index 0000000..501c1c0 --- /dev/null +++ b/assets/icons/mypage.tsx @@ -0,0 +1,43 @@ +import { globalGray500 } from "@/shared/ui"; +import * as React from "react"; +import Svg, { Path, SvgProps } from "react-native-svg"; + +interface MyPageIconProps extends SvgProps { + size?: number; + color?: string; +} + +const MyPageIcon = ({ + size = 24, + color = globalGray500, + ...props +}: MyPageIconProps) => ( + + + + + + + + +); + +export default MyPageIcon; diff --git a/assets/icons/personal.tsx b/assets/icons/personal.tsx new file mode 100644 index 0000000..214bf23 --- /dev/null +++ b/assets/icons/personal.tsx @@ -0,0 +1,54 @@ +import { globalGray500 } from "@/shared/ui"; +import * as React from "react"; +import Svg, { Path, SvgProps } from "react-native-svg"; + +interface PersonalIconProps extends SvgProps { + size?: number; + color?: string; +} + +const PersonalIcon = ({ + size = 24, + color = globalGray500, + ...props +}: PersonalIconProps) => ( + + + + + + + +); + +export default PersonalIcon; diff --git a/shared/stories/atoms/Input.stories.tsx b/shared/stories/atoms/Input.stories.tsx index 96e4e76..d6fc2e4 100644 --- a/shared/stories/atoms/Input.stories.tsx +++ b/shared/stories/atoms/Input.stories.tsx @@ -1,9 +1,18 @@ +import { globalGray50 } from "@/shared/ui"; import type { Meta, StoryObj } from "@storybook/react"; +import { View } from "react-native"; import Input from "../../ui/atoms/Input"; const meta: Meta = { title: "atoms/Input", component: Input, + decorators: [ + (Story) => ( + + + + ), + ], }; export default meta; diff --git a/shared/stories/organisms/AlertModal.stories.tsx b/shared/stories/organisms/AlertModal.stories.tsx index 9a44d81..9e8c358 100644 --- a/shared/stories/organisms/AlertModal.stories.tsx +++ b/shared/stories/organisms/AlertModal.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from "@storybook/react"; +import { useState } from "react"; import { View } from "react-native"; import { globalGray100 } from "../../ui/index"; import AlertModal from "../../ui/organisms/AlertModal"; @@ -26,62 +27,163 @@ type Story = StoryObj; // 1. 버튼 하나 export const SingleButton: Story = { - args: { - title: "알림", - content: "작업이 완료되었습니다.", - confirmLabel: "확인", - onConfirm: () => { - console.log("확인 클릭"); - }, - }, + render: () => ( + + 탈퇴할까요? + { + console.log("확인 클릭"); + }} + /> + + ), }; -// 2. 버튼 두 개 +// 2. 버튼 둘 export const TwoButtons: Story = { - args: { - title: "알림", - content: "이 작업을 진행하시겠습니까?", - cancelLabel: "취소", - confirmLabel: "확인", - onCancel: () => { - console.log("취소 클릭"); - }, - onConfirm: () => { - console.log("확인 클릭"); - }, - }, + render: () => ( + + 탈퇴하기 + { + console.log("취소 클릭"); + }} + onConfirm={() => { + console.log("확인 클릭"); + }} + /> + + ), }; -// 3. 이미지 있음 -export const WithDefaultProfileImage: Story = { - args: { - title: "모달 타이틀", - content: "모달 본문내용 모달 본문내용 모달 본문내용 모달 본문내용", - confirmLabel: "맞아요", - onConfirm: () => { - console.log("확인 클릭"); - }, - }, - render: (args) => ( - +// 3. 타이틀 + 설명 + 버튼 2개 +export const WithText: Story = { + render: () => ( + + 탈퇴하기 + 계정을 삭제하시고 싶으신가요? + { + console.log("취소 클릭"); + }} + onConfirm={() => { + console.log("확인 클릭"); + }} + /> + + ), +}; + +// 4. 프로필 이미지 + 타이틀 + 설명 + 버튼 2개 +export const WithProfileImage: Story = { + render: () => ( + + 탈퇴하기 + 계정을 삭제하시고 싶으신가요? + { + console.log("취소 클릭"); + }} + onConfirm={() => { + console.log("확인 클릭"); + }} + /> ), }; -// 4. 긴 텍스트 -export const LongContent: Story = { - args: { - title: "긴 제목이 들어가는 경우 테스트", - content: - "이것은 매우 긴 콘텐츠 텍스트입니다. 모달의 width가 화면 크기에 따라 조절되고, 콘텐츠는 자동으로 wrap되어야 합니다. 여러 줄에 걸쳐 표시되는 긴 텍스트를 테스트하기 위한 예시입니다.", - cancelLabel: "취소", - confirmLabel: "확인", - onCancel: () => { - console.log("취소 클릭"); - }, - onConfirm: () => { - console.log("확인 클릭"); - }, +// 5. 타이틀 + 설명 + Input + 버튼 2개 +export const WithTextAndInput: Story = { + render: () => { + const [inputValue, setInputValue] = useState(""); + + return ( + + 탈퇴하기 + + 계정을 삭제하려면 탈퇴하기를 입력해주세요 + + + { + console.log("취소 클릭"); + setInputValue(""); + }} + onConfirm={() => { + console.log("확인 클릭", inputValue); + setInputValue(""); + }} + /> + + ); + }, +}; + +// 6. 타이틀 + Input만 +export const WithInputOnly: Story = { + render: () => { + const [inputValue, setInputValue] = useState(""); + + return ( + + 이름 변경 + + { + console.log("취소 클릭"); + setInputValue(""); + }} + onConfirm={() => { + console.log("저장 클릭", inputValue); + setInputValue(""); + }} + /> + + ); }, }; + +// 7. 계정 완전 삭제 확인 (실제 이미지 케이스) +export const DeleteAccountConfirmation: Story = { + render: () => ( + + 탈퇴하기 + + 계정이 탈퇴되었습니다. {"\n"} 그동안 이용해주셔서 감사합니다. + + { + console.log("확인 클릭"); + }} + /> + + ), +}; diff --git a/shared/ui/atoms/Input.tsx b/shared/ui/atoms/Input.tsx index 495bb5a..e332dca 100644 --- a/shared/ui/atoms/Input.tsx +++ b/shared/ui/atoms/Input.tsx @@ -5,20 +5,43 @@ import { TextInputProps, View, } from "react-native"; -import { globalGray200, globalGray600, globalRed50, globalRed600 } from ".."; +import { + globalGray0, + globalGray50, + globalGray600, + globalRed50, + globalRed600, +} from ".."; + +type InputVariant = "default" | "modal"; interface InputProps extends TextInputProps { label?: string; isError?: boolean; + variant?: InputVariant; } -const Input = ({ label, isError = false, ...props }: InputProps) => { +const Input = ({ + label, + isError = false, + variant = "default", + ...props +}: InputProps) => { + const containerStyle = + variant === "modal" ? styles.containerModal : styles.containerDefault; + + const textStyle = + variant === "modal" ? styles.inputModal : styles.inputDefault; + return ( - {label && {label}} + {label && variant === "default" && ( + {label} + )} { > @@ -36,14 +59,21 @@ const Input = ({ label, isError = false, ...props }: InputProps) => { }; const styles = StyleSheet.create({ - container: { + containerBase: { alignSelf: "stretch", minHeight: 48, borderRadius: 8, justifyContent: "center", - borderWidth: 1, - borderColor: globalGray200, paddingRight: 12, + borderWidth: 1, + }, + containerDefault: { + backgroundColor: globalGray0, + borderColor: globalGray0, + }, + containerModal: { + backgroundColor: globalGray50, + borderColor: globalGray50, }, label: { fontFamily: "Pretendard-Regular", @@ -52,18 +82,20 @@ const styles = StyleSheet.create({ fontSize: 14, marginBottom: 12, }, - input: { + inputBase: { fontFamily: "Pretendard-Regular", fontWeight: "400", fontSize: 14, - flex: 1, // 컨테이너의 남은 가로 공간을 다 사용 + flex: 1, marginLeft: 12, letterSpacing: 0, paddingVertical: 0, }, - placeholder: { - color: globalGray600, - fontWeight: "400", + inputDefault: { + lineHeight: 16, // body2 + }, + inputModal: { + lineHeight: 20, // body2wide }, }); diff --git a/shared/ui/atoms/NemoText.tsx b/shared/ui/atoms/NemoText.tsx index c04fe9d..4a62711 100644 --- a/shared/ui/atoms/NemoText.tsx +++ b/shared/ui/atoms/NemoText.tsx @@ -78,6 +78,27 @@ const style = StyleSheet.create({ lineHeight: 18, letterSpacing: 0, }, + text_body2Tight: { + fontWeight: "400", + fontFamily: "Pretendard-Regular", + fontSize: 14, + lineHeight: 16, + letterSpacing: 0, + }, + text_body2wide: { + fontWeight: "400", + fontFamily: "Pretendard-Regular", + fontSize: 14, + lineHeight: 20, + letterSpacing: 0, + }, + text_caption: { + fontWeight: "600", + fontFamily: "Pretendard-Regular", + fontSize: 12, + lineHeight: 14, + letterSpacing: 0, + }, }); export default NemoText; diff --git a/shared/ui/atoms/ProfileImage.tsx b/shared/ui/atoms/ProfileImage.tsx index be52805..be0d0f6 100644 --- a/shared/ui/atoms/ProfileImage.tsx +++ b/shared/ui/atoms/ProfileImage.tsx @@ -1,4 +1,4 @@ -import { Image } from "react-native"; +import { Image, StyleSheet, View } from "react-native"; const defaultUserImage = require("../../../assets/icons/user.svg"); @@ -10,7 +10,17 @@ interface ProfileImageProps { const ProfileImage = ({ uri, size }: ProfileImageProps) => { const imageSource = uri ? { uri } : defaultUserImage; - return ; + return ( + + + + ); }; +const styles = StyleSheet.create({ + container: { + alignItems: "center", + }, +}); + export default ProfileImage; diff --git a/shared/ui/molecules/AlertModalAction.tsx b/shared/ui/molecules/AlertModalAction.tsx new file mode 100644 index 0000000..6f9bacf --- /dev/null +++ b/shared/ui/molecules/AlertModalAction.tsx @@ -0,0 +1,71 @@ +import { StyleSheet, View } from "react-native"; +import { globalSpacingXs } from "../index"; +import ModalButton from "./ModalButton"; + +interface SingleButtonActionsProps { + type: "single"; + confirmLabel: string; + onConfirm: () => void; +} + +interface DoubleButtonActionsProps { + type: "double"; + cancelLabel: string; + confirmLabel: string; + onCancel: () => void; + onConfirm: () => void; +} + +type AlertModalActionsProps = + | SingleButtonActionsProps + | DoubleButtonActionsProps; + +/** + * 모달 액션 버튼들 + */ +const AlertModalActions = (props: AlertModalActionsProps) => { + if (props.type === "single") { + return ( + + + + + + ); + } + + return ( + + + + + + + + + ); +}; + +const styles = StyleSheet.create({ + container: { + flexDirection: "row", + gap: globalSpacingXs, + }, + buttonWrapper: { + flex: 1, + }, +}); + +export default AlertModalActions; diff --git a/shared/ui/molecules/AlertModalInput.tsx b/shared/ui/molecules/AlertModalInput.tsx new file mode 100644 index 0000000..2a5bf5d --- /dev/null +++ b/shared/ui/molecules/AlertModalInput.tsx @@ -0,0 +1,17 @@ +// AlertModalInput.tsx +import { TextInputProps, View } from "react-native"; +import Input from "../atoms/Input"; + +interface AlertModalInputProps extends TextInputProps { + isError?: boolean; +} + +const AlertModalInput = ({ ...props }: AlertModalInputProps) => { + return ( + + + + ); +}; + +export default AlertModalInput; diff --git a/shared/ui/molecules/AlertModalText.tsx b/shared/ui/molecules/AlertModalText.tsx new file mode 100644 index 0000000..132b6bd --- /dev/null +++ b/shared/ui/molecules/AlertModalText.tsx @@ -0,0 +1,32 @@ +import { StyleSheet, View } from "react-native"; +import NemoText from "../atoms/NemoText"; +import { globalGray700 } from "../index"; + +interface AlertModalTextProps { + children: React.ReactNode; +} + +/** + * 모달 설명 텍스트 + */ +const AlertModalText = ({ children }: AlertModalTextProps) => { + return ( + + + {children} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: "center", + }, + text: { + color: globalGray700, + textAlign: "center", + }, +}); + +export default AlertModalText; diff --git a/shared/ui/molecules/AlertModalTitle.tsx b/shared/ui/molecules/AlertModalTitle.tsx new file mode 100644 index 0000000..f5cfb7b --- /dev/null +++ b/shared/ui/molecules/AlertModalTitle.tsx @@ -0,0 +1,25 @@ +import { StyleSheet, View } from "react-native"; +import NemoText from "../atoms/NemoText"; + +interface AlertModalTitleProps { + children: string; +} + +/** + * 모달 타이틀 + */ +const AlertModalTitle = ({ children }: AlertModalTitleProps) => { + return ( + + {children} + + ); +}; + +const styles = StyleSheet.create({ + container: { + alignItems: "center", + }, +}); + +export default AlertModalTitle; diff --git a/shared/ui/organisms/AlertModal.tsx b/shared/ui/organisms/AlertModal.tsx index 4dc4a44..867fae3 100644 --- a/shared/ui/organisms/AlertModal.tsx +++ b/shared/ui/organisms/AlertModal.tsx @@ -1,121 +1,96 @@ import { StyleSheet, View } from "react-native"; -import NemoText from "../atoms/NemoText"; +import { globalGray0, globalSpacingLg, globalSpacingSm } from "../index"; + import ProfileImage from "../atoms/ProfileImage"; -import { - globalGray0, - globalGray700, - globalSpacingLg, - globalSpacingSm, - globalSpacingXs, -} from "../index"; -import ModalButton from "../molecules/ModalButton"; +import AlertModalActions from "../molecules/AlertModalAction"; +import AlertModalInput from "../molecules/AlertModalInput"; +import AlertModalText from "../molecules/AlertModalText"; +import AlertModalTitle from "../molecules/AlertModalTitle"; interface AlertModalProps { - children?: React.ReactNode; - title: string; - content?: string; - cancelLabel?: string; - confirmLabel: string; - onCancel?: () => void; - onConfirm: () => void; + children: React.ReactNode; } /** - * AlertModal 컴포넌트 + * AlertModal - Compound Component Pattern + * + * 각 하위 컴포넌트를 조합하여 다양한 형태의 모달 구성 가능 * * @example - * // 버튼 하나만 - * {}} - * /> + * // 기본 확인 모달 + * + * 알림 + * 작업이 완료되었습니다. + * {}} + * /> + * * * @example - * // 버튼 두 개 - * {}} - * onConfirm={() => {}} - * /> + * // 이미지 + 타이틀 + 설명 + * + * + * 사용자 정보 + * 정보를 수정하시겠습니까? + * {}} + * onConfirm={() => {}} + * /> + * * * @example - * // 프로필 이미지 포함 (기본 이미지) - * {}} - * > - * + * // 타이틀 + 설명 + Input + * + * 탈퇴하기 + * + * 계정을 삭제하려면 탈퇴하기를 입력해주세요 + * + * + * {}} + * onConfirm={() => {}} + * /> * * * @example - * // 프로필 이미지 포함 (커스텀 이미지) - * {}} - * onConfirm={() => {}} - * > - * + * // 타이틀 + Input만 + * + * 이름 변경 + * + * {}} + * onConfirm={() => {}} + * /> * */ - -const AlertModal = ({ - title, - content, - cancelLabel, - confirmLabel, - onCancel, - onConfirm, - children, -}: AlertModalProps) => { - return ( - - {children && {children}} - - - {title} - - - {content && ( - - - {content} - - - )} - - - {cancelLabel && onCancel && ( - - - - )} - - - - - - ); +const AlertModal = ({ children }: AlertModalProps) => { + return {children}; }; -// Composition을 위해 ProfileImage를 붙임 +// Compound Components +AlertModal.Title = AlertModalTitle; +AlertModal.Text = AlertModalText; +AlertModal.Input = AlertModalInput; +AlertModal.Actions = AlertModalActions; AlertModal.ProfileImage = ProfileImage; const styles = StyleSheet.create({ @@ -128,22 +103,6 @@ const styles = StyleSheet.create({ padding: globalSpacingLg, alignSelf: "center", }, - image: { - alignItems: "center", - }, - title: { - alignItems: "center", - }, - content: { - alignItems: "center", - }, - footer: { - flexDirection: "row", - gap: globalSpacingXs, - }, - buttonWrapper: { - flex: 1, - }, }); export default AlertModal;