From d104b7f36d89a5b6cc2e518c4de8a7c4e5e2f202 Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Wed, 8 Jul 2026 12:53:53 +0900 Subject: [PATCH 01/19] =?UTF-8?q?feat(design-system):=20ChevronSmall=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=86=8C=EC=8A=A4=20=EB=B0=8F=20?= =?UTF-8?q?google-logo=20=EC=97=90=EC=85=8B=20=EC=B6=94=EA=B0=80=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 온보딩 컴포넌트에서 사용할 ChevronSmall SVG 소스 파일 5종과 Google 로그인 버튼에 사용할 google-logo.svg 에셋을 추가했습니다. Co-Authored-By: Claude Sonnet 4.6 --- .../timo-design-system/src/assets/images/google-logo.svg | 9 +++++++++ .../src/icons/source/chevron-small-down.svg | 3 +++ .../src/icons/source/chevron-small-left.svg | 3 +++ .../src/icons/source/chevron-small-right-white.svg | 3 +++ .../src/icons/source/chevron-small-right.svg | 3 +++ .../src/icons/source/chevron-small-up.svg | 3 +++ 6 files changed, 24 insertions(+) create mode 100644 packages/timo-design-system/src/assets/images/google-logo.svg create mode 100644 packages/timo-design-system/src/icons/source/chevron-small-down.svg create mode 100644 packages/timo-design-system/src/icons/source/chevron-small-left.svg create mode 100644 packages/timo-design-system/src/icons/source/chevron-small-right-white.svg create mode 100644 packages/timo-design-system/src/icons/source/chevron-small-right.svg create mode 100644 packages/timo-design-system/src/icons/source/chevron-small-up.svg diff --git a/packages/timo-design-system/src/assets/images/google-logo.svg b/packages/timo-design-system/src/assets/images/google-logo.svg new file mode 100644 index 00000000..8869c6c0 --- /dev/null +++ b/packages/timo-design-system/src/assets/images/google-logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/packages/timo-design-system/src/icons/source/chevron-small-down.svg b/packages/timo-design-system/src/icons/source/chevron-small-down.svg new file mode 100644 index 00000000..2b76ab00 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/chevron-small-down.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/timo-design-system/src/icons/source/chevron-small-left.svg b/packages/timo-design-system/src/icons/source/chevron-small-left.svg new file mode 100644 index 00000000..7ef41ae7 --- /dev/null +++ b/packages/timo-design-system/src/icons/source/chevron-small-left.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/timo-design-system/src/icons/source/chevron-small-right-white.svg b/packages/timo-design-system/src/icons/source/chevron-small-right-white.svg new file mode 100644 index 00000000..b2ddad4b --- /dev/null +++ b/packages/timo-design-system/src/icons/source/chevron-small-right-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/timo-design-system/src/icons/source/chevron-small-right.svg b/packages/timo-design-system/src/icons/source/chevron-small-right.svg new file mode 100644 index 00000000..6354043b --- /dev/null +++ b/packages/timo-design-system/src/icons/source/chevron-small-right.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/timo-design-system/src/icons/source/chevron-small-up.svg b/packages/timo-design-system/src/icons/source/chevron-small-up.svg new file mode 100644 index 00000000..6f46161e --- /dev/null +++ b/packages/timo-design-system/src/icons/source/chevron-small-up.svg @@ -0,0 +1,3 @@ + + + From e43b142278d737bae12322970cae65a94fdc540b Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Wed, 8 Jul 2026 12:54:14 +0900 Subject: [PATCH 02/19] =?UTF-8?q?feat(web):=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OnboardingButton, OnboardingLoginButton, OnboardingTimeDropdown, OnboardingStepButton 컴포넌트를 구현했습니다. Co-Authored-By: Claude Sonnet 4.6 --- .../_components/OnboardingButton.tsx | 56 ++++++++++++++++ .../_components/OnboardingLoginButton.tsx | 35 ++++++++++ .../_components/OnboardingStepButton.tsx | 32 +++++++++ .../_components/OnboardingTimeDropdown.tsx | 65 +++++++++++++++++++ 4 files changed, 188 insertions(+) create mode 100644 apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx create mode 100644 apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx create mode 100644 apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx create mode 100644 apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx new file mode 100644 index 00000000..120e0c82 --- /dev/null +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx @@ -0,0 +1,56 @@ +import { + ChevronSmallLeftIcon, + ChevronSmallRightIcon, + ChevronSmallRightWhiteIcon, +} from "@repo/timo-design-system/icons"; +import { cn } from "@repo/timo-design-system/utils"; + +export type OnboardingButtonVariant = + | "다음" + | "다음_활성화" + | "이전" + | "시작하기" + | "시작하기_비활성"; + +export interface OnboardingButtonProps { + variant: OnboardingButtonVariant; + onClick?: () => void; +} + +const LABEL: Record = { + 다음: "다음", + 다음_활성화: "다음", + 이전: "이전", + 시작하기: "시작하기", + 시작하기_비활성: "시작하기", +}; + +export const OnboardingButton = ({ + variant, + onClick, +}: OnboardingButtonProps) => { + const active = variant === "다음_활성화" || variant === "시작하기"; + + return ( + + ); +}; diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx new file mode 100644 index 00000000..ddf9a9d4 --- /dev/null +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx @@ -0,0 +1,35 @@ +import googleLogo from "@repo/timo-design-system/assets/images/google-logo.svg"; +import { cn } from "@repo/timo-design-system/utils"; +import Image from "next/image"; + +export interface OnboardingLoginButtonProps { + selected?: boolean; + label?: string; + onClick?: () => void; +} + +export const OnboardingLoginButton = ({ + selected = false, + label = "Google 계정으로 계속하기", + onClick, +}: OnboardingLoginButtonProps) => { + return ( + + ); +}; diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx new file mode 100644 index 00000000..e9c9b993 --- /dev/null +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx @@ -0,0 +1,32 @@ +import { cn } from "@repo/timo-design-system/utils"; + +export interface OnboardingStepButtonProps { + step: 1 | 2 | 3 | 4; +} + +const STEPS = [1, 2, 3, 4] as const; + +export const OnboardingStepButton = ({ step }: OnboardingStepButtonProps) => { + return ( +
+ {STEPS.map((s) => ( +
+ + {s} + +
+ ))} +
+ ); +}; diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx new file mode 100644 index 00000000..14483829 --- /dev/null +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx @@ -0,0 +1,65 @@ +import { + ChevronSmallDownIcon, + ChevronSmallUpIcon, +} from "@repo/timo-design-system/icons"; +import { Dropdown } from "@repo/timo-design-system/ui"; +import { cn } from "@repo/timo-design-system/utils"; + +const PANEL_SCROLLBAR = + "[scrollbar-width:thin] [scrollbar-color:var(--color-timo-gray-600)_transparent] [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar-track]:bg-transparent [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:bg-timo-gray-600 [&::-webkit-scrollbar-thumb:hover]:bg-timo-gray-700"; + +const TIME_OPTIONS = Array.from( + { length: 25 }, + (_, i) => `${String(i).padStart(2, "0")}:00`, +); + +export interface OnboardingTimeDropdownProps { + value?: string; + placeholder?: string; + onChange?: (time: string) => void; +} + +export const OnboardingTimeDropdown = ({ + value, + placeholder = "01:00", + onChange, +}: OnboardingTimeDropdownProps) => { + const hasValue = value !== undefined; + + return ( + + + + {value ?? placeholder} + + + + + + + {TIME_OPTIONS.map((time) => ( + onChange?.(time)} + className={cn( + "typo-headline-b-16 w-full rounded-none text-left", + value === time ? "text-timo-blue-300" : "text-timo-gray-700", + )} + > + {time} + + ))} + + + ); +}; From 300728d27a0c7947da53d61e26592a064d00c967 Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Thu, 9 Jul 2026 03:12:52 +0900 Subject: [PATCH 03/19] =?UTF-8?q?feat(web):=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20next-intl=20=EB=8B=A4?= =?UTF-8?q?=EA=B5=AD=EC=96=B4=20=EB=A7=A4=ED=95=91=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OnboardingButton variant를 영문 키로 변경 후 useTranslations 연결 - OnboardingLoginButton → OnboardingGoogleButton으로 rename, variant 기반 번역 적용 - OnboardingTimeDropdown "use client" 추가 - ko.json / en.json에 Onboarding 네임스페이스 추가 - 온보딩 page.tsx에 컴포넌트 테스트 렌더링 추가 Co-Authored-By: Claude Sonnet 4.6 --- .../_components/OnboardingButton.tsx | 41 ++++++++++------- ...nButton.tsx => OnboardingGoogleButton.tsx} | 21 ++++++--- .../_components/OnboardingTimeDropdown.tsx | 2 + .../timo-web/app/[locale]/onboarding/page.tsx | 45 ++++++++++++++++++- apps/timo-web/messages/en.json | 11 +++++ apps/timo-web/messages/ko.json | 11 +++++ 6 files changed, 108 insertions(+), 23 deletions(-) rename apps/timo-web/app/[locale]/onboarding/_components/{OnboardingLoginButton.tsx => OnboardingGoogleButton.tsx} (66%) diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx index 120e0c82..2ce81dbd 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx @@ -1,35 +1,44 @@ +"use client"; + import { ChevronSmallLeftIcon, ChevronSmallRightIcon, ChevronSmallRightWhiteIcon, } from "@repo/timo-design-system/icons"; import { cn } from "@repo/timo-design-system/utils"; +import { useTranslations } from "next-intl"; export type OnboardingButtonVariant = - | "다음" - | "다음_활성화" - | "이전" - | "시작하기" - | "시작하기_비활성"; + | "next" + | "next_active" + | "prev" + | "start" + | "start_inactive"; export interface OnboardingButtonProps { variant: OnboardingButtonVariant; onClick?: () => void; } -const LABEL: Record = { - 다음: "다음", - 다음_활성화: "다음", - 이전: "이전", - 시작하기: "시작하기", - 시작하기_비활성: "시작하기", +type ButtonTranslationKey = "button.next" | "button.prev" | "button.start"; + +const BUTTON_TRANSLATION_KEY: Record< + OnboardingButtonVariant, + ButtonTranslationKey +> = { + next: "button.next", + next_active: "button.next", + prev: "button.prev", + start: "button.start", + start_inactive: "button.start", }; export const OnboardingButton = ({ variant, onClick, }: OnboardingButtonProps) => { - const active = variant === "다음_활성화" || variant === "시작하기"; + const t = useTranslations("Onboarding"); + const active = variant === "next_active" || variant === "start"; return ( ); }; diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx similarity index 66% rename from apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx rename to apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx index ddf9a9d4..6e6a3fbd 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingLoginButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx @@ -1,18 +1,25 @@ +"use client"; + import googleLogo from "@repo/timo-design-system/assets/images/google-logo.svg"; import { cn } from "@repo/timo-design-system/utils"; import Image from "next/image"; +import { useTranslations } from "next-intl"; + +export type OnboardingGoogleButtonVariant = "login" | "connectCalendar"; -export interface OnboardingLoginButtonProps { +export interface OnboardingGoogleButtonProps { + variant: OnboardingGoogleButtonVariant; selected?: boolean; - label?: string; onClick?: () => void; } -export const OnboardingLoginButton = ({ +export const OnboardingGoogleButton = ({ + variant, selected = false, - label = "Google 계정으로 계속하기", onClick, -}: OnboardingLoginButtonProps) => { +}: OnboardingGoogleButtonProps) => { + const t = useTranslations("Onboarding"); + return ( ); diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx index 14483829..bc23dbfe 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx @@ -1,3 +1,5 @@ +"use client"; + import { ChevronSmallDownIcon, ChevronSmallUpIcon, diff --git a/apps/timo-web/app/[locale]/onboarding/page.tsx b/apps/timo-web/app/[locale]/onboarding/page.tsx index e82bb921..cbc3a4a3 100644 --- a/apps/timo-web/app/[locale]/onboarding/page.tsx +++ b/apps/timo-web/app/[locale]/onboarding/page.tsx @@ -1,3 +1,46 @@ +import { OnboardingButton } from "./_components/OnboardingButton"; +import { OnboardingGoogleButton } from "./_components/OnboardingGoogleButton"; +import { OnboardingStepButton } from "./_components/OnboardingStepButton"; +import { OnboardingTimeDropdown } from "./_components/OnboardingTimeDropdown"; + export default function OnboardingPage() { - return <>; + return ( +
+
+

OnboardingButton

+
+ + + + + +
+
+ +
+

OnboardingGoogleButton

+
+ + + + +
+
+ +
+

OnboardingStepButton

+
+ + + + +
+
+ +
+

OnboardingTimeDropdown

+ +
+
+ ); } diff --git a/apps/timo-web/messages/en.json b/apps/timo-web/messages/en.json index aafb3a8a..4a81a299 100644 --- a/apps/timo-web/messages/en.json +++ b/apps/timo-web/messages/en.json @@ -5,5 +5,16 @@ "focus": "Focus Mode", "statistics": "Statistics", "settings": "Settings" + }, + "Onboarding": { + "button": { + "next": "Next", + "prev": "Previous", + "start": "Get Started" + }, + "onboardingGoogleButton": { + "login": "Continue with your Google account", + "connectCalendar": "Connect Google Calendar" + } } } diff --git a/apps/timo-web/messages/ko.json b/apps/timo-web/messages/ko.json index cae27e6f..f08d768f 100644 --- a/apps/timo-web/messages/ko.json +++ b/apps/timo-web/messages/ko.json @@ -5,5 +5,16 @@ "focus": "집중 모드", "statistics": "통계", "settings": "설정" + }, + "Onboarding": { + "button": { + "next": "다음", + "prev": "이전", + "start": "시작하기" + }, + "onboardingGoogleButton": { + "login": "Google 계정으로 계속하기", + "connectCalendar": "Google 캘린더 연결하기" + } } } From 032108f10efd75697b869556ddc9eddebd3a51a6 Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Thu, 9 Jul 2026 03:32:27 +0900 Subject: [PATCH 04/19] =?UTF-8?q?fix(web):=20=EC=BD=94=EB=93=9C=EB=9E=98?= =?UTF-8?q?=EB=B9=97=20=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81=20-=20Onboa?= =?UTF-8?q?rdingButton=20disabled=20=EC=B2=98=EB=A6=AC=20=EB=B0=8F=20isSel?= =?UTF-8?q?ected=20=EC=BB=A8=EB=B2=A4=EC=85=98=20=EC=A0=81=EC=9A=A9=20(#11?= =?UTF-8?q?8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OnboardingButton: next/start_inactive variant에 disabled 속성 추가 - OnboardingGoogleButton: selected → isSelected boolean prop 컨벤션 적용 Co-Authored-By: Claude Sonnet 4.6 --- .../[locale]/onboarding/_components/OnboardingButton.tsx | 2 ++ .../onboarding/_components/OnboardingGoogleButton.tsx | 6 +++--- apps/timo-web/app/[locale]/onboarding/page.tsx | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx index 2ce81dbd..bd48b6a3 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx @@ -39,11 +39,13 @@ export const OnboardingButton = ({ }: OnboardingButtonProps) => { const t = useTranslations("Onboarding"); const active = variant === "next_active" || variant === "start"; + const disabled = variant === "next" || variant === "start_inactive"; return ( + ); + } + + if (variant === "start") { + return ( + + ); + } + + const { isActive, disabled = false } = props; + const isDisabled = disabled || !isActive; return ( ); }; From 6ee9ec6460670ce8ff378e2d61287c1f3ba9874e Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Fri, 10 Jul 2026 02:06:34 +0900 Subject: [PATCH 13/19] =?UTF-8?q?fix(config):=20=EC=A0=84=EC=97=AD=20webki?= =?UTF-8?q?t=20=EC=8A=A4=ED=81=AC=EB=A1=A4=EB=B0=94=20=EB=84=88=EB=B9=84?= =?UTF-8?q?=20=EC=8B=A4=EC=B8=A1=EA=B0=92=EC=9C=BC=EB=A1=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/tailwind-config/scrollbar.css | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/tailwind-config/scrollbar.css b/packages/tailwind-config/scrollbar.css index 94bd10b5..96dc6d82 100644 --- a/packages/tailwind-config/scrollbar.css +++ b/packages/tailwind-config/scrollbar.css @@ -4,8 +4,8 @@ } *::-webkit-scrollbar { - width: 6px; - height: 6px; + width: 8px; + height: 8px; } *::-webkit-scrollbar-track { @@ -20,3 +20,8 @@ *::-webkit-scrollbar-thumb:hover { background-color: var(--color-timo-gray-700); } + +.scrollbar-sm::-webkit-scrollbar { + width: 4px; + height: 4px; +} From 43c8b5daf86eac9bd18926260c5da4f49ecf084b Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Fri, 10 Jul 2026 02:12:36 +0900 Subject: [PATCH 14/19] =?UTF-8?q?chore(web):=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=EB=A0=8C=EB=8D=94=EB=A7=81=20?= =?UTF-8?q?=EB=B0=8F=20=EC=8A=A4=ED=81=AC=EB=A1=A4=EB=B0=94=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=A0=95=EB=A6=AC=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../_components/OnboardingTimeDropdown.module.css | 4 ---- .../onboarding/_components/OnboardingTimeDropdown.tsx | 9 +-------- packages/tailwind-config/scrollbar.css | 5 ----- 3 files changed, 1 insertion(+), 17 deletions(-) delete mode 100644 apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.module.css diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.module.css b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.module.css deleted file mode 100644 index eee816f2..00000000 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.module.css +++ /dev/null @@ -1,4 +0,0 @@ -.scrollbar::-webkit-scrollbar { - width: 4px; - height: 4px; -} diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx index 1a9a45f5..57d05c2b 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx @@ -7,8 +7,6 @@ import { import { Dropdown } from "@repo/timo-design-system/ui"; import { cn } from "@repo/timo-design-system/utils"; -import styles from "./OnboardingTimeDropdown.module.css"; - const TIME_OPTIONS = Array.from( { length: 25 }, (_, i) => `${String(i).padStart(2, "0")}:00`, @@ -50,12 +48,7 @@ export const OnboardingTimeDropdown = ({ -
+
{TIME_OPTIONS.map((time) => ( Date: Fri, 10 Jul 2026 02:24:45 +0900 Subject: [PATCH 15/19] =?UTF-8?q?refactor(web):=20OnboardingTimeField=20?= =?UTF-8?q?=5Fcomponents=EC=97=90=EC=84=9C=20=5Fcontainers=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{_components => _containers}/OnboardingTimeField.tsx | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/timo-web/app/[locale]/onboarding/{_components => _containers}/OnboardingTimeField.tsx (100%) diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeField.tsx b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx similarity index 100% rename from apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeField.tsx rename to apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx From 4b960e0cfcd61dcda3aa418ea46e0dafc92b76ce Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Fri, 10 Jul 2026 02:26:32 +0900 Subject: [PATCH 16/19] =?UTF-8?q?chore(web):=20=EC=98=A8=EB=B3=B4=EB=94=A9?= =?UTF-8?q?=20=5Fcontainers=20.gitkeep=20=EC=A0=9C=EA=B1=B0=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/timo-web/app/[locale]/onboarding/_containers/.gitkeep | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/timo-web/app/[locale]/onboarding/_containers/.gitkeep diff --git a/apps/timo-web/app/[locale]/onboarding/_containers/.gitkeep b/apps/timo-web/app/[locale]/onboarding/_containers/.gitkeep deleted file mode 100644 index e69de29b..00000000 From 6650449e7956c96ccb3b0dc8be81f23c0a8d7e9c Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Fri, 10 Jul 2026 02:30:57 +0900 Subject: [PATCH 17/19] =?UTF-8?q?fix(web):=20OnboardingTimeField=EC=9D=98?= =?UTF-8?q?=20=EC=9E=98=EB=AA=BB=EB=90=9C=20import=20=EA=B2=BD=EB=A1=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OnboardingTimeDropdown import 경로를 ./ 에서 ../_components/로 수정했습니다 --- .../app/[locale]/onboarding/_containers/OnboardingTimeField.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx index dc51ab5e..62c8ace4 100644 --- a/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx @@ -2,7 +2,7 @@ import { useState } from "react"; -import { OnboardingTimeDropdown } from "./OnboardingTimeDropdown"; +import { OnboardingTimeDropdown } from "../_components/OnboardingTimeDropdown"; export const OnboardingTimeField = () => { const [time, setTime] = useState(""); From e6155ae5c81c95d94c365a5099cf9b9935eaefac Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Fri, 10 Jul 2026 07:46:59 +0900 Subject: [PATCH 18/19] =?UTF-8?q?refactor(web):=20=EC=98=A8=EB=B3=B4?= =?UTF-8?q?=EB=94=A9=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=C2=B7=EC=BB=A8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=84=88=20=EA=B3=84=EC=B8=B5=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 컴포넌트에서 "use client"와 번역 로직을 제거하고 컨테이너로 이동했습니다 - OnboardingButton, OnboardingGoogleButton에 label prop을 추가해 번역 책임을 컨테이너로 위임했습니다 - OnboardingButtonContainer, OnboardingGoogleButtonContainer, OnboardingTimeContainer를 신규 추가했습니다 - OnboardingTimeField를 OnboardingTimeContainer로 대체했습니다 - getAmPm 함수를 utils/get-am-pm.ts로 분리했습니다 - 외부에서 사용하지 않는 interface export를 제거했습니다 --- .../[locale]/onboarding/_components/.gitkeep | 0 .../_components/OnboardingButton.tsx | 52 ++++++------------- .../_components/OnboardingGoogleButton.tsx | 14 ++--- .../_components/OnboardingStepButton.tsx | 2 +- .../_components/OnboardingTimeDropdown.tsx | 11 ++-- .../_containers/OnboardingButtonContainer.tsx | 31 +++++++++++ .../OnboardingGoogleButtonContainer.tsx | 28 ++++++++++ ...eField.tsx => OnboardingTimeContainer.tsx} | 4 +- apps/timo-web/utils/get-am-pm.ts | 13 +++++ 9 files changed, 99 insertions(+), 56 deletions(-) delete mode 100644 apps/timo-web/app/[locale]/onboarding/_components/.gitkeep create mode 100644 apps/timo-web/app/[locale]/onboarding/_containers/OnboardingButtonContainer.tsx create mode 100644 apps/timo-web/app/[locale]/onboarding/_containers/OnboardingGoogleButtonContainer.tsx rename apps/timo-web/app/[locale]/onboarding/_containers/{OnboardingTimeField.tsx => OnboardingTimeContainer.tsx} (59%) create mode 100644 apps/timo-web/utils/get-am-pm.ts diff --git a/apps/timo-web/app/[locale]/onboarding/_components/.gitkeep b/apps/timo-web/app/[locale]/onboarding/_components/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx index ba7fedb0..7f4251ab 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingButton.tsx @@ -1,38 +1,25 @@ -"use client"; - import { ChevronLeftIcon, ChevronSmallRightIcon, ChevronSmallRightWhiteIcon, } from "@repo/timo-design-system/icons"; import { cn } from "@repo/timo-design-system/utils"; -import { useTranslations } from "next-intl"; - -type ButtonTranslationKey = "button.next" | "button.prev" | "button.start"; - -const BUTTON_TRANSLATION_KEY: Record< - "next" | "prev" | "start", - ButtonTranslationKey -> = { - next: "button.next", - prev: "button.prev", - start: "button.start", -}; - -export type OnboardingButtonProps = - | { - variant: "next"; - isActive: boolean; - disabled?: boolean; - onClick?: () => void; - } - | { variant: "prev"; onClick?: () => void } - | { variant: "start"; onClick?: () => void }; -export const OnboardingButton = (props: OnboardingButtonProps) => { - const { variant, onClick } = props; - const t = useTranslations("Onboarding"); +export interface OnboardingButtonProps { + variant: "next" | "prev" | "start"; + label: string; + isActive?: boolean; + disabled?: boolean; + onClick?: () => void; +} +export const OnboardingButton = ({ + variant, + label, + isActive = false, + disabled = false, + onClick, +}: OnboardingButtonProps) => { if (variant === "prev") { return ( ); } @@ -55,14 +40,11 @@ export const OnboardingButton = (props: OnboardingButtonProps) => { onClick={onClick} className="bg-timo-blue-300 flex items-center justify-center gap-2 rounded-[4px] px-4 py-2" > - - {t(BUTTON_TRANSLATION_KEY.start)} - + {label} ); } - const { isActive, disabled = false } = props; const isDisabled = disabled || !isActive; return ( @@ -81,7 +63,7 @@ export const OnboardingButton = (props: OnboardingButtonProps) => { isActive ? "text-white" : "text-timo-gray-700", )} > - {t(BUTTON_TRANSLATION_KEY.next)} + {label} {isActive ? : } diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx index 9e93eff2..da014259 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx @@ -1,25 +1,21 @@ -"use client"; - import googleLogo from "@repo/timo-design-system/assets/images/google-logo.svg"; import { cn } from "@repo/timo-design-system/utils"; import Image from "next/image"; -import { useTranslations } from "next-intl"; -export type OnboardingGoogleButtonVariant = "login" | "connectCalendar"; +type OnboardingGoogleButtonVariant = "login" | "connectCalendar"; export interface OnboardingGoogleButtonProps { variant: OnboardingGoogleButtonVariant; + label: string; isSelected?: boolean; onClick?: () => void; } export const OnboardingGoogleButton = ({ - variant, + label, isSelected = false, onClick, }: OnboardingGoogleButtonProps) => { - const t = useTranslations("Onboarding"); - return (
- - {t(`onboardingGoogleButton.${variant}`)} - + {label}
); diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx index 4fe958f0..d2be88f1 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingStepButton.tsx @@ -1,6 +1,6 @@ import { cn } from "@repo/timo-design-system/utils"; -export interface OnboardingStepButtonProps { +interface OnboardingStepButtonProps { step: 1 | 2 | 3 | 4; } diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx index 57d05c2b..196a2507 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingTimeDropdown.tsx @@ -1,5 +1,3 @@ -"use client"; - import { ChevronDownGrayIcon, ChevronUpGrayIcon, @@ -7,17 +5,14 @@ import { import { Dropdown } from "@repo/timo-design-system/ui"; import { cn } from "@repo/timo-design-system/utils"; +import { getAmPm } from "@/utils/get-am-pm"; + const TIME_OPTIONS = Array.from( { length: 25 }, (_, i) => `${String(i).padStart(2, "0")}:00`, ); -const getAmPm = (time: string): "AM" | "PM" => { - const hour = parseInt(time.split(":")[0] ?? "0", 10); - return hour >= 12 && hour < 24 ? "PM" : "AM"; -}; - -export interface OnboardingTimeDropdownProps { +interface OnboardingTimeDropdownProps { value: string; placeholder?: string; onChange: (time: string) => void; diff --git a/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingButtonContainer.tsx b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingButtonContainer.tsx new file mode 100644 index 00000000..368e18c1 --- /dev/null +++ b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingButtonContainer.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { useTranslations } from "next-intl"; + +import { OnboardingButton } from "@/app/[locale]/onboarding/_components/OnboardingButton"; + +interface OnboardingButtonContainerProps { + variant: "next" | "prev" | "start"; + isActive?: boolean; + disabled?: boolean; + onClick?: () => void; +} + +export const OnboardingButtonContainer = ({ + variant, + isActive, + disabled, + onClick, +}: OnboardingButtonContainerProps) => { + const t = useTranslations("Onboarding"); + + return ( + + ); +}; diff --git a/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingGoogleButtonContainer.tsx b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingGoogleButtonContainer.tsx new file mode 100644 index 00000000..821d5cb6 --- /dev/null +++ b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingGoogleButtonContainer.tsx @@ -0,0 +1,28 @@ +"use client"; + +import { useTranslations } from "next-intl"; + +import { OnboardingGoogleButton } from "@/app/[locale]/onboarding/_components/OnboardingGoogleButton"; + +interface OnboardingGoogleButtonContainerProps { + variant: "login" | "connectCalendar"; + isSelected?: boolean; + onClick?: () => void; +} + +export const OnboardingGoogleButtonContainer = ({ + variant, + isSelected, + onClick, +}: OnboardingGoogleButtonContainerProps) => { + const t = useTranslations("Onboarding"); + + return ( + + ); +}; diff --git a/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeContainer.tsx similarity index 59% rename from apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx rename to apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeContainer.tsx index 62c8ace4..3bf7f761 100644 --- a/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeField.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_containers/OnboardingTimeContainer.tsx @@ -2,9 +2,9 @@ import { useState } from "react"; -import { OnboardingTimeDropdown } from "../_components/OnboardingTimeDropdown"; +import { OnboardingTimeDropdown } from "@/app/[locale]/onboarding/_components/OnboardingTimeDropdown"; -export const OnboardingTimeField = () => { +export const OnboardingTimeContainer = () => { const [time, setTime] = useState(""); return ( diff --git a/apps/timo-web/utils/get-am-pm.ts b/apps/timo-web/utils/get-am-pm.ts new file mode 100644 index 00000000..ccae4dbc --- /dev/null +++ b/apps/timo-web/utils/get-am-pm.ts @@ -0,0 +1,13 @@ +const HOURS_IN_DAY = 24; + +/** + * "HH:MM" 형식의 시간 문자열에서 오전/오후를 판별합니다. + * 24시("24:00")는 다음날 자정(오전)으로 취급합니다. + * + * @param time - "HH:MM" 형식의 시간 문자열 + * @returns "AM" 또는 "PM" + */ +export const getAmPm = (time: string): "AM" | "PM" => { + const hour = parseInt(time.split(":")[0] ?? "0", 10); + return hour >= 12 && hour < HOURS_IN_DAY ? "PM" : "AM"; +}; From 3c70014afb1cb058d889369d12a71f52b7a7123e Mon Sep 17 00:00:00 2001 From: Lee Hye Won Date: Fri, 10 Jul 2026 16:08:58 +0900 Subject: [PATCH 19/19] =?UTF-8?q?refactor(web):=20OnboardingGoogleButtonPr?= =?UTF-8?q?ops=20=EC=9D=B8=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=20export=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(#118)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OnboardingGoogleButtonProps 인터페이스의 불필요한 export 키워드를 제거했습니다 --- .../[locale]/onboarding/_components/OnboardingGoogleButton.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx index da014259..c898324b 100644 --- a/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx +++ b/apps/timo-web/app/[locale]/onboarding/_components/OnboardingGoogleButton.tsx @@ -4,7 +4,7 @@ import Image from "next/image"; type OnboardingGoogleButtonVariant = "login" | "connectCalendar"; -export interface OnboardingGoogleButtonProps { +interface OnboardingGoogleButtonProps { variant: OnboardingGoogleButtonVariant; label: string; isSelected?: boolean;