From 3560803a0939a9f449409c4a6c1f41bc85555ac2 Mon Sep 17 00:00:00 2001 From: JungSoEun <85235356+ssilver01@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:11:21 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20BottomSheet=20onClose=20Context=20A?= =?UTF-8?q?PI=20=EB=8F=84=EC=9E=85=EC=9C=BC=EB=A1=9C=20props=20drilling=20?= =?UTF-8?q?=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx | 3 ++- .../shared/ui/bottomSheet/BottomSheetContext.tsx | 13 +++++++++++++ apps/web/src/shared/ui/bottomSheet/index.ts | 1 + .../templates/BaseBottomSheetTemplate.tsx | 10 +++------- 4 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx diff --git a/apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx b/apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx index 0d61047f..4e005d12 100644 --- a/apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx +++ b/apps/web/src/shared/ui/bottomSheet/BottomSheet.tsx @@ -3,6 +3,7 @@ import { PropsWithChildren, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; +import { BottomSheetContext } from './BottomSheetContext'; import * as styles from './BottomSheet.css'; export interface BottomSheetProps { @@ -67,7 +68,7 @@ export const BottomSheet = ({
e.stopPropagation()}> - {children} + {children}
, document.body diff --git a/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx b/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx new file mode 100644 index 00000000..3aa36a9a --- /dev/null +++ b/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx @@ -0,0 +1,13 @@ +import { createContext, useContext } from 'react'; + +interface BottomSheetContextValue { + onClose: () => void; +} + +export const BottomSheetContext = createContext(null); + +export const useBottomSheetContext = (): BottomSheetContextValue => { + const ctx = useContext(BottomSheetContext); + if (!ctx) throw new Error('useBottomSheetContext must be used within BottomSheet'); + return ctx; +}; diff --git a/apps/web/src/shared/ui/bottomSheet/index.ts b/apps/web/src/shared/ui/bottomSheet/index.ts index 9d638371..5495533e 100644 --- a/apps/web/src/shared/ui/bottomSheet/index.ts +++ b/apps/web/src/shared/ui/bottomSheet/index.ts @@ -1,3 +1,4 @@ export { BottomSheet } from './BottomSheet'; export type { BottomSheetProps } from './BottomSheet'; export { BaseBottomSheetTemplate } from './templates'; +export { useBottomSheetContext } from './BottomSheetContext'; diff --git a/apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx b/apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx index 5a81be80..493f1621 100644 --- a/apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx +++ b/apps/web/src/shared/ui/bottomSheet/templates/BaseBottomSheetTemplate.tsx @@ -12,6 +12,7 @@ import { Text } from '../../text'; import { vars } from '../../theme.css'; import { IcClear, IcPlusSimple } from 'public/icons'; import { Button } from '../../button'; +import { useBottomSheetContext } from '../BottomSheetContext'; interface BottomSheetButtonProps { label: string; @@ -23,7 +24,6 @@ interface BottomSheetHeaderProps { text?: string; type?: headerType; onClickAddBtn?: () => void; - onClose?: () => void; } const BaseBottomSheetTemplate = ({ children }: { children: React.ReactNode }) => { @@ -40,12 +40,8 @@ const BottomSheetContent = ({ return
{children}
; }; -const BottomSheetHeader = ({ - text, - type = 'close', - onClickAddBtn, - onClose, -}: BottomSheetHeaderProps) => { +const BottomSheetHeader = ({ text, type = 'close', onClickAddBtn }: BottomSheetHeaderProps) => { + const { onClose } = useBottomSheetContext(); return (
From cfabfb34842dce62b643496ea3e1149c5ad60603 Mon Sep 17 00:00:00 2001 From: JungSoEun <85235356+ssilver01@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:11:36 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20BottomSheet=20Context=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9=EC=9C=BC=EB=A1=9C=20onClose=20props=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datePickerModal/ui/DatePickerBottomSheet.tsx | 5 +---- .../features/datePickerModal/ui/DatePickerFeature.tsx | 1 - .../src/features/expense/ui/ExpenseEditBottomSheet.tsx | 2 -- .../expenseBottomSheet/DatePickerBottomSheet.stories.tsx | 8 -------- .../ui/expenseBottomSheet/DatePickerBottomSheet.tsx | 5 +---- .../ExpenseFormBottomSheet.stories.tsx | 9 --------- .../ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx | 5 +---- .../expenseBottomSheet/IconPickerBottomSheet.stories.tsx | 8 -------- .../ui/expenseBottomSheet/IconPickerBottomSheet.tsx | 5 +---- .../expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx | 1 - .../expense/ui/steps/AmountDateStep/AmountDateStep.tsx | 1 - .../ui/steps/AmountDateStep/CalendarBottomSheet.tsx | 4 +--- apps/web/src/widgets/addCategory/ui/AddCategory.tsx | 1 - 13 files changed, 5 insertions(+), 50 deletions(-) diff --git a/apps/web/src/features/datePickerModal/ui/DatePickerBottomSheet.tsx b/apps/web/src/features/datePickerModal/ui/DatePickerBottomSheet.tsx index 2d42a1db..035a625b 100644 --- a/apps/web/src/features/datePickerModal/ui/DatePickerBottomSheet.tsx +++ b/apps/web/src/features/datePickerModal/ui/DatePickerBottomSheet.tsx @@ -10,8 +10,6 @@ export interface DatePickerBottomSheetTemplateProps { initialMonth: number; /** 선택 버튼 클릭 시 콜백 */ onConfirm?: (year: number, month: number) => void; - /** X 버튼 클릭 시 콜백 */ - onClose?: () => void; /** 미래 날짜 선택 허용 여부 (기본값: false) */ allowFuture?: boolean; } @@ -26,7 +24,6 @@ export const DatePickerBottomSheetTemplate = ({ initialYear, initialMonth, onConfirm, - onClose, allowFuture = false, }: DatePickerBottomSheetTemplateProps) => { const [tempValue, setTempValue] = useState({ year: initialYear, month: initialMonth }); @@ -65,7 +62,7 @@ export const DatePickerBottomSheetTemplate = ({ return ( - +
diff --git a/apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx b/apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx index 2a86854c..b9b7fb36 100644 --- a/apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx +++ b/apps/web/src/features/expense/ui/ExpenseEditBottomSheet.tsx @@ -223,7 +223,6 @@ export const ExpenseEditBottomSheet = ({ onCategorySelect={(cat) => setSelectedCategoryId(cat.id)} onConfirm={handleConfirm} onDelete={handleDelete} - onClose={onClose} selectedDate={date} onDateClick={() => setIsCalendarOpen(true)} onMoreCategoryClick={() => setIsCategorySheetOpen(true)} @@ -251,7 +250,6 @@ export const ExpenseEditBottomSheet = ({ if (newDate) setDate(newDate); }} onConfirm={() => setIsCalendarOpen(false)} - onClose={() => setIsCalendarOpen(false)} /> setIsCategorySheetOpen(false)}> diff --git a/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx b/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx index 50e5b640..3c0ec3c9 100644 --- a/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx +++ b/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.stories.tsx @@ -35,7 +35,6 @@ const meta = { ' selectedDate={selectedDate}', ' onSelectDate={setSelectedDate}', ' onConfirm={() => {}}', - ' onClose={() => {}}', '/>', '```', ].join('\n'), @@ -63,12 +62,6 @@ const meta = { type: { summary: '(year: number, month: number) => void' }, }, }, - onClose: { - description: '닫기 버튼 클릭 시 콜백', - table: { - type: { summary: '() => void' }, - }, - }, allowFuture: { control: 'boolean', description: '미래 날짜 선택 허용 여부', @@ -110,7 +103,6 @@ export const Default: Story = { { alert(`선택된 월: ${year}년 ${month}월`); closeModal(); diff --git a/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.tsx b/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.tsx index a0a58e69..2d077cda 100644 --- a/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.tsx +++ b/apps/web/src/features/expense/ui/expenseBottomSheet/DatePickerBottomSheet.tsx @@ -10,8 +10,6 @@ export interface DatePickerBottomSheetTemplateProps { initialMonth: number; /** 선택 버튼 클릭 시 콜백 */ onConfirm?: (year: number, month: number) => void; - /** X 버튼 클릭 시 콜백 */ - onClose?: () => void; /** 미래 날짜 선택 허용 여부 (기본값: false) */ allowFuture?: boolean; } @@ -20,7 +18,6 @@ export const DatePickerBottomSheetTemplate = ({ initialYear, initialMonth, onConfirm, - onClose, allowFuture = false, }: DatePickerBottomSheetTemplateProps) => { const [tempValue, setTempValue] = useState({ year: initialYear, month: initialMonth }); @@ -59,7 +56,7 @@ export const DatePickerBottomSheetTemplate = ({ return ( - +
setSelectedCategoryId(category.id)}', ' onConfirm={() => {}}', - ' onClose={() => {}}', '/>', '```', ].join('\n'), @@ -119,12 +118,6 @@ const meta = { type: { summary: '() => void' }, }, }, - onClose: { - description: '닫기 버튼 클릭 시 콜백', - table: { - type: { summary: '() => void' }, - }, - }, }, } satisfies Meta; @@ -169,7 +162,6 @@ export const Default: Story = { satisfactionLabel='만족도 낮음' satisfactionEmoji='😒' onDelete={() => alert('삭제')} - onClose={closeModal} onConfirm={() => { alert('소비 입력 완료'); closeModal(); @@ -232,7 +224,6 @@ export const EmptyForm: Story = { onCategorySelect={(category) => setSelectedCategoryId(category.id)} onMoreCategoryClick={() => alert('더보기 클릭')} onDelete={() => alert('삭제')} - onClose={closeModal} onConfirm={() => { alert('소비 입력 완료'); closeModal(); diff --git a/apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx b/apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx index 742b9bb8..173aeeea 100644 --- a/apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx +++ b/apps/web/src/features/expense/ui/expenseBottomSheet/ExpenseFormBottomSheet.tsx @@ -51,8 +51,6 @@ export interface ExpenseFormBottomSheetProps { onDelete?: () => void; /** 선택 버튼 클릭 시 콜백 */ onConfirm?: () => void; - /** X 버튼 클릭 시 콜백 */ - onClose?: () => void; /** 확인 버튼 비활성화 여부 */ confirmDisabled?: boolean; /** 소비 금액 에러 메세지 */ @@ -79,7 +77,6 @@ export const ExpenseFormBottomSheet = ({ satisfactionEvaluationType, onDelete, onConfirm, - onClose, confirmDisabled, amountErrorMessage, isAmountError, @@ -98,7 +95,7 @@ export const ExpenseFormBottomSheet = ({ return ( - + {/* 소비금액 */} diff --git a/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx b/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx index 830303a3..170e46fd 100644 --- a/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx +++ b/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.stories.tsx @@ -39,7 +39,6 @@ const meta = { ' selectedId={selectedId}', ' onSelect={(category) => setSelectedId(category.id)}', ' onConfirm={() => {}}', - ' onClose={() => {}}', '/>', '```', ].join('\n'), @@ -72,12 +71,6 @@ const meta = { type: { summary: '() => void' }, }, }, - onClose: { - description: '닫기 버튼 클릭 시 콜백', - table: { - type: { summary: '() => void' }, - }, - }, }, } satisfies Meta; @@ -134,7 +127,6 @@ export const Default: Story = { categories={mockCategories} selectedId={selectedId} onSelect={(category) => setSelectedId(category.id)} - onClose={closeModal} onConfirm={() => { alert(`선택된 아이콘: ${selectedId}`); closeModal(); diff --git a/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.tsx b/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.tsx index 8631173d..c66ce133 100644 --- a/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.tsx +++ b/apps/web/src/features/expense/ui/expenseBottomSheet/IconPickerBottomSheet.tsx @@ -11,8 +11,6 @@ export interface IconPickerBottomSheetTemplateProps { onSelect?: (category: CategoryItem) => void; /** 선택 버튼 클릭 시 콜백 */ onConfirm?: () => void; - /** X 버튼 클릭 시 콜백 */ - onClose?: () => void; } export const IconPickerBottomSheetTemplate = ({ @@ -20,11 +18,10 @@ export const IconPickerBottomSheetTemplate = ({ selectedId, onSelect, onConfirm, - onClose, }: IconPickerBottomSheetTemplateProps) => { return ( - +
{categories.map((category) => ( diff --git a/apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx b/apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx index 28199b6e..fcecbef6 100644 --- a/apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx +++ b/apps/web/src/features/expense/ui/steps/AddCategoryStep/AddCategoryStep.tsx @@ -154,7 +154,6 @@ export const AddCategoryStep = ({ onBack }: AddCategoryStepProps) => { selectedId={tempIcon?.id} onSelect={setTempIcon} onConfirm={handleConfirm} - onClose={closeBottomSheet} /> diff --git a/apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx b/apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx index a5e8be28..126811d5 100644 --- a/apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx +++ b/apps/web/src/features/expense/ui/steps/AmountDateStep/AmountDateStep.tsx @@ -44,7 +44,6 @@ export const AmountDateStep = ({ onNext, defaultAmount, defaultDate }: AmountDat onSelectDate={(date) => { if (date) setSelectedDate(date); }} - onClose={closeModal} onConfirm={closeModal} /> diff --git a/apps/web/src/features/expense/ui/steps/AmountDateStep/CalendarBottomSheet.tsx b/apps/web/src/features/expense/ui/steps/AmountDateStep/CalendarBottomSheet.tsx index e5bac8d9..fe341894 100644 --- a/apps/web/src/features/expense/ui/steps/AmountDateStep/CalendarBottomSheet.tsx +++ b/apps/web/src/features/expense/ui/steps/AmountDateStep/CalendarBottomSheet.tsx @@ -14,14 +14,12 @@ interface CalendarBottomSheetTemplateProps { selectedDate?: Date; onSelectDate?: (date: Date | null) => void; onConfirm?: () => void; - onClose?: () => void; } export const CalendarBottomSheetTemplate = ({ selectedDate: initialDate, onSelectDate, onConfirm, - onClose, }: CalendarBottomSheetTemplateProps) => { const [selectedDate, setSelectedDate] = useState(initialDate); const [currentDate, setCurrentDate] = useState(initialDate || new Date()); @@ -43,7 +41,7 @@ export const CalendarBottomSheetTemplate = ({ return ( - +
{ selectedId={tempIcon?.id} onSelect={setTempIcon} onConfirm={handleConfirm} - onClose={closeBottomSheet} /> From a925bfdcc3f0bca3682b186f87984476e5afec8f Mon Sep 17 00:00:00 2001 From: JungSoEun <85235356+ssilver01@users.noreply.github.com> Date: Tue, 21 Apr 2026 16:24:45 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20use=20client=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx b/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx index 3aa36a9a..0ece1dca 100644 --- a/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx +++ b/apps/web/src/shared/ui/bottomSheet/BottomSheetContext.tsx @@ -1,3 +1,5 @@ +'use client'; + import { createContext, useContext } from 'react'; interface BottomSheetContextValue {