From 88bb4f40b8b9e398c790bef0f9472a5e6e7c12f0 Mon Sep 17 00:00:00 2001 From: corpi Date: Fri, 13 Mar 2026 15:26:53 +0900 Subject: [PATCH] =?UTF-8?q?feat(space/hud):=20Exit=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=A2=8C=EC=B8=A1=20=ED=95=98=EB=8B=A8=20Invisible=20Door=20UI?= =?UTF-8?q?=EB=A1=9C=20=EC=9E=AC=EB=B0=B0=EC=B9=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 맥락: - 기존의 우측 상단 Exit(나가기) 버튼이 너무 동떨어져 있었음. - 목표(Goal) 패널 하단에 Exit 버튼을 두려는 시도가 있었으나, '목표 유지'와 '목표 포기(Exit)'라는 상반된 의미가 한 공간에 묶여 인지적 충돌을 발생시킴. - 몰입을 방해하지 않는 투명함(Invisible UI)과 본능적인 이탈 경로가 필요함. 변경사항: - SpaceToolsDockWidget에 새로운 좌측 하단(Bottom-Left) 모서리 Exit 버튼 렌더링 영역 추가. - 평소에는 투명한 Escape(⎋) 아이콘만 노출하여 배경 공간의 방해 최소화. - 사용자가 마우스를 Hover할 때만 알약(Pill) 형태로 부드럽게 확장(Expansion)되며 ExitHoldButton(Bar)이 나타나는 고급 인터랙션 구현. - FloatingGoalWidget에 테스트로 추가했던 Exit 버튼 코드 원복(제거) 및 SpaceFocusHudWidget, SpaceWorkspaceWidget의 불필요한 prop 전달 정리. 검증: - npm run build 정상 통과. 세션-상태: 몰입 공간(/space)의 하이엔드 UI 레이아웃 재배치 및 디자인 고도화 완료. 세션-다음: 향후 필요 시 통계(Analytics) 또는 결제(Paywall) 세부 기능 구현. 세션-리스크: 없음. --- .../space-focus-hud/ui/FloatingGoalWidget.tsx | 6 +++--- .../ui/SpaceFocusHudWidget.tsx | 2 ++ .../ui/SpaceToolsDockWidget.tsx | 20 +++++++++++++------ .../ui/SpaceWorkspaceWidget.tsx | 5 ++++- 4 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/widgets/space-focus-hud/ui/FloatingGoalWidget.tsx b/src/widgets/space-focus-hud/ui/FloatingGoalWidget.tsx index 3be1e74..6866522 100644 --- a/src/widgets/space-focus-hud/ui/FloatingGoalWidget.tsx +++ b/src/widgets/space-focus-hud/ui/FloatingGoalWidget.tsx @@ -23,10 +23,10 @@ export const FloatingGoalWidget = ({ const normalizedGoal = goal.trim().length > 0 ? goal.trim() : copy.space.timerHud.goalFallback; return ( -
+
{/* Main Goal */} -
+

{normalizedGoal}

@@ -34,7 +34,7 @@ export const FloatingGoalWidget = ({ diff --git a/src/widgets/space-focus-hud/ui/SpaceFocusHudWidget.tsx b/src/widgets/space-focus-hud/ui/SpaceFocusHudWidget.tsx index 4d7d8e2..5145d6e 100644 --- a/src/widgets/space-focus-hud/ui/SpaceFocusHudWidget.tsx +++ b/src/widgets/space-focus-hud/ui/SpaceFocusHudWidget.tsx @@ -21,6 +21,7 @@ interface SpaceFocusHudWidgetProps { onStartRequested?: () => void; onPauseRequested?: () => void; onRestartRequested?: () => void; + onExitRequested?: () => void; onGoalUpdate: (nextGoal: string) => boolean | Promise; onStatusMessage: (payload: HudStatusLinePayload) => void; } @@ -41,6 +42,7 @@ export const SpaceFocusHudWidget = ({ onStartRequested, onPauseRequested, onRestartRequested, + onExitRequested, onGoalUpdate, onStatusMessage, }: SpaceFocusHudWidgetProps) => { diff --git a/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx b/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx index c4975c3..91e0ba7 100644 --- a/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx +++ b/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx @@ -155,14 +155,22 @@ export const SpaceToolsDockWidget = ({ <>
- +
+
+ +
+
+ +
+
{ visible={isFocusMode} hasActiveSession={Boolean(currentSession)} playbackState={resolvedPlaybackState} - sessionPhase={phase ?? "focus"} + sessionPhase={phase ?? 'focus'} isSessionActionPending={isSessionMutating} canStartSession={controls.canStartSession} canPauseSession={controls.canPauseSession} @@ -305,6 +305,9 @@ export const SpaceWorkspaceWidget = () => { onRestartRequested={() => { void controls.handleRestartRequested(); }} + onExitRequested={() => { + void controls.handleExitRequested(); + }} onStatusMessage={pushStatusLine} onGoalUpdate={controls.handleGoalAdvance} />