1010import { Canvas } from '@react-three/fiber' ;
1111import { useReducedMotion } from 'framer-motion' ;
1212import { useSceneTheme } from '@/lib/3d/hooks/useSceneTheme' ;
13- import { CHRONOS_STYLES , CHRONOS_PHASES , toChronosPhase , type ChronosPhase } from './chronosStyles' ;
13+ import { CHRONOS_STYLES , CHRONOS_PHASES , CHRONOS_STATE_LABELS , toChronosPhase , type ChronosPhase } from './chronosStyles' ;
1414import { ChronosSphere } from './ChronosSphere' ;
1515
1616interface ChronosCanvasProps {
@@ -31,17 +31,15 @@ interface ChronosCanvasProps {
3131 onLongPress ?: ( ) => void ;
3232 /** 中央显示内容(时间字符串) */
3333 timeStr : string ;
34- /** 中央显示标签(如 专注中) */
35- label : string ;
3634}
3735
3836/** 2D 静态回退形态(reduced motion / 极端低配) */
39- function ChronosStatic ( { phase, timeStr, label } : {
37+ function ChronosStatic ( { phase, timeStr } : {
4038 phase : ChronosPhase ;
4139 timeStr : string ;
42- label : string ;
4340} ) {
4441 const phaseColor = CHRONOS_PHASES [ phase ] . body ;
42+ const state = CHRONOS_STATE_LABELS [ phase ] ;
4543 return (
4644 < div className = "relative flex items-center justify-center w-full h-full" >
4745 { /* 静态光环 + 渐变球体 */ }
@@ -59,9 +57,10 @@ function ChronosStatic({ phase, timeStr, label }: {
5957 < span className = "font-timer font-light tracking-tight leading-none text-text-primary" style = { { fontSize : 'clamp(2rem, 8vmin, 4.5rem)' , fontVariantNumeric : 'tabular-nums' } } >
6058 { timeStr }
6159 </ span >
62- < span className = "text-[11px] mt-2 font-medium tracking-[0.15em] uppercase text-text-tertiary" >
63- { label }
60+ < span className = "text-[11px] mt-2 font-medium tracking-[0.15em] uppercase" style = { { color : phaseColor } } >
61+ { state . icon } { state . name }
6462 </ span >
63+ < span className = "text-[10px] mt-1 text-text-tertiary/60" > { state . hint } </ span >
6564 </ div >
6665 </ div >
6766 ) ;
@@ -79,24 +78,26 @@ export function ChronosCanvas({
7978 onTap,
8079 onLongPress,
8180 timeStr,
82- label,
8381} : ChronosCanvasProps ) {
8482 const theme = useSceneTheme ( ) ;
8583 const reduced = useReducedMotion ( ) ;
8684 const style = CHRONOS_STYLES [ theme ] ;
8785 const chronosPhase = toChronosPhase ( phase , isRunning , remainingSeconds , started ) ;
86+ // 状态指示:完整状态机(沉睡/呼吸/专注/短休/长休/即将完成),优先于静态 label
87+ const state = CHRONOS_STATE_LABELS [ chronosPhase ] ;
88+ const stateColor = CHRONOS_PHASES [ chronosPhase ] . body ;
8889
8990 // 降级:减少动效偏好 → 2D 静态形态
9091 if ( reduced ) {
91- return < ChronosStatic phase = { chronosPhase } timeStr = { timeStr } label = { label } /> ;
92+ return < ChronosStatic phase = { chronosPhase } timeStr = { timeStr } /> ;
9293 }
9394
9495 return (
9596 < div
9697 className = { mode === 'full'
9798 ? 'absolute inset-0 flex items-center justify-center pointer-events-none'
9899 : 'relative w-[clamp(150px,34vmin,280px)] h-[clamp(150px,34vmin,280px)] pointer-events-none' }
99- aria-label = { `${ label } ${ timeStr } ` }
100+ aria-label = { `${ state . name } ${ timeStr } ` }
100101 role = "timer"
101102 >
102103 < Canvas
@@ -119,17 +120,21 @@ export function ChronosCanvas({
119120 onLongPress = { onLongPress }
120121 />
121122 </ Canvas >
122- { /* 中央数字 (HTML 层,与 3D 叠加) */ }
123+ { /* 中央状态区:时间 + 状态名 + 交互提示 (HTML 层,与 3D 叠加) */ }
123124 < div className = "absolute inset-0 flex flex-col items-center justify-center pointer-events-none" >
124125 < span
125126 className = "font-timer font-light tracking-tight leading-none text-text-primary"
126127 style = { { fontSize : mode === 'full' ? 'clamp(3rem, 9vmin, 6rem)' : 'clamp(1.75rem, 7vmin, 3.5rem)' , fontVariantNumeric : 'tabular-nums' } }
127128 >
128129 { timeStr }
129130 </ span >
130- < span className = "text-[11px] mt-2 font-medium tracking-[0.15em] uppercase text-text-tertiary" >
131- { label }
131+ < span
132+ className = "text-[11px] mt-2 font-medium tracking-[0.15em] uppercase transition-colors duration-500"
133+ style = { { color : stateColor } }
134+ >
135+ { state . icon } { state . name }
132136 </ span >
137+ < span className = "text-[10px] mt-1 text-text-tertiary/60" > { state . hint } </ span >
133138 </ div >
134139 </ div >
135140 ) ;
0 commit comments