feat(immersion): 몰입 모드 상단 액션을 나가기로 전환
맥락: - 몰입 모드 ON에서 상단 우측 액션이 허브 이동으로 보이는 혼선을 줄이고 즉시 이탈 동선을 제공하기 위해 변경사항: - 몰입 모드 훅에 exitImmersionMode 액션 추가 - 몰입 모드 ON 시 상단 우측 액션을 나가기 버튼으로 전환 - 나가기 클릭 시 토스트(나가기(더미)) 노출 후 몰입 모드 OFF 처리 - docs/90_current_state.md, docs/session_brief.md 최신 상태 반영 검증: - npx tsc --noEmit 세션-상태: 몰입 모드 ON에서 상단 우측 액션은 나가기로 동작함 세션-다음: RoomSheet/도크의 인원수 중심 정보를 분위기형 정보로 교체 세션-리스크: 터치 환경에서 미니 레일 발견성이 낮을 수 있어 UX 보완이 필요
This commit is contained in:
@@ -22,6 +22,12 @@ Last Updated: 2026-02-27
|
|||||||
- `/space` 하단 사운드 프리셋 바 제거, 오른쪽 `🎧 Sound` 시트로 이동
|
- `/space` 하단 사운드 프리셋 바 제거, 오른쪽 `🎧 Sound` 시트로 이동
|
||||||
- `features/sound-preset` + `widgets/sound-sheet` 추가
|
- `features/sound-preset` + `widgets/sound-sheet` 추가
|
||||||
- `features/immersion-mode` 추가, Quick 시트에서 몰입 모드 토글 연결
|
- `features/immersion-mode` 추가, Quick 시트에서 몰입 모드 토글 연결
|
||||||
|
- `/space` 상단 헤더 크롬 최소화:
|
||||||
|
- 헤더 프레임(border/강한 배경) 제거
|
||||||
|
- 패딩 축소로 배경 노출 증가
|
||||||
|
- 타이머 HUD 하단 위치를 safe-area 기반 최소 여백으로 조정
|
||||||
|
- 몰입 모드 ON 시 상단 액션을 `나가기` 버튼으로 전환
|
||||||
|
- 클릭 시 토스트 `나가기(더미)` 노출 + 몰입 모드 OFF
|
||||||
- 몰입 모드 ON 시 `/space` 크롬 정리:
|
- 몰입 모드 ON 시 `/space` 크롬 정리:
|
||||||
- 상단 `Current Room` 블록 숨김
|
- 상단 `Current Room` 블록 숨김
|
||||||
- 우상단 허브 버튼 소형 아이콘화
|
- 우상단 허브 버튼 소형 아이콘화
|
||||||
@@ -39,12 +45,14 @@ Last Updated: 2026-02-27
|
|||||||
|
|
||||||
1. `RoomSheetWidget`/도크 패널의 인원수 기반 UI를 큐레이션형 정보로 재정의
|
1. `RoomSheetWidget`/도크 패널의 인원수 기반 UI를 큐레이션형 정보로 재정의
|
||||||
2. 몰입 모드에서 터치 환경(hover 없음) 레일 노출 UX를 보완할지 정책 확정
|
2. 몰입 모드에서 터치 환경(hover 없음) 레일 노출 UX를 보완할지 정책 확정
|
||||||
|
3. `/space` 헤더 최소화 스타일을 테마별(밝은 배경) 대비 점검
|
||||||
|
|
||||||
## RISKS
|
## RISKS
|
||||||
|
|
||||||
- `npm run build`는 네트워크 제한 시 Google Font fetch 실패 가능
|
- `npm run build`는 네트워크 제한 시 Google Font fetch 실패 가능
|
||||||
- 터치 기기에서 레일 미니 상태가 발견성 낮을 수 있어 추가 힌트가 필요할 수 있음
|
- 터치 기기에서 레일 미니 상태가 발견성 낮을 수 있어 추가 힌트가 필요할 수 있음
|
||||||
- 일부 시트(예: Room)는 아직 인원수 중심 문구가 남아 있어 톤 불일치 가능성 존재
|
- 일부 시트(예: Room)는 아직 인원수 중심 문구가 남아 있어 톤 불일치 가능성 존재
|
||||||
|
- safe-area 값이 작은 기기에서는 HUD가 너무 낮게 느껴질 수 있어 세부 조정 여지 존재
|
||||||
|
|
||||||
## CHANGED FILES
|
## CHANGED FILES
|
||||||
|
|
||||||
@@ -81,6 +89,8 @@ Last Updated: 2026-02-27
|
|||||||
- `src/widgets/space-tools-dock/model/useSpaceToolsDock.ts`
|
- `src/widgets/space-tools-dock/model/useSpaceToolsDock.ts`
|
||||||
- `src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx`
|
- `src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx`
|
||||||
- `src/widgets/space-timer-hud/ui/SpaceTimerHudWidget.tsx`
|
- `src/widgets/space-timer-hud/ui/SpaceTimerHudWidget.tsx`
|
||||||
|
- `src/widgets/space-chrome/ui/SpaceChromeWidget.tsx`
|
||||||
|
- `src/features/immersion-mode/model/useImmersionMode.ts`
|
||||||
|
|
||||||
## QUICK VERIFY
|
## QUICK VERIFY
|
||||||
|
|
||||||
|
|||||||
@@ -16,12 +16,15 @@ Last Updated: 2026-02-27
|
|||||||
|
|
||||||
1. `RoomSheetWidget`/도크 패널의 인원 수 UI를 큐레이션형으로 전환
|
1. `RoomSheetWidget`/도크 패널의 인원 수 UI를 큐레이션형으로 전환
|
||||||
2. 몰입 모드에서 터치 환경 레일 발견성(미니 핸들 UX) 보완 여부 결정
|
2. 몰입 모드에서 터치 환경 레일 발견성(미니 핸들 UX) 보완 여부 결정
|
||||||
|
3. `/space` 헤더 최소화 스타일의 밝은 배경 대비 점검
|
||||||
|
|
||||||
## 최근 세션 상태
|
## 최근 세션 상태
|
||||||
|
|
||||||
- 세션 복구용 문서/템플릿/스크립트가 준비되어 있다.
|
- 세션 복구용 문서/템플릿/스크립트가 준비되어 있다.
|
||||||
- `workFlow.md`는 토큰 절약 모드를 사용한다.
|
- `workFlow.md`는 토큰 절약 모드를 사용한다.
|
||||||
- `/space` 하단 사운드 바를 제거하고 오른쪽 `🎧 Sound` 시트로 이동했다.
|
- `/space` 하단 사운드 바를 제거하고 오른쪽 `🎧 Sound` 시트로 이동했다.
|
||||||
|
- `/space` 헤더 프레임을 축소하고 HUD를 하단 safe-area 기준으로 더 밀착시켰다.
|
||||||
|
- 몰입 모드 ON에서 상단 우측 액션을 `나가기`로 전환했고, 클릭 시 토스트(더미)와 함께 몰입 모드 OFF 처리한다.
|
||||||
- 몰입 모드 ON 시 상단 룸 블록 숨김, 레일 미니화, HUD 저대비, 비네팅 강화가 적용된다.
|
- 몰입 모드 ON 시 상단 룸 블록 숨김, 레일 미니화, HUD 저대비, 비네팅 강화가 적용된다.
|
||||||
- 이후 작업은 `docs/work.md`를 기준으로 실행한다.
|
- 이후 작업은 `docs/work.md`를 기준으로 실행한다.
|
||||||
|
|
||||||
@@ -29,6 +32,7 @@ Last Updated: 2026-02-27
|
|||||||
|
|
||||||
- 네트워크 제한 환경에서는 `npm run build` 시 Google Fonts fetch 실패 가능
|
- 네트워크 제한 환경에서는 `npm run build` 시 Google Fonts fetch 실패 가능
|
||||||
- 터치 환경에서 레일 미니 상태가 발견성 낮을 수 있어 UX 보완이 필요할 수 있음
|
- 터치 환경에서 레일 미니 상태가 발견성 낮을 수 있어 UX 보완이 필요할 수 있음
|
||||||
|
- safe-area가 작은 기기에서는 HUD 하단 간격 체감이 과도할 수 있어 미세 조정이 필요할 수 있음
|
||||||
|
|
||||||
## 상세 원문 위치
|
## 상세 원문 위치
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
import { useToast } from '@/shared/ui';
|
||||||
|
|
||||||
export const useImmersionMode = () => {
|
export const useImmersionMode = () => {
|
||||||
|
const { pushToast } = useToast();
|
||||||
const [isImmersionMode, setImmersionMode] = useState(false);
|
const [isImmersionMode, setImmersionMode] = useState(false);
|
||||||
|
|
||||||
const toggleImmersionMode = () => {
|
const toggleImmersionMode = () => {
|
||||||
setImmersionMode((current) => !current);
|
setImmersionMode((current) => !current);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const exitImmersionMode = () => {
|
||||||
|
setImmersionMode(false);
|
||||||
|
pushToast({ title: '나가기(더미)' });
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isImmersionMode,
|
isImmersionMode,
|
||||||
toggleImmersionMode,
|
toggleImmersionMode,
|
||||||
|
exitImmersionMode,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,12 +4,14 @@ interface SpaceChromeWidgetProps {
|
|||||||
roomName: string;
|
roomName: string;
|
||||||
vibeLabel: string;
|
vibeLabel: string;
|
||||||
isImmersionMode: boolean;
|
isImmersionMode: boolean;
|
||||||
|
onExitImmersionMode: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const SpaceChromeWidget = ({
|
export const SpaceChromeWidget = ({
|
||||||
roomName,
|
roomName,
|
||||||
vibeLabel,
|
vibeLabel,
|
||||||
isImmersionMode,
|
isImmersionMode,
|
||||||
|
onExitImmersionMode,
|
||||||
}: SpaceChromeWidgetProps) => {
|
}: SpaceChromeWidgetProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="px-4 pt-2 sm:px-6">
|
<div className="px-4 pt-2 sm:px-6">
|
||||||
@@ -21,23 +23,23 @@ export const SpaceChromeWidget = ({
|
|||||||
<p className="text-sm font-medium tracking-tight text-white/90">VibeRoom</p>
|
<p className="text-sm font-medium tracking-tight text-white/90">VibeRoom</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Link
|
{isImmersionMode ? (
|
||||||
href="/app"
|
<button
|
||||||
className={
|
type="button"
|
||||||
isImmersionMode
|
onClick={onExitImmersionMode}
|
||||||
? 'inline-flex h-7 w-7 items-center justify-center rounded-md bg-white/8 text-[11px] text-white/74 transition hover:bg-white/14 hover:text-white'
|
className="inline-flex items-center gap-1 rounded-md bg-white/8 px-2 py-1 text-[11px] text-white/74 transition hover:bg-white/14 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-200/80"
|
||||||
: 'rounded-lg bg-white/8 px-2.5 py-1.5 text-xs text-white/82 transition hover:bg-white/14 hover:text-white'
|
>
|
||||||
}
|
<span aria-hidden>⤫</span>
|
||||||
>
|
<span>나가기</span>
|
||||||
{isImmersionMode ? (
|
</button>
|
||||||
<>
|
) : (
|
||||||
<span aria-hidden>↩</span>
|
<Link
|
||||||
<span className="sr-only">허브로 돌아가기</span>
|
href="/app"
|
||||||
</>
|
className="rounded-lg bg-white/8 px-2.5 py-1.5 text-xs text-white/82 transition hover:bg-white/14 hover:text-white"
|
||||||
) : (
|
>
|
||||||
'허브로 돌아가기'
|
허브로 돌아가기
|
||||||
)}
|
</Link>
|
||||||
</Link>
|
)}
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{!isImmersionMode ? (
|
{!isImmersionMode ? (
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export const SpaceSkeletonWidget = () => {
|
|||||||
const soundFromQuery = searchParams.get('sound');
|
const soundFromQuery = searchParams.get('sound');
|
||||||
|
|
||||||
const room = useMemo(() => getRoomById(roomId) ?? ROOM_THEMES[0], [roomId]);
|
const room = useMemo(() => getRoomById(roomId) ?? ROOM_THEMES[0], [roomId]);
|
||||||
const { isImmersionMode, toggleImmersionMode } = useImmersionMode();
|
const { isImmersionMode, toggleImmersionMode, exitImmersionMode } = useImmersionMode();
|
||||||
const initialSoundPresetId =
|
const initialSoundPresetId =
|
||||||
SOUND_PRESETS.find((preset) => preset.id === soundFromQuery)?.id ??
|
SOUND_PRESETS.find((preset) => preset.id === soundFromQuery)?.id ??
|
||||||
SOUND_PRESETS[0].id;
|
SOUND_PRESETS[0].id;
|
||||||
@@ -66,6 +66,7 @@ export const SpaceSkeletonWidget = () => {
|
|||||||
roomName={room.name}
|
roomName={room.name}
|
||||||
vibeLabel={room.vibeLabel}
|
vibeLabel={room.vibeLabel}
|
||||||
isImmersionMode={isImmersionMode}
|
isImmersionMode={isImmersionMode}
|
||||||
|
onExitImmersionMode={exitImmersionMode}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<main className="flex-1" />
|
<main className="flex-1" />
|
||||||
|
|||||||
Reference in New Issue
Block a user