@@ -4,6 +4,9 @@ import moment from "moment";
4
4
import { useEffect , useState } from "react" ;
5
5
import { formatTimeSinceLastBreak } from "./utils" ;
6
6
7
+ const GRACE_PERIOD_MS = 60000 ;
8
+ const TOTAL_COUNTDOWN_MS = 120000 ;
9
+
7
10
interface BreakNotificationProps {
8
11
onCountdownOver : ( ) => void ;
9
12
onPostponeBreak : ( ) => void ;
@@ -38,11 +41,11 @@ export function BreakNotification({
38
41
const now = moment ( ) ;
39
42
const elapsedMs = now . diff ( startTime , "milliseconds" ) ;
40
43
41
- if ( elapsedMs < 60000 ) {
44
+ if ( elapsedMs < GRACE_PERIOD_MS ) {
42
45
setPhase ( "grace" ) ;
43
- } else if ( elapsedMs < 120000 ) {
46
+ } else if ( elapsedMs < TOTAL_COUNTDOWN_MS ) {
44
47
setPhase ( "countdown" ) ;
45
- setMsRemaining ( 120000 - elapsedMs ) ;
48
+ setMsRemaining ( TOTAL_COUNTDOWN_MS - elapsedMs ) ;
46
49
} else {
47
50
onCountdownOver ( ) ;
48
51
return ;
@@ -61,12 +64,15 @@ export function BreakNotification({
61
64
} , [ onCountdownOver ] ) ;
62
65
63
66
const secondsRemaining = Math . ceil ( msRemaining / 1000 ) ;
67
+ const countdownDurationMs = TOTAL_COUNTDOWN_MS - GRACE_PERIOD_MS ;
64
68
const progressValue =
65
- phase === "countdown" ? ( ( 60000 - msRemaining ) / 60000 ) * 100 : 0 ;
69
+ phase === "countdown"
70
+ ? ( ( countdownDurationMs - msRemaining ) / countdownDurationMs ) * 100
71
+ : 0 ;
66
72
67
73
return (
68
74
< motion . div
69
- className = "flex flex-col w-full h-full z-20 rounded-xl overflow-hidden"
75
+ className = "flex flex-col w-full h-full z-20 rounded-xl overflow-hidden relative "
70
76
initial = { { opacity : 0 , scale : 0.9 , y : 10 } }
71
77
animate = { { opacity : 1 , scale : 1 , y : 0 } }
72
78
exit = { { opacity : 0 , scale : 0.9 , y : 10 } }
@@ -76,6 +82,18 @@ export function BreakNotification({
76
82
color : textColor ,
77
83
} }
78
84
>
85
+ { phase === "countdown" && (
86
+ < div
87
+ className = "absolute inset-0 transition-all duration-75 ease-linear"
88
+ style = { {
89
+ background : textColor ,
90
+ opacity : 0.15 ,
91
+ width : `${ progressValue } %` ,
92
+ left : 0 ,
93
+ top : 0 ,
94
+ } }
95
+ />
96
+ ) }
79
97
< div className = "flex justify-between items-center px-6 py-2 h-full" >
80
98
< div className = "flex flex-col justify-center" >
81
99
< h2
@@ -96,30 +114,14 @@ export function BreakNotification({
96
114
) }
97
115
</ div >
98
116
99
- { /* Action buttons */ }
100
- < div className = "flex justify-center gap-3" >
117
+ < div className = "flex justify-center gap-3 relative z-10" >
101
118
< div className = "relative" >
102
- { /* Circular progress border */ }
103
- { phase === "countdown" && (
104
- < div
105
- className = "absolute rounded-md"
106
- style = { {
107
- top : "-0.5px" ,
108
- right : "-0.5px" ,
109
- bottom : "-0.5px" ,
110
- left : "-0.5px" ,
111
- background : `conic-gradient(from 0deg at 50% 50%, ${ textColor } 0deg, ${ textColor } ${ ( progressValue / 100 ) * 360 } deg, transparent ${ ( progressValue / 100 ) * 360 } deg, transparent 360deg)` ,
112
- padding : "2.5px" ,
113
- WebkitMask :
114
- "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)" ,
115
- WebkitMaskComposite : "xor" ,
116
- mask : "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)" ,
117
- maskComposite : "exclude" ,
118
- } }
119
- />
120
- ) }
119
+ < div
120
+ className = "absolute inset-0 rounded-md"
121
+ style = { { backgroundColor } }
122
+ />
121
123
< Button
122
- className = "!bg-transparent hover:!bg-white/15 active:!bg-white/25 border-white/20 relative z-10"
124
+ className = "!bg-transparent hover:!bg-black/10 active:!bg-black/20 border-white/20 relative z-10"
123
125
onClick = { onStartBreakNow }
124
126
variant = "outline"
125
127
style = { {
@@ -131,30 +133,42 @@ export function BreakNotification({
131
133
</ Button >
132
134
</ div >
133
135
{ postponeBreakEnabled && (
134
- < Button
135
- className = "!bg-transparent hover:!bg-white/15 active:!bg-white/25 border-white/20"
136
- onClick = { onPostponeBreak }
137
- variant = "outline"
138
- style = { {
139
- color : textColor ,
140
- borderColor : "rgba(255, 255, 255, 0.2)" ,
141
- } }
142
- >
143
- Snooze
144
- </ Button >
136
+ < div className = "relative" >
137
+ < div
138
+ className = "absolute inset-0 rounded-md"
139
+ style = { { backgroundColor } }
140
+ />
141
+ < Button
142
+ className = "!bg-transparent hover:!bg-black/10 active:!bg-black/20 border-white/20 relative z-10"
143
+ onClick = { onPostponeBreak }
144
+ variant = "outline"
145
+ style = { {
146
+ color : textColor ,
147
+ borderColor : "rgba(255, 255, 255, 0.2)" ,
148
+ } }
149
+ >
150
+ Snooze
151
+ </ Button >
152
+ </ div >
145
153
) }
146
154
{ skipBreakEnabled && (
147
- < Button
148
- className = "!bg-transparent hover:!bg-white/15 active:!bg-white/25 border-white/20"
149
- onClick = { onSkipBreak }
150
- variant = "outline"
151
- style = { {
152
- color : textColor ,
153
- borderColor : "rgba(255, 255, 255, 0.2)" ,
154
- } }
155
- >
156
- Skip
157
- </ Button >
155
+ < div className = "relative" >
156
+ < div
157
+ className = "absolute inset-0 rounded-md"
158
+ style = { { backgroundColor } }
159
+ />
160
+ < Button
161
+ className = "!bg-transparent hover:!bg-black/10 active:!bg-black/20 border-white/20 relative z-10"
162
+ onClick = { onSkipBreak }
163
+ variant = "outline"
164
+ style = { {
165
+ color : textColor ,
166
+ borderColor : "rgba(255, 255, 255, 0.2)" ,
167
+ } }
168
+ >
169
+ Skip
170
+ </ Button >
171
+ </ div >
158
172
) }
159
173
</ div >
160
174
</ div >
0 commit comments