fix(space): HUD 시작 흐름과 컨트롤 상태를 정리
This commit is contained in:
@@ -12,10 +12,14 @@ interface SpaceTimerHudWidgetProps {
|
||||
goal: string;
|
||||
timeDisplay?: string;
|
||||
className?: string;
|
||||
hasActiveSession?: boolean;
|
||||
sessionPhase?: 'focus' | 'break' | null;
|
||||
playbackState?: 'running' | 'paused' | null;
|
||||
isControlsDisabled?: boolean;
|
||||
isImmersionMode?: boolean;
|
||||
canStart?: boolean;
|
||||
canPause?: boolean;
|
||||
canReset?: boolean;
|
||||
onStartClick?: () => void;
|
||||
onPauseClick?: () => void;
|
||||
onResetClick?: () => void;
|
||||
@@ -33,10 +37,14 @@ export const SpaceTimerHudWidget = ({
|
||||
goal,
|
||||
timeDisplay = '25:00',
|
||||
className,
|
||||
hasActiveSession = false,
|
||||
sessionPhase = 'focus',
|
||||
playbackState = 'running',
|
||||
playbackState = 'paused',
|
||||
isControlsDisabled = false,
|
||||
isImmersionMode = false,
|
||||
canStart = true,
|
||||
canPause = false,
|
||||
canReset = false,
|
||||
onStartClick,
|
||||
onPauseClick,
|
||||
onResetClick,
|
||||
@@ -46,6 +54,8 @@ export const SpaceTimerHudWidget = ({
|
||||
const normalizedGoal = goal.trim().length > 0 ? goal.trim() : '이번 한 조각을 설정해 주세요.';
|
||||
const modeLabel = isBreatheMode
|
||||
? RECOVERY_30S_MODE_LABEL
|
||||
: !hasActiveSession
|
||||
? 'Ready'
|
||||
: sessionPhase === 'break'
|
||||
? 'Break'
|
||||
: 'Focus';
|
||||
@@ -110,42 +120,59 @@ export const SpaceTimerHudWidget = ({
|
||||
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div className="flex items-center gap-1.5">
|
||||
{HUD_ACTIONS.map((action) => (
|
||||
<button
|
||||
key={action.id}
|
||||
type="button"
|
||||
title={action.label}
|
||||
disabled={isControlsDisabled}
|
||||
onClick={() => {
|
||||
if (action.id === 'start') {
|
||||
onStartClick?.();
|
||||
}
|
||||
{HUD_ACTIONS.map((action) => {
|
||||
const isStartAction = action.id === 'start';
|
||||
const isPauseAction = action.id === 'pause';
|
||||
const isResetAction = action.id === 'reset';
|
||||
const isDisabled =
|
||||
isControlsDisabled ||
|
||||
(isStartAction ? !canStart : isPauseAction ? !canPause : !canReset);
|
||||
const isHighlighted =
|
||||
(isStartAction && playbackState !== 'running') ||
|
||||
(isPauseAction && playbackState === 'running');
|
||||
|
||||
if (action.id === 'pause') {
|
||||
onPauseClick?.();
|
||||
}
|
||||
return (
|
||||
<button
|
||||
key={action.id}
|
||||
type="button"
|
||||
title={action.label}
|
||||
aria-pressed={isHighlighted}
|
||||
disabled={isDisabled}
|
||||
onClick={() => {
|
||||
if (isStartAction) {
|
||||
onStartClick?.();
|
||||
}
|
||||
|
||||
if (action.id === 'reset') {
|
||||
onResetClick?.();
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
'inline-flex h-8 w-8 items-center justify-center rounded-full border text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-200/80 disabled:cursor-not-allowed disabled:opacity-45',
|
||||
isImmersionMode
|
||||
? 'border-white/14 bg-black/26 text-white/82 hover:bg-black/34'
|
||||
: 'border-white/14 bg-black/26 text-white/84 hover:bg-black/34',
|
||||
action.id === 'start' && playbackState === 'running'
|
||||
? 'border-sky-200/42 bg-sky-200/18 text-white'
|
||||
: '',
|
||||
action.id === 'pause' && playbackState === 'paused'
|
||||
? 'border-amber-200/42 bg-amber-200/16 text-white'
|
||||
: '',
|
||||
)}
|
||||
>
|
||||
<span aria-hidden>{action.icon}</span>
|
||||
<span className="sr-only">{action.label}</span>
|
||||
</button>
|
||||
))}
|
||||
if (isPauseAction) {
|
||||
onPauseClick?.();
|
||||
}
|
||||
|
||||
if (isResetAction) {
|
||||
onResetClick?.();
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
'inline-flex h-9 w-9 items-center justify-center rounded-full border text-sm transition-[transform,background-color,border-color,box-shadow,color,opacity] duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-200/80 active:translate-y-px active:scale-[0.95] disabled:cursor-not-allowed disabled:opacity-38 disabled:shadow-none',
|
||||
'shadow-[inset_0_1px_0_rgba(255,255,255,0.08),0_8px_18px_rgba(2,6,23,0.18)]',
|
||||
isImmersionMode
|
||||
? 'border-white/14 bg-black/28 text-white/82 hover:border-white/22 hover:bg-white/[0.09]'
|
||||
: 'border-white/14 bg-black/28 text-white/84 hover:border-white/22 hover:bg-white/[0.09]',
|
||||
isStartAction && isHighlighted
|
||||
? 'border-sky-200/56 bg-sky-200/20 text-sky-50 shadow-[inset_0_1px_0_rgba(255,255,255,0.12),0_10px_22px_rgba(56,189,248,0.24)]'
|
||||
: '',
|
||||
isPauseAction && isHighlighted
|
||||
? 'border-amber-200/52 bg-amber-200/18 text-amber-50 shadow-[inset_0_1px_0_rgba(255,255,255,0.12),0_10px_22px_rgba(251,191,36,0.18)]'
|
||||
: '',
|
||||
isResetAction && !isDisabled
|
||||
? 'hover:border-white/26 hover:bg-white/[0.12] hover:text-white'
|
||||
: '',
|
||||
)}
|
||||
>
|
||||
<span aria-hidden>{action.icon}</span>
|
||||
<span className="sr-only">{action.label}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<Restart30sAction
|
||||
onTrigger={triggerRestart}
|
||||
|
||||
Reference in New Issue
Block a user