style(space): 상단 토스트 크기·패딩·타이포 조정
This commit is contained in:
@@ -26,14 +26,14 @@ export const FocusTopToast = ({
|
||||
role="status"
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
className="pointer-events-auto inline-flex max-w-[min(420px,92vw)] items-center gap-2 rounded-full border border-white/14 bg-black/32 px-3 py-1.5 text-xs text-white/86 shadow-[0_8px_24px_rgba(2,6,23,0.28)] backdrop-blur-md"
|
||||
className="pointer-events-auto inline-flex min-h-10 max-w-[min(480px,94vw)] items-center gap-2.5 rounded-full border border-white/14 bg-black/36 px-4 py-2 text-sm text-white/88 shadow-[0_10px_28px_rgba(2,6,23,0.3)] backdrop-blur-md"
|
||||
>
|
||||
<span className="truncate">{message}</span>
|
||||
{actionLabel ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={onAction}
|
||||
className="shrink-0 text-xs font-medium text-white/92 underline underline-offset-2 transition-colors hover:text-white"
|
||||
className="shrink-0 text-sm font-semibold text-white/92 underline underline-offset-2 transition-colors hover:text-white"
|
||||
>
|
||||
{actionLabel}
|
||||
</button>
|
||||
|
||||
@@ -143,14 +143,11 @@ const resolveInitialTimerLabel = (
|
||||
|
||||
export const SpaceWorkspaceWidget = () => {
|
||||
const searchParams = useSearchParams();
|
||||
const storedSelection = useMemo(() => readStoredWorkspaceSelection(), []);
|
||||
const roomQuery = searchParams.get('room');
|
||||
const goalQuery = searchParams.get('goal');
|
||||
const goalQuery = searchParams.get('goal')?.trim() ?? '';
|
||||
const soundQuery = searchParams.get('sound');
|
||||
const timerQuery = searchParams.get('timer');
|
||||
const storedGoal = storedSelection.goal?.trim() ?? '';
|
||||
const hasQueryOverrides = Boolean(roomQuery || goalQuery || soundQuery || timerQuery);
|
||||
const canOfferResume = storedGoal.length > 0 && !hasQueryOverrides;
|
||||
const {
|
||||
thoughts,
|
||||
thoughtCount,
|
||||
@@ -162,17 +159,17 @@ export const SpaceWorkspaceWidget = () => {
|
||||
setThoughtCompleted,
|
||||
} = useThoughtInbox();
|
||||
|
||||
const initialRoomId = resolveInitialRoomId(roomQuery, storedSelection.sceneId);
|
||||
const initialRoomId = resolveInitialRoomId(roomQuery, undefined);
|
||||
const initialRoom = getRoomById(initialRoomId) ?? ROOM_THEMES[0];
|
||||
const initialGoal = goalQuery?.trim() ?? '';
|
||||
const initialGoal = goalQuery;
|
||||
const initialSoundPresetId = resolveInitialSoundPreset(
|
||||
soundQuery,
|
||||
storedSelection.soundPresetId,
|
||||
undefined,
|
||||
initialRoom.recommendedSoundPresetId,
|
||||
);
|
||||
const initialTimerLabel = resolveInitialTimerLabel(
|
||||
timerQuery,
|
||||
storedSelection.timerPresetId,
|
||||
undefined,
|
||||
initialRoom.recommendedTimerPresetId,
|
||||
);
|
||||
|
||||
@@ -181,10 +178,12 @@ export const SpaceWorkspaceWidget = () => {
|
||||
const [selectedTimerLabel, setSelectedTimerLabel] = useState(initialTimerLabel);
|
||||
const [goalInput, setGoalInput] = useState(initialGoal);
|
||||
const [selectedGoalId, setSelectedGoalId] = useState<string | null>(null);
|
||||
const [showResumePrompt, setShowResumePrompt] = useState(canOfferResume);
|
||||
const [resumeGoal, setResumeGoal] = useState('');
|
||||
const [showResumePrompt, setShowResumePrompt] = useState(false);
|
||||
const [hasHydratedSelection, setHasHydratedSelection] = useState(false);
|
||||
const [selectionOverride, setSelectionOverride] = useState<SelectionOverride>({
|
||||
sound: Boolean(storedSelection.override?.sound),
|
||||
timer: Boolean(storedSelection.override?.timer),
|
||||
sound: false,
|
||||
timer: false,
|
||||
});
|
||||
|
||||
const {
|
||||
@@ -234,6 +233,41 @@ export const SpaceWorkspaceWidget = () => {
|
||||
}
|
||||
}, [selectionOverride.sound, selectionOverride.timer, setSelectedPresetId]);
|
||||
|
||||
useEffect(() => {
|
||||
const storedSelection = readStoredWorkspaceSelection();
|
||||
const restoredSelectionOverride: SelectionOverride = {
|
||||
sound: Boolean(storedSelection.override?.sound),
|
||||
timer: Boolean(storedSelection.override?.timer),
|
||||
};
|
||||
|
||||
setSelectionOverride(restoredSelectionOverride);
|
||||
|
||||
if (!roomQuery && storedSelection.sceneId && getRoomById(storedSelection.sceneId)) {
|
||||
setSelectedRoomId(storedSelection.sceneId);
|
||||
}
|
||||
|
||||
if (!timerQuery) {
|
||||
const restoredTimerLabel = resolveTimerLabelFromPresetId(storedSelection.timerPresetId);
|
||||
|
||||
if (restoredTimerLabel) {
|
||||
setSelectedTimerLabel(restoredTimerLabel);
|
||||
}
|
||||
}
|
||||
|
||||
if (!soundQuery && storedSelection.soundPresetId && SOUND_PRESETS.some((preset) => preset.id === storedSelection.soundPresetId)) {
|
||||
setSelectedPresetId(storedSelection.soundPresetId);
|
||||
}
|
||||
|
||||
const restoredGoal = storedSelection.goal?.trim() ?? '';
|
||||
|
||||
if (!goalQuery && restoredGoal.length > 0 && !hasQueryOverrides) {
|
||||
setResumeGoal(restoredGoal);
|
||||
setShowResumePrompt(true);
|
||||
}
|
||||
|
||||
setHasHydratedSelection(true);
|
||||
}, [goalQuery, hasQueryOverrides, roomQuery, setSelectedPresetId, soundQuery, timerQuery]);
|
||||
|
||||
useEffect(() => {
|
||||
applyRecommendedSelections(selectedRoomId);
|
||||
}, [applyRecommendedSelections, selectedRoomId]);
|
||||
@@ -323,11 +357,15 @@ export const SpaceWorkspaceWidget = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasHydratedSelection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const timerPresetId = resolveTimerPresetIdFromLabel(selectedTimerLabel);
|
||||
const normalizedGoal = goalInput.trim().length > 0
|
||||
? goalInput.trim()
|
||||
: showResumePrompt
|
||||
? storedGoal
|
||||
? resumeGoal
|
||||
: '';
|
||||
|
||||
window.localStorage.setItem(
|
||||
@@ -340,7 +378,7 @@ export const SpaceWorkspaceWidget = () => {
|
||||
override: selectionOverride,
|
||||
}),
|
||||
);
|
||||
}, [goalInput, selectedRoomId, selectedTimerLabel, selectedPresetId, selectionOverride, showResumePrompt, storedGoal]);
|
||||
}, [goalInput, hasHydratedSelection, resumeGoal, selectedRoomId, selectedTimerLabel, selectedPresetId, selectionOverride, showResumePrompt]);
|
||||
|
||||
return (
|
||||
<div className="relative h-dvh overflow-hidden text-white">
|
||||
@@ -373,11 +411,11 @@ export const SpaceWorkspaceWidget = () => {
|
||||
onGoalChipSelect={handleGoalChipSelect}
|
||||
onStart={handleStart}
|
||||
resumeHint={
|
||||
showResumePrompt
|
||||
showResumePrompt && resumeGoal
|
||||
? {
|
||||
goal: storedGoal,
|
||||
goal: resumeGoal,
|
||||
onResume: () => {
|
||||
setGoalInput(storedGoal);
|
||||
setGoalInput(resumeGoal);
|
||||
setSelectedGoalId(null);
|
||||
setShowResumePrompt(false);
|
||||
setWorkspaceMode('focus');
|
||||
|
||||
Reference in New Issue
Block a user