Skip to content

Commit

Permalink
feat: modal 버튼 속성 custom 가능하게 수정
Browse files Browse the repository at this point in the history
  • Loading branch information
yeynii committed Oct 15, 2023
1 parent 98b51d3 commit 856355b
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 38 deletions.
9 changes: 7 additions & 2 deletions src/contexts/ModalProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { createContext, type PropsWithChildren, useContext, useState } from 'react';

import { type ButtonProps } from '@/domain/_common/components';
import Modal from '@/domain/_common/components/Modal';

interface ModalData {
title: string;
message: string;
closeButton?: { label: string; onClick?: () => void };
confirmButton?: { label: string; onClick: () => void };
closeButton?: {
text: string;
} & Omit<ButtonProps, 'children'>;
confirmButton?: {
text: string;
} & Omit<ButtonProps, 'children'>;
}

interface ModalContextType {
Expand Down
2 changes: 1 addition & 1 deletion src/domain/_common/components/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { type ReactNode } from 'react';

interface ButtonProps {
export interface ButtonProps {
disabled?: boolean;
variant?: 'text' | 'contained';
color?: 'grey' | 'primary' | 'red';
Expand Down
43 changes: 21 additions & 22 deletions src/domain/_common/components/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
import React, { Fragment } from 'react';

import { ReactComponent as CloseIcon } from '@/assets/close.svg';
import { Button } from '@/domain/_common/components/Button';
import { Button, type ButtonProps } from '@/domain/_common/components/Button';

interface ModalProps {
title: string;
message: string;
onClose: () => void;
closeButton?: {
label: string;
};
text: string;
} & Omit<ButtonProps, 'children'>;
confirmButton?: {
label: string;
onClick: () => void;
};
text: string;
} & Omit<ButtonProps, 'children'>;
}
export default function Modal({ title, message, onClose, closeButton, confirmButton }: ModalProps) {
return (
<>
<div className="absolute top-0 left-0 w-full h-full bg-black bg-opacity-40" onClick={onClose} />
<div className="absolute top-1/2 left-1/2 translate-x-[-50%] translate-y-[-50%]">
<div className="z-10 bg-white rounded-[12px] text-center flex flex-col p-6 justify-center items-start gap-6">
<div className="absolute top-1/2 left-1/2 translate-x-[-50%] translate-y-[-50%] p-6 w-full">
<div className="z-10 m-auto max-w-[335px] bg-white rounded-[12px] text-center flex flex-col p-6 justify-center items-start gap-6">
<div className="text-[24px] font-bold stroke-grey-placeholder flex justify-between w-full">
{title} <CloseIcon className="cursor-pointer" onClick={onClose} />
</div>
<div className="text-[18px] font-bold text-grey-placeholder">{message}</div>
<div className="flex gap-6">
{closeButton && (
<Button isDisabled={false} type="text" onClick={onClose}>
{closeButton.label}
</Button>
)}
{confirmButton && (
<Button isDisabled={false} type="primary" onClick={confirmButton.onClick}>
{confirmButton.label}
</Button>
)}
</div>
{(!!closeButton || !!confirmButton) && (
<div className="flex w-full gap-6">
{closeButton && (
<Button variant="contained" color="grey" onClick={onClose} {...closeButton}>
{closeButton.text}
</Button>
)}
{confirmButton && (
<Button variant="contained" color="red" {...confirmButton}>
{confirmButton.text}
</Button>
)}
</div>
)}
</div>
</div>
</>
Expand Down
91 changes: 78 additions & 13 deletions src/stories/Modal.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,83 @@ import type { Meta, StoryObj } from '@storybook/react';

import { useModal } from '@/contexts/ModalProvider';
import { Button } from '@/domain/_common/components';
import Modal from '@/domain/_common/components/Modal';

export default {
title: 'Components/Modal',
parameters: {
layout: 'centered',
design: {
type: 'figma',
url: 'https://www.figma.com/file/KHvd0JBcID35sOdr61Iief/Main?type=design&node-id=216-7319&mode=design&t=jq3LIMBJupzd6oGf-4',
docs: {
story: {
height: '500px',
},
},
},
} satisfies Meta<typeof HTMLDivElement>;
component: Modal,
tags: ['autodocs'],
} satisfies Meta<typeof Modal>;

type Story = StoryObj<typeof HTMLDivElement>;
export const Basic: Story = {
type Story = StoryObj<typeof Modal>;

export const CloseConfirm: Story = {
render: () => {
const { openModal } = useModal();
const onClickNormal = () => {
openModal({
title: '제목',
message: '메시지',
});
};

const onClickConfirmClose = () => {
openModal({
title: '제목',
message: '메시지',
closeButton: {
text: '닫기',
},
confirmButton: {
text: '확인',
onClick: () => {
alert('확인');
},
},
});
};

const onClickConfirm = () => {
openModal({
title: '제목',
message: '메시지',
confirmButton: {
text: '확인',
onClick: () => {
alert('확인');
},
},
});
};

const onClickClose = () => {
openModal({
title: '제목',
message: '메시지',
closeButton: {
text: '닫기',
},
});
};

const onClick = () => {
const onClickCustom = () => {
openModal({
title: '제목',
message: '메시지',
closeButton: {
label: '닫기',
text: '닫기',
variant: 'text',
},
confirmButton: {
label: '확인',
text: '확인',
variant: 'text',
onClick: () => {
alert('확인');
},
Expand All @@ -36,9 +87,23 @@ export const Basic: Story = {
};

return (
<Button isDisabled={false} type="primary" onClick={onClick}>
클릭
</Button>
<div className="flex flex-col w-[500px] gap-4 p-4">
<Button variant="contained" onClick={onClickNormal}>
Normal
</Button>
<Button variant="contained" onClick={onClickConfirmClose}>
Confirm & Close
</Button>
<Button variant="contained" onClick={onClickConfirm}>
Confirm
</Button>
<Button variant="contained" onClick={onClickClose}>
Close
</Button>
<Button variant="contained" onClick={onClickCustom}>
Custom
</Button>
</div>
);
},
};

0 comments on commit 856355b

Please sign in to comment.