style(control-center): 모드 선택 pill로 교체하고 패널 바디로 재배치
맥락: - Quick Controls 헤더의 모드 토글이 대시보드형 느낌을 만들어 감성 톤을 해치고 있었습니다. 변경사항: - Control Center 헤더에서는 모드 조작 UI를 제거하고 Plan Pill + 닫기만 유지했습니다. - 패널 바디 첫 섹션에 기본/몰입 segmented pill을 배치하고, 선택 상태에 따라 저자극 스타일을 적용했습니다. - 모드 설명 1줄(기본: 모든 컨트롤 표시, 몰입: 필수만 남기고 숨김)을 추가했습니다. - 모드 상태를 workspace -> tools-dock -> focus-hud 경로로 연결해 HUD 톤 반영을 유지했습니다. 검증: - npx tsc --noEmit 세션-상태: Quick Controls 헤더가 깔끔해지고 모드 선택이 패널 바디에서 동작합니다. 세션-다음: Scene 추천 매핑 품질 점검과 override UX 검증을 진행합니다. 세션-리스크: 모드 설명 문구의 톤/길이는 실제 사용성 테스트에서 추가 미세조정이 필요할 수 있습니다.
This commit is contained in:
@@ -16,9 +16,11 @@ interface ControlCenterSheetWidgetProps {
|
||||
rooms: RoomTheme[];
|
||||
selectedRoomId: string;
|
||||
selectedTimerLabel: string;
|
||||
isImmersionMode: boolean;
|
||||
sceneRecommendedSoundLabel: string;
|
||||
sceneRecommendedTimerLabel: string;
|
||||
timerPresets: TimerPreset[];
|
||||
onImmersionModeChange: (next: boolean) => void;
|
||||
onSelectRoom: (roomId: string) => void;
|
||||
onSelectTimer: (timerLabel: string) => void;
|
||||
onLockedClick: (source: string) => void;
|
||||
@@ -47,9 +49,11 @@ export const ControlCenterSheetWidget = ({
|
||||
rooms,
|
||||
selectedRoomId,
|
||||
selectedTimerLabel,
|
||||
isImmersionMode,
|
||||
sceneRecommendedSoundLabel,
|
||||
sceneRecommendedTimerLabel,
|
||||
timerPresets,
|
||||
onImmersionModeChange,
|
||||
onSelectRoom,
|
||||
onSelectTimer,
|
||||
onLockedClick,
|
||||
@@ -70,6 +74,41 @@ export const ControlCenterSheetWidget = ({
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<section className="space-y-2 rounded-2xl border border-white/12 bg-black/22 p-3 backdrop-blur-md">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<p className="text-[11px] text-white/64">모드</p>
|
||||
<div className="inline-flex items-center rounded-full border border-white/14 bg-white/[0.03] p-0.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onImmersionModeChange(false)}
|
||||
className={cn(
|
||||
'h-7 rounded-full border px-3 text-[11px] transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-200/70',
|
||||
!isImmersionMode
|
||||
? 'border-white/15 bg-white/10 text-white/90'
|
||||
: 'border-white/10 bg-transparent text-white/60 hover:text-white/78',
|
||||
)}
|
||||
>
|
||||
기본
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => onImmersionModeChange(true)}
|
||||
className={cn(
|
||||
'h-7 rounded-full border px-3 text-[11px] transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-200/70',
|
||||
isImmersionMode
|
||||
? 'border-white/15 bg-white/10 text-white/90'
|
||||
: 'border-white/10 bg-transparent text-white/60 hover:text-white/78',
|
||||
)}
|
||||
>
|
||||
몰입
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-[11px] text-white/54">
|
||||
{isImmersionMode ? '필수만 남기고 숨김' : '모든 컨트롤 표시'}
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className="space-y-2.5 rounded-2xl border border-white/12 bg-black/22 p-3.5 backdrop-blur-md">
|
||||
<SectionTitle title="Scene" description={selectedRoom?.name ?? '공간'} />
|
||||
<div
|
||||
|
||||
@@ -9,6 +9,7 @@ interface SpaceFocusHudWidgetProps {
|
||||
goal: string;
|
||||
timerLabel: string;
|
||||
visible: boolean;
|
||||
isImmersionMode: boolean;
|
||||
onGoalUpdate: (nextGoal: string) => void;
|
||||
statusLine: HudStatusLineItem | null;
|
||||
onStatusAction: () => void;
|
||||
@@ -19,6 +20,7 @@ export const SpaceFocusHudWidget = ({
|
||||
goal,
|
||||
timerLabel,
|
||||
visible,
|
||||
isImmersionMode,
|
||||
onGoalUpdate,
|
||||
statusLine,
|
||||
onStatusAction,
|
||||
@@ -108,7 +110,7 @@ export const SpaceFocusHudWidget = ({
|
||||
}
|
||||
: null
|
||||
}
|
||||
isImmersionMode
|
||||
isImmersionMode={isImmersionMode}
|
||||
className="pr-[4.2rem]"
|
||||
onGoalCompleteRequest={handleOpenCompleteSheet}
|
||||
onStatusAction={onStatusAction}
|
||||
|
||||
@@ -20,6 +20,7 @@ import { QuickSoundPopover } from './popovers/QuickSoundPopover';
|
||||
import { InboxToolPanel } from './panels/InboxToolPanel';
|
||||
interface SpaceToolsDockWidgetProps {
|
||||
isFocusMode: boolean;
|
||||
isImmersionMode: boolean;
|
||||
rooms: RoomTheme[];
|
||||
selectedRoomId: string;
|
||||
selectedTimerLabel: string;
|
||||
@@ -42,12 +43,14 @@ interface SpaceToolsDockWidgetProps {
|
||||
onRestoreThought: (thought: RecentThought) => void;
|
||||
onClearInbox: () => RecentThought[];
|
||||
onResetToSceneRecommended: () => void;
|
||||
onImmersionModeChange: (next: boolean) => void;
|
||||
onStatusMessage: (payload: HudStatusLinePayload) => void;
|
||||
onExitRequested: () => void;
|
||||
}
|
||||
|
||||
export const SpaceToolsDockWidget = ({
|
||||
isFocusMode,
|
||||
isImmersionMode,
|
||||
rooms,
|
||||
selectedRoomId,
|
||||
selectedTimerLabel,
|
||||
@@ -70,6 +73,7 @@ export const SpaceToolsDockWidget = ({
|
||||
onRestoreThought,
|
||||
onClearInbox,
|
||||
onResetToSceneRecommended,
|
||||
onImmersionModeChange,
|
||||
onStatusMessage,
|
||||
onExitRequested,
|
||||
}: SpaceToolsDockWidgetProps) => {
|
||||
@@ -411,9 +415,11 @@ export const SpaceToolsDockWidget = ({
|
||||
rooms={rooms}
|
||||
selectedRoomId={selectedRoomId}
|
||||
selectedTimerLabel={selectedTimerLabel}
|
||||
isImmersionMode={isImmersionMode}
|
||||
sceneRecommendedSoundLabel={sceneRecommendedSoundLabel}
|
||||
sceneRecommendedTimerLabel={sceneRecommendedTimerLabel}
|
||||
timerPresets={timerPresets}
|
||||
onImmersionModeChange={onImmersionModeChange}
|
||||
onSelectRoom={(roomId) => {
|
||||
onRoomSelect(roomId);
|
||||
}}
|
||||
|
||||
@@ -167,6 +167,7 @@ export const SpaceWorkspaceWidget = () => {
|
||||
);
|
||||
|
||||
const [workspaceMode, setWorkspaceMode] = useState<WorkspaceMode>('setup');
|
||||
const [isImmersionMode, setImmersionMode] = useState(false);
|
||||
const [selectedRoomId, setSelectedRoomId] = useState(initialRoomId);
|
||||
const [selectedTimerLabel, setSelectedTimerLabel] = useState(initialTimerLabel);
|
||||
const [goalInput, setGoalInput] = useState(initialGoal);
|
||||
@@ -377,6 +378,7 @@ export const SpaceWorkspaceWidget = () => {
|
||||
goal={goalInput.trim()}
|
||||
timerLabel={selectedTimerLabel}
|
||||
visible={isFocusMode}
|
||||
isImmersionMode={isImmersionMode}
|
||||
statusLine={activeStatus}
|
||||
onStatusAction={runActiveAction}
|
||||
onStatusMessage={pushStatusLine}
|
||||
@@ -405,6 +407,8 @@ export const SpaceWorkspaceWidget = () => {
|
||||
onSetSoundVolume={setMasterVolume}
|
||||
isSoundMuted={isMuted}
|
||||
onSetSoundMuted={setMuted}
|
||||
isImmersionMode={isImmersionMode}
|
||||
onImmersionModeChange={setImmersionMode}
|
||||
onCaptureThought={(note) => addThought(note, selectedRoom.name)}
|
||||
onDeleteThought={removeThought}
|
||||
onSetThoughtCompleted={setThoughtCompleted}
|
||||
|
||||
Reference in New Issue
Block a user