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 {