From 78abe01a59cccd454dc4f961dd81900887ad8a9a Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 8 Jul 2026 06:44:38 +0900 Subject: [PATCH 01/10] =?UTF-8?q?feat(ui):=20Calendar=20=EC=BB=B4=ED=8F=AC?= =?UTF-8?q?=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/calendar/Calendar.tsx | 147 ++++++++++++++++++ .../src/components/index.ts | 2 + 2 files changed, 149 insertions(+) create mode 100644 packages/timo-design-system/src/components/calendar/Calendar.tsx diff --git a/packages/timo-design-system/src/components/calendar/Calendar.tsx b/packages/timo-design-system/src/components/calendar/Calendar.tsx new file mode 100644 index 00000000..3442f33a --- /dev/null +++ b/packages/timo-design-system/src/components/calendar/Calendar.tsx @@ -0,0 +1,147 @@ +import { useState } from "react"; + +import { cn } from "../../lib"; +import { WeeklyButton } from "../button/weekly-button/WeeklyButton"; + +const WEEKDAYS = ["S", "M", "T", "W", "T", "F", "S"]; + +const MONTH_LABELS = [ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +]; + +interface CalendarDate { + date: Date; + day: number; + isCurrentMonth: boolean; +} + +const getCalendarDates = (month: Date): CalendarDate[] => { + const year = month.getFullYear(); + const monthIndex = month.getMonth(); + const firstDate = new Date(year, monthIndex, 1); + const firstDay = firstDate.getDay(); + const startDate = new Date(year, monthIndex, 1 - firstDay); + + return Array.from({ length: 35 }, (_, index) => { + const date = new Date( + startDate.getFullYear(), + startDate.getMonth(), + startDate.getDate() + index, + ); + + return { + date, + day: date.getDate(), + isCurrentMonth: date.getMonth() === monthIndex, + }; + }); +}; + +export interface CalendarProps { + value?: Date; + defaultMonth?: Date; + onChange?: (date: Date) => void; + className?: string; +} + +export const Calendar = ({ + value, + defaultMonth, + onChange, + className, +}: CalendarProps) => { + const [visibleMonth, setVisibleMonth] = useState( + defaultMonth ?? value ?? new Date(), + ); + const calendarDates = getCalendarDates(visibleMonth); + const today = new Date(); + const isSameDate = (a: Date, b: Date) => { + return ( + a.getFullYear() === b.getFullYear() && + a.getMonth() === b.getMonth() && + a.getDate() === b.getDate() + ); + }; + const moveMonth = (amount: number) => { + setVisibleMonth( + (prev) => new Date(prev.getFullYear(), prev.getMonth() + amount, 1), + ); + }; + + return ( +
+
+ moveMonth(-1)} + className="absolute top-0 left-0" + /> + +
+ + {MONTH_LABELS[visibleMonth.getMonth()]} + + + {visibleMonth.getFullYear()} + +
+ + moveMonth(1)} + className="absolute top-0 right-0" + /> +
+ +
+ {WEEKDAYS.map((weekday, index) => ( +
+ {weekday} +
+ ))} + + {calendarDates.map((calendarDate) => { + const isSelected = value + ? isSameDate(calendarDate.date, value) + : false; + const isToday = isSameDate(calendarDate.date, today); + + return ( + + ); + })} +
+
+ ); +}; diff --git a/packages/timo-design-system/src/components/index.ts b/packages/timo-design-system/src/components/index.ts index d13011e2..be5c7d45 100644 --- a/packages/timo-design-system/src/components/index.ts +++ b/packages/timo-design-system/src/components/index.ts @@ -35,3 +35,5 @@ export { TodayButton } from "./button/today-button/TodayButton"; export { WeeklyButton } from "./button/weekly-button/WeeklyButton"; export { TimeSelector } from "./time/time-selector/TimeSelector"; export { RepeatSelector } from "./repeat/repeat-selector/RepeatSelector"; +export { Calendar } from "./calendar/Calendar"; +export type { CalendarProps } from "./calendar/Calendar"; From 0c11d8983d53eb35ab7f3743e6a9aed6b6c49d08 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 8 Jul 2026 06:44:53 +0900 Subject: [PATCH 02/10] =?UTF-8?q?docs(ui):=20Calendar=20=EC=8A=A4=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/calendar/Calendar.stories.tsx | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 packages/timo-design-system/src/components/calendar/Calendar.stories.tsx diff --git a/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx b/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx new file mode 100644 index 00000000..07fcb4e4 --- /dev/null +++ b/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx @@ -0,0 +1,36 @@ +import { useState } from "react"; + +import { Calendar } from "./Calendar"; + +import type { CalendarProps } from "./Calendar"; +import type { Meta, StoryObj } from "@storybook/react"; + +const meta = { + title: "Components/Calendar", + component: Calendar, + parameters: { + layout: "centered", + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +const CalendarDemo = (args: CalendarProps) => { + const [selectedDate, setSelectedDate] = useState( + new Date(2026, 5, 24), + ); + + return ( + + ); +}; + +export const Default: Story = { + render: (args) => , +}; From 310460476c4c8217d90d53e24cddfdb4e26c77af Mon Sep 17 00:00:00 2001 From: "Novaris." Date: Wed, 8 Jul 2026 20:05:49 +0900 Subject: [PATCH 03/10] =?UTF-8?q?refactor(ui):=20=EC=9B=94=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99=20=ED=95=B8=EB=93=A4=EB=9F=AC=20=EB=84=A4=EC=9D=B4?= =?UTF-8?q?=EB=B0=8D=20=EA=B0=9C=EC=84=A0=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 김민아 --- .../timo-design-system/src/components/calendar/Calendar.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/timo-design-system/src/components/calendar/Calendar.tsx b/packages/timo-design-system/src/components/calendar/Calendar.tsx index 3442f33a..6cd12877 100644 --- a/packages/timo-design-system/src/components/calendar/Calendar.tsx +++ b/packages/timo-design-system/src/components/calendar/Calendar.tsx @@ -73,7 +73,8 @@ export const Calendar = ({ a.getDate() === b.getDate() ); }; - const moveMonth = (amount: number) => { + + const handleMoveMonth = (amount: number) => { setVisibleMonth( (prev) => new Date(prev.getFullYear(), prev.getMonth() + amount, 1), ); From 37e7bdb7906361d1325432a71df0bf2fe35d1d64 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 8 Jul 2026 20:22:06 +0900 Subject: [PATCH 04/10] =?UTF-8?q?refactor(ui):=20WeeklyButton=EC=9D=84=20C?= =?UTF-8?q?hevronButton=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChevronButton.stories.tsx} | 2 +- .../WeeklyButton.tsx => chevron-button/ChevronButton.tsx} | 0 .../timo-design-system/src/components/calendar/Calendar.tsx | 2 +- packages/timo-design-system/src/components/index.ts | 3 +-- 4 files changed, 3 insertions(+), 4 deletions(-) rename packages/timo-design-system/src/components/button/{weekly-button/WeeklyButton.stories.tsx => chevron-button/ChevronButton.stories.tsx} (93%) rename packages/timo-design-system/src/components/button/{weekly-button/WeeklyButton.tsx => chevron-button/ChevronButton.tsx} (100%) diff --git a/packages/timo-design-system/src/components/button/weekly-button/WeeklyButton.stories.tsx b/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx similarity index 93% rename from packages/timo-design-system/src/components/button/weekly-button/WeeklyButton.stories.tsx rename to packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx index 88ccc0be..fd2da25a 100644 --- a/packages/timo-design-system/src/components/button/weekly-button/WeeklyButton.stories.tsx +++ b/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx @@ -1,4 +1,4 @@ -import { WeeklyButton } from "./WeeklyButton"; +import { WeeklyButton } from "./ChevronButton"; import type { Meta, StoryObj } from "@storybook/react"; diff --git a/packages/timo-design-system/src/components/button/weekly-button/WeeklyButton.tsx b/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.tsx similarity index 100% rename from packages/timo-design-system/src/components/button/weekly-button/WeeklyButton.tsx rename to packages/timo-design-system/src/components/button/chevron-button/ChevronButton.tsx diff --git a/packages/timo-design-system/src/components/calendar/Calendar.tsx b/packages/timo-design-system/src/components/calendar/Calendar.tsx index 6cd12877..9419cc1a 100644 --- a/packages/timo-design-system/src/components/calendar/Calendar.tsx +++ b/packages/timo-design-system/src/components/calendar/Calendar.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { cn } from "../../lib"; -import { WeeklyButton } from "../button/weekly-button/WeeklyButton"; +import { WeeklyButton } from "../button/chevron-button/ChevronButton"; const WEEKDAYS = ["S", "M", "T", "W", "T", "F", "S"]; diff --git a/packages/timo-design-system/src/components/index.ts b/packages/timo-design-system/src/components/index.ts index be5c7d45..9253de1d 100644 --- a/packages/timo-design-system/src/components/index.ts +++ b/packages/timo-design-system/src/components/index.ts @@ -32,8 +32,7 @@ export type { } from "./layout/modal/Modal"; export { SidebarButton } from "./button/sidebar-button/SidebarButton"; export { TodayButton } from "./button/today-button/TodayButton"; -export { WeeklyButton } from "./button/weekly-button/WeeklyButton"; +export { WeeklyButton } from "./button/chevron-button/ChevronButton"; export { TimeSelector } from "./time/time-selector/TimeSelector"; export { RepeatSelector } from "./repeat/repeat-selector/RepeatSelector"; export { Calendar } from "./calendar/Calendar"; -export type { CalendarProps } from "./calendar/Calendar"; From 40c18d5ddc4543307b99c4edb906f17a145d4ca0 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 8 Jul 2026 20:25:56 +0900 Subject: [PATCH 05/10] =?UTF-8?q?refactor(ui):=20ChevronButton=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EC=8A=A4=ED=86=A0=EB=A6=AC?= =?UTF-8?q?=EB=B6=81=20=EB=B0=98=EC=98=81=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/button/chevron-button/ChevronButton.stories.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx b/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx index fd2da25a..9dabc8e0 100644 --- a/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx +++ b/packages/timo-design-system/src/components/button/chevron-button/ChevronButton.stories.tsx @@ -3,7 +3,7 @@ import { WeeklyButton } from "./ChevronButton"; import type { Meta, StoryObj } from "@storybook/react"; const meta = { - title: "Components/Button/WeeklyButton", + title: "Components/Button/ChevronButton", component: WeeklyButton, parameters: { layout: "centered", From 1d2bb2c30ad53f2e813d80313b5542aeb32bc14f Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 8 Jul 2026 20:28:49 +0900 Subject: [PATCH 06/10] =?UTF-8?q?fix(ui):=20Calendar=20=EC=99=B8=EB=B6=80?= =?UTF-8?q?=20=EC=9B=94=20=EB=82=A0=EC=A7=9C=20=EC=84=A0=ED=83=9D=20?= =?UTF-8?q?=EB=8F=99=EC=9E=91=20=EC=88=98=EC=A0=95=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/calendar/Calendar.stories.tsx | 2 +- .../src/components/calendar/Calendar.tsx | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx b/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx index 07fcb4e4..08e75ce5 100644 --- a/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx +++ b/packages/timo-design-system/src/components/calendar/Calendar.stories.tsx @@ -18,7 +18,7 @@ type Story = StoryObj; const CalendarDemo = (args: CalendarProps) => { const [selectedDate, setSelectedDate] = useState( - new Date(2026, 5, 24), + new Date(2026, 6, 1), ); return ( diff --git a/packages/timo-design-system/src/components/calendar/Calendar.tsx b/packages/timo-design-system/src/components/calendar/Calendar.tsx index 9419cc1a..a46aec30 100644 --- a/packages/timo-design-system/src/components/calendar/Calendar.tsx +++ b/packages/timo-design-system/src/components/calendar/Calendar.tsx @@ -127,7 +127,19 @@ export const Calendar = ({ ); diff --git a/packages/timo-design-system/src/components/calendar/Calendar.tsx b/packages/timo-design-system/src/components/calendar/Calendar.tsx index f4e49a89..ad80aebe 100644 --- a/packages/timo-design-system/src/components/calendar/Calendar.tsx +++ b/packages/timo-design-system/src/components/calendar/Calendar.tsx @@ -1,7 +1,7 @@ import { useState } from "react"; import { cn } from "../../lib"; -import { WeeklyButton } from "../button/chevron-button/ChevronButton"; +import { ChevronButton } from "../button/chevron-button/ChevronButton"; const WEEKDAYS = ["S", "M", "T", "W", "T", "F", "S"]; @@ -90,7 +90,7 @@ export const Calendar = ({ className={cn("h-66 w-67 rounded-[4px] bg-white px-6 py-4", className)} >
- handleMoveMonth(-1)} className="absolute top-0 left-0" @@ -105,7 +105,7 @@ export const Calendar = ({
- handleMoveMonth(1)} className="absolute top-0 right-0" diff --git a/packages/timo-design-system/src/components/index.ts b/packages/timo-design-system/src/components/index.ts index 9253de1d..55c38bb2 100644 --- a/packages/timo-design-system/src/components/index.ts +++ b/packages/timo-design-system/src/components/index.ts @@ -32,7 +32,7 @@ export type { } from "./layout/modal/Modal"; export { SidebarButton } from "./button/sidebar-button/SidebarButton"; export { TodayButton } from "./button/today-button/TodayButton"; -export { WeeklyButton } from "./button/chevron-button/ChevronButton"; +export { ChevronButton } from "./button/chevron-button/ChevronButton"; export { TimeSelector } from "./time/time-selector/TimeSelector"; export { RepeatSelector } from "./repeat/repeat-selector/RepeatSelector"; export { Calendar } from "./calendar/Calendar"; From 4e0e1ec421a6664e54a3ce12ffe1babb245baa00 Mon Sep 17 00:00:00 2001 From: yumin-kim4757 Date: Wed, 8 Jul 2026 21:54:17 +0900 Subject: [PATCH 10/10] =?UTF-8?q?fix(web):=20Header=20ChevronButton=20?= =?UTF-8?q?=EC=B0=B8=EC=A1=B0=20=EB=B0=98=EC=98=81=20(#107)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/timo-web/components/layout/header/Header.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/timo-web/components/layout/header/Header.tsx b/apps/timo-web/components/layout/header/Header.tsx index 5ace3dcd..7729c246 100644 --- a/apps/timo-web/components/layout/header/Header.tsx +++ b/apps/timo-web/components/layout/header/Header.tsx @@ -4,7 +4,7 @@ import { DropdownView, SidebarButton, TodayButton, - WeeklyButton, + ChevronButton, } from "@repo/timo-design-system/ui"; import { cn } from "@repo/timo-design-system/utils"; @@ -39,13 +39,13 @@ export interface HeaderWeeklyNavProps { const HeaderWeeklyNav = ({ onPrev, onNext, label }: HeaderWeeklyNavProps) => { return (
- + {label && ( {label} )} - +
); };