Add a status-bar toggle to disable the falling petals

Some people find the drifting ambient petals distracting rather than
cozy, so make the whole PetalFall layer opt-out-able from a 🌸 toggle
sitting just left of the sound toggle in the status bar.

Mirrors the existing sound-mute pattern: a tiny localStorage-backed
pub/sub (effects/petals.ts) drives a PetalsToggle twin of SoundToggle.
PetalFall subscribes to the setting, stops animating and wipes the
canvas when off, and the choice persists across reloads. Works in both
day (petals) and night (stars) modes.

Claude-Session: https://claude.ai/code/session_016Yr6jELuRc7hyzYLccQKZd
This commit is contained in:
prosolis
2026-06-26 17:27:00 -07:00
parent 4d544f29b5
commit 8be852ddf2
4 changed files with 90 additions and 3 deletions
@@ -0,0 +1,37 @@
import { useEffect, useState } from 'react'
import { isPetalsEnabled, onPetalsEnabledChange, setPetalsEnabled } from '../../effects/petals'
// A tiny toggle for Petal's ambient falling-blossom layer, sitting just left of
// the sound toggle in the status bar. Some people find the drifting petals
// distracting, so this turns them off entirely. Bilingual tooltip (she reads
// Mandarin first), and the choice persists across reloads.
export function PetalsToggle() {
const [on, setOn] = useState(isPetalsEnabled)
// Stay in sync if the setting is flipped elsewhere.
useEffect(() => onPetalsEnabledChange(setOn), [])
const toggle = () => {
const next = !on
setPetalsEnabled(next)
setOn(next)
}
return (
<button
type="button"
onClick={toggle}
aria-pressed={on}
title={on ? '花瓣开 · Petals on' : '花瓣关 · Petals off'}
aria-label={on ? 'Hide falling petals' : 'Show falling petals'}
className="flex items-center justify-center rounded-full px-2 py-1 text-xl leading-none transition-colors"
style={{ color: on ? 'var(--color-accent)' : 'var(--color-muted)', lineHeight: 1 }}
onMouseEnter={(e) => (e.currentTarget.style.color = 'var(--color-accent-hover)')}
onMouseLeave={(e) =>
(e.currentTarget.style.color = on ? 'var(--color-accent)' : 'var(--color-muted)')
}
>
<span aria-hidden>{on ? '🌸' : '🍃'}</span>
</button>
)
}
+3 -1
View File
@@ -1,6 +1,7 @@
import { Fragment, useEffect, useRef, useState } from 'react'
import type { SaveStatus } from '../../hooks/useAutoSave'
import { StatsPanel } from './StatsPanel'
import { PetalsToggle } from './PetalsToggle'
import { SoundToggle } from './SoundToggle'
interface Props {
@@ -145,7 +146,8 @@ export function StatusBar({ wordCount, text, saveStatus, checking, voicing, coll
</span>
</>
)}
<div className="ml-auto">
<div className="ml-auto flex items-center">
<PetalsToggle />
<SoundToggle />
</div>
</footer>