refactor(feedback): 전역 토스트 제거 및 HUD 오버레이 피드백 도입

This commit is contained in:
2026-03-04 21:56:51 +09:00
parent 06dbee8d63
commit 836679753e
5 changed files with 30 additions and 128 deletions

View File

@@ -37,7 +37,7 @@ export const SpaceTimerHudWidget = ({
onGoalCompleteRequest,
onStatusAction,
}: SpaceTimerHudWidgetProps) => {
const { isBreatheMode, hintMessage, triggerRestart } = useRestart30s();
const { isBreatheMode, triggerRestart } = useRestart30s();
const normalizedGoal = goal.trim().length > 0 ? goal.trim() : '이번 한 조각을 설정해 주세요.';
return (
@@ -55,7 +55,7 @@ export const SpaceTimerHudWidget = ({
/>
<section
className={cn(
'relative z-10 flex min-h-[4.65rem] items-center justify-between gap-3 rounded-2xl px-3.5 py-2 transition-colors',
'relative z-10 flex h-[4.85rem] items-center justify-between gap-3 overflow-hidden rounded-2xl px-3.5 py-2 transition-colors',
isImmersionMode
? 'border border-white/12 bg-black/22 backdrop-blur-md'
: 'border border-white/12 bg-black/24 backdrop-blur-md',
@@ -96,26 +96,6 @@ export const SpaceTimerHudWidget = ({
</button>
</div>
{statusLine ? (
<div className="mt-1 flex min-w-0 items-center gap-2">
<p className={cn('min-w-0 truncate text-[11px]', isImmersionMode ? 'text-white/68' : 'text-white/66')}>
{statusLine.message}
</p>
{statusLine.actionLabel ? (
<button
type="button"
onClick={onStatusAction}
className="shrink-0 text-[11px] font-medium text-white/76 underline-offset-2 transition-colors hover:text-white/92 hover:underline"
>
{statusLine.actionLabel}
</button>
) : null}
</div>
) : hintMessage ? (
<p className={cn('mt-1 truncate text-[10px]', isImmersionMode ? 'text-white/52' : 'text-white/52')}>
{hintMessage}
</p>
) : null}
</div>
<div className="flex items-center gap-2.5">
@@ -152,6 +132,30 @@ export const SpaceTimerHudWidget = ({
/>
</div>
</section>
<div
className="pointer-events-none absolute bottom-2 left-3.5 z-[12] max-w-[72%]"
role="status"
aria-live="polite"
aria-atomic="true"
>
<div
className={cn(
'inline-flex max-w-full items-center gap-1.5 rounded-full border border-white/12 bg-black/24 px-2.5 py-1 text-[10px] text-white/72 backdrop-blur-sm transition-all duration-[220ms] ease-out motion-reduce:duration-0',
statusLine ? 'translate-y-0 opacity-100' : 'translate-y-1 opacity-0',
)}
>
<span className="truncate">{statusLine?.message ?? ''}</span>
{statusLine?.actionLabel ? (
<button
type="button"
onClick={onStatusAction}
className="pointer-events-auto shrink-0 text-[10px] font-medium text-white/84 underline-offset-2 transition-colors hover:text-white hover:underline"
>
{statusLine.actionLabel}
</button>
) : null}
</div>
</div>
</div>
</div>
);