Phase 14: bedtime nag + night mode (dark theme + falling stars)
Companion warmth: - ENCOURAGEMENTS grown 5->10; new BEDTIME lines (warm/playful, zh-first) - useCompanion heartbeat gains a bedtime branch (>=11pm, while actively writing) gated by a 30min cooldown; new 'bedtime' BubbleTone paces it Night mode (auto at ~11pm, local clock): - lib/night.ts centralizes isBedtime() + the window, shared with the nag - useNightMode toggles a `petal-night` class on <html>; index.css re-points only the palette tokens, so every Tailwind color utility flips via var() with no component edits (600ms dusk fade; print stays white) - PetalFall gains a `night` prop: chunky cartoon power stars (makeCartoonStar, 5 candy colors) mixed ~70/30 with twinkle sparkles; each star spins at its own rate (~0.5-2.2 rad/s, random direction), falls straight down, shimmers Verified: go vet/test, tsc, vitest 51/51, vite build; real-browser screenshots/video (clock mocked to 23:30). Claude-Session: https://claude.ai/code/session_016Yr6jELuRc7hyzYLccQKZd
This commit is contained in:
25
web/src/hooks/useNightMode.ts
Normal file
25
web/src/hooks/useNightMode.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { isBedtime } from '../lib/night'
|
||||
|
||||
// Tracks whether it's late enough to shift Petal into its calm night mode (dark
|
||||
// theme + falling stars instead of petals). Re-checks once a minute so the swap
|
||||
// happens on its own as the clock rolls past 11pm — no reload needed. Returns
|
||||
// the boolean and also toggles a `petal-night` class on <html> so the CSS token
|
||||
// overrides cascade to everything (body background, panels, portals included).
|
||||
export function useNightMode(): boolean {
|
||||
const [night, setNight] = useState(() => isBedtime())
|
||||
|
||||
useEffect(() => {
|
||||
const tick = () => setNight(isBedtime())
|
||||
tick()
|
||||
const id = setInterval(tick, 60_000)
|
||||
return () => clearInterval(id)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
document.documentElement.classList.toggle('petal-night', night)
|
||||
return () => document.documentElement.classList.remove('petal-night')
|
||||
}, [night])
|
||||
|
||||
return night
|
||||
}
|
||||
Reference in New Issue
Block a user