diff --git a/src/App.jsx b/src/App.jsx index 752fc09..d9aecb1 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -12,7 +12,7 @@ import { useCountdown, useStopwatch } from "./lib/hooks.js"; export default function App() { const [mode, setMode] = useState("stopwatch"); // "stopwatch" | "countdown" const sw = useStopwatch(); - const cd = useCountdown(5 * 60 * 1000); + const cd = useCountdown(0); const [laps, setLaps] = useState([]); @@ -53,6 +53,8 @@ export default function App() { mode === "stopwatch" ? formatHMS(sw.elapsedMs, { showMs: true }) : formatHMS(cd.remainingMs, { showMs: true }); + const isCountdownFinalSeconds = + mode === "countdown" && cd.totalMs > 0 && cd.remainingMs <= 10000; const onReset = () => { if (mode === "stopwatch") { @@ -129,12 +131,16 @@ export default function App() { ) : (
-
+
{viz.title}
- +
@@ -155,14 +161,14 @@ export default function App() {
+
+ 按多次可累加時間,或按「清除」重新設定。 +
-
- 按多次可累加時間,或按「清除」重新設定。 -
diff --git a/src/components/Controls.jsx b/src/components/Controls.jsx index f8f9c2a..cad50a1 100644 --- a/src/components/Controls.jsx +++ b/src/components/Controls.jsx @@ -19,8 +19,8 @@ export default function Controls({ > {isRunning ? "暫停" : "開始"} - {extraRight}
diff --git a/src/components/TimeDisplay.jsx b/src/components/TimeDisplay.jsx index 2c84fa2..b39b36a 100644 --- a/src/components/TimeDisplay.jsx +++ b/src/components/TimeDisplay.jsx @@ -1,11 +1,16 @@ import React from "react"; -export default function TimeDisplay({ primary, secondary }) { +export default function TimeDisplay({ + primary, + secondary, + className = "", + primaryClassName = "", +}) { const [main, ms] = String(primary || "").split("."); return ( -
-
+
+
{main} {ms ? .{ms} : null}
diff --git a/src/styles.css b/src/styles.css index 05ee41f..51b833f 100644 --- a/src/styles.css +++ b/src/styles.css @@ -15,17 +15,17 @@ --water-surface: rgba(255,255,255,0.24); --cta-start: #7fcf7c; --cta-pause: #e25656; - --cta-reset: #a5724b; + --cta-reset: #FF9224; } .app.mode-countdown { - --bg1: #9d6bdc; - --bg2: #6b40a4; - --bg-highlight1: rgba(255, 255, 255, 0.10); - --bg-highlight2: rgba(255, 255, 255, 0.08); - --water-top: rgba(0, 128, 255, 0.7); - --water-bottom: rgba(0, 128, 255, 0.55); - --water-surface: rgba(255,255,255,0.42); + --bg1: #02C874; + --bg2: #02C874; + --bg-highlight1: rgba(255, 255, 255, 0.12); + --bg-highlight2: rgba(255, 255, 255, 0.10); + --water-top: rgba(0, 128, 255, 0.75); + --water-bottom: rgba(0, 128, 255, 0.60); + --water-surface: rgba(255,255,255,0.50); } * { box-sizing: border-box; } @@ -170,6 +170,23 @@ a { color: inherit; } font-variant-numeric: tabular-nums; } .timeSecondary { font-size: 13px; color: var(--muted); } +.timePrimaryAlert { + color: #FF2D2D; + animation: countdownFlash 1s steps(2, start) infinite; +} +.timePrimaryAlert .timeMs { + color: #FF2D2D; +} +.countdownAlert .ringProgress, +.countdownAlert .ringTrack { + animation: countdownFlash 1s steps(2, start) infinite; + stroke: rgba(255,255,255,0.9); +} +@keyframes countdownFlash { + 0% { opacity: 1; } + 50% { opacity: 0.18; } + 100% { opacity: 1; } +} .stopwatchGrid .timerCard { max-width: 700px; @@ -218,11 +235,11 @@ a { color: inherit; } .btnPause:hover { background: #d84c4c; } .btnReset { background: var(--cta-reset); - border-color: #8b5f3f; + border-color: #f78b1f; color: #fff; - box-shadow: 0 12px 26px rgba(165, 114, 75, 0.32); + box-shadow: 0 12px 26px rgba(255, 146, 36, 0.32); } -.btnReset:hover { background: #9b6946; } +.btnReset:hover { background: #ff9f3c; } .btnLap { background: #84C1FF; border-color: #6ca7e5; @@ -262,6 +279,16 @@ a { color: inherit; } color: var(--muted2); text-align: center; } +.countdownHint { + font-size: 16px; + margin-top: 0; + margin-bottom: 12px; + color: rgba(255,255,255,0.92); +} +.countdownTools { + display: flex; + flex-direction: column; +} .laps { margin-top: 14px;