From 8f64637b6f49e4c87bd9d6725eb38df8038517f6 Mon Sep 17 00:00:00 2001 From: corpi Date: Wed, 4 Mar 2026 14:55:14 +0900 Subject: [PATCH] =?UTF-8?q?refactor(quick-controls):=20=EC=82=AC=EC=9A=B4?= =?UTF-8?q?=EB=93=9C=20=EC=97=AD=ED=95=A0=20=EB=B6=84=EB=A6=AC=EC=99=80=20?= =?UTF-8?q?=ED=8C=A8=EB=84=90=20=EB=A0=88=EC=9D=B4=EC=95=84=EC=9B=83=C2=B7?= =?UTF-8?q?=EC=98=A4=EB=B2=84=EB=A0=88=EC=9D=B4=20=EA=B0=9C=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/ControlCenterSheetWidget.tsx | 27 ++++++++++--------- .../space-sheet-shell/ui/SpaceSideSheet.tsx | 4 +++ .../model/getQuickSoundPresets.ts | 21 +++++++++++++++ .../ui/SpaceToolsDockWidget.tsx | 23 ++++++++-------- 4 files changed, 51 insertions(+), 24 deletions(-) create mode 100644 src/widgets/space-tools-dock/model/getQuickSoundPresets.ts diff --git a/src/widgets/control-center-sheet/ui/ControlCenterSheetWidget.tsx b/src/widgets/control-center-sheet/ui/ControlCenterSheetWidget.tsx index 9ca7c8e..da95551 100644 --- a/src/widgets/control-center-sheet/ui/ControlCenterSheetWidget.tsx +++ b/src/widgets/control-center-sheet/ui/ControlCenterSheetWidget.tsx @@ -106,11 +106,14 @@ export const ControlCenterSheetWidget = ({ }, [selectedSoundPresetId, soundPresets]); return ( -
-
+
+
{rooms.slice(0, 6).map((room) => { @@ -149,9 +152,9 @@ export const ControlCenterSheetWidget = ({
-
+
-
+
{timerPresets.slice(0, 3).map((preset) => { const selected = preset.label === selectedTimerLabel; const locked = !isPro && PRO_LOCKED_TIMER_LABELS.includes(preset.label); @@ -169,7 +172,7 @@ export const ControlCenterSheetWidget = ({ onSelectTimer(preset.label); }} className={cn( - 'relative rounded-xl border px-2 py-2 text-xs', + 'relative rounded-xl border px-3 py-2.5 text-xs', colorMotionClass, selected ? 'border-sky-200/42 bg-sky-200/16 text-white' @@ -184,9 +187,9 @@ export const ControlCenterSheetWidget = ({
-
+
-
+
{soundPresets.slice(0, 6).map((preset) => { const selected = preset.id === selectedSoundPresetId; const locked = !isPro && PRO_LOCKED_SOUND_IDS.includes(preset.id); @@ -204,7 +207,7 @@ export const ControlCenterSheetWidget = ({ onSelectSound(preset.id); }} className={cn( - 'rounded-full border px-3 py-1.5 text-xs', + 'rounded-xl border px-3 py-2 text-xs', colorMotionClass, selected ? 'border-sky-200/42 bg-sky-200/16 text-white' @@ -219,9 +222,9 @@ export const ControlCenterSheetWidget = ({
-
+
-
+
{QUICK_PACKS.map((pack) => { const locked = !isPro && pack.locked; @@ -238,7 +241,7 @@ export const ControlCenterSheetWidget = ({ onApplyPack(pack.id); }} className={cn( - 'relative rounded-xl border border-white/16 bg-white/[0.04] px-3 py-2 text-left hover:bg-white/[0.1]', + 'relative rounded-xl border border-white/16 bg-white/[0.04] px-3.5 py-2.5 text-left hover:bg-white/[0.1]', colorMotionClass, )} > diff --git a/src/widgets/space-sheet-shell/ui/SpaceSideSheet.tsx b/src/widgets/space-sheet-shell/ui/SpaceSideSheet.tsx index db2d229..972bd80 100644 --- a/src/widgets/space-sheet-shell/ui/SpaceSideSheet.tsx +++ b/src/widgets/space-sheet-shell/ui/SpaceSideSheet.tsx @@ -14,6 +14,7 @@ interface SpaceSideSheetProps { widthClassName?: string; dismissible?: boolean; headerAction?: ReactNode; + overlayClassName?: string; } export const SpaceSideSheet = ({ @@ -26,6 +27,7 @@ export const SpaceSideSheet = ({ widthClassName, dismissible = true, headerAction, + overlayClassName, }: SpaceSideSheetProps) => { const reducedMotion = useReducedMotion(); const transitionMs = reducedMotion ? 0 : 260; @@ -97,6 +99,7 @@ export const SpaceSideSheet = ({ 'fixed inset-0 z-40 bg-slate-950/14 backdrop-blur-[1px] transition-opacity', reducedMotion ? 'duration-0' : 'duration-[240ms]', visible ? 'opacity-100' : 'pointer-events-none opacity-0', + overlayClassName, )} /> ) : ( @@ -106,6 +109,7 @@ export const SpaceSideSheet = ({ 'fixed inset-0 z-40 bg-slate-950/8 backdrop-blur-[1px] transition-opacity', reducedMotion ? 'duration-0' : 'duration-[240ms]', visible ? 'opacity-100' : 'opacity-0', + overlayClassName, )} /> )} diff --git a/src/widgets/space-tools-dock/model/getQuickSoundPresets.ts b/src/widgets/space-tools-dock/model/getQuickSoundPresets.ts new file mode 100644 index 0000000..9951e67 --- /dev/null +++ b/src/widgets/space-tools-dock/model/getQuickSoundPresets.ts @@ -0,0 +1,21 @@ +import { PRO_LOCKED_SOUND_IDS } from '@/entities/plan'; +import type { SoundPreset } from '@/entities/session'; + +const QUICK_SOUND_FALLBACK_IDS = ['rain-focus', 'deep-white', 'silent'] as const; + +const isQuickAvailablePreset = (preset: SoundPreset | undefined): preset is SoundPreset => { + if (!preset) { + return false; + } + + return !PRO_LOCKED_SOUND_IDS.includes(preset.id); +}; + +export const getQuickSoundPresets = (presets: SoundPreset[], selectedPresetId: string) => { + const uniquePresetIds = Array.from(new Set([selectedPresetId, ...QUICK_SOUND_FALLBACK_IDS])); + + return uniquePresetIds + .map((presetId) => presets.find((preset) => preset.id === presetId)) + .filter(isQuickAvailablePreset) + .slice(0, 3); +}; diff --git a/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx b/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx index 958c165..e20c203 100644 --- a/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx +++ b/src/widgets/space-tools-dock/ui/SpaceToolsDockWidget.tsx @@ -12,6 +12,7 @@ import { ControlCenterSheetWidget } from '@/widgets/control-center-sheet'; import { SpaceSideSheet } from '@/widgets/space-sheet-shell'; import type { SpaceAnchorPopoverId, SpaceUtilityPanelId } from '../model/types'; import { applyQuickPack } from '../model/applyQuickPack'; +import { getQuickSoundPresets } from '../model/getQuickSoundPresets'; import { ANCHOR_ICON, formatThoughtCount, RAIL_ICON, UTILITY_PANEL_TITLE } from './constants'; import { InboxToolPanel } from './panels/InboxToolPanel'; interface SpaceToolsDockWidgetProps { @@ -68,6 +69,10 @@ export const SpaceToolsDockWidget = ({ ); }, [selectedPresetId]); + const quickSoundPresets = useMemo(() => { + return getQuickSoundPresets(SOUND_PRESETS, selectedPresetId); + }, [selectedPresetId]); + useEffect(() => { if (!openPopover) { return; @@ -389,12 +394,12 @@ export const SpaceToolsDockWidget = ({ {openPopover === 'sound' ? (
-

사운드 프리셋

+

빠른 사운드 전환

- {SOUND_PRESETS.slice(0, 6).map((preset) => { + {quickSoundPresets.map((preset) => { const selected = preset.id === selectedPresetId; return ( @@ -403,6 +408,7 @@ export const SpaceToolsDockWidget = ({ type="button" onClick={() => { onSelectPreset(preset.id); + pushToast({ title: `${preset.label}로 전환했어요.` }); setOpenPopover(null); }} className={cn( @@ -417,15 +423,6 @@ export const SpaceToolsDockWidget = ({ ); })}
-
- -
) : null}
@@ -442,6 +439,8 @@ export const SpaceToolsDockWidget = ({ ) : undefined } + widthClassName={utilityPanel === 'control-center' ? 'w-[min(408px,94vw)]' : undefined} + overlayClassName={utilityPanel === 'control-center' ? 'bg-slate-950/6 backdrop-blur-none' : undefined} onClose={() => setUtilityPanel(null)} > {utilityPanel === 'control-center' ? (