Idle Blinds Design
Summary
Lower the LiveWindow blinds when chat goes idle; raise them when the user becomes active again. On initial load, the blinds open via the same openBlinds() path (replacing the current one-shot runAnimation logic).
Event Flow
- Site-wide idle manager dispatches events —
BaseLayout.tscreates a site-wide idle manager that firessite:idleandsite:activecustom events ondocument. - Homepage script listens —
index.astro’s script block listens forsite:idleandsite:activeondocument, callscloseBlinds()/openBlinds()on the<live-window>element. - LiveWindow delegates —
LiveWindowElementexposes publiccloseBlinds()andopenBlinds()methods that delegate toBlindsComponent.
BlindsComponent Changes
New public API
openBlinds()— runs the existing two-step open animation (rotate slats open, then collapse upward). Called on initial load and when chat becomes active.closeBlinds()— smooth simultaneous animation:numBlindsCollapsed → 0(uncollapse all slats) andblindsOpenDeg → 20(rotate flat/closed). All slats move at once.- Track
isOpenboolean to prevent redundant animations and cancel in-flight animations when direction changes.
Cleanup
- Remove the
animationStartedflag and theupdate()trigger. The initial load path inLiveWindow.startUpdates()callsopenBlinds()directly instead. runAnimation()becomes the internal implementation ofopenBlinds().- The
stepAnimationhelper stays — both open and close use it.
Files Modified
app/src/scripts/idle-manager.ts+app/src/layouts/BaseLayout/BaseLayout.ts— site-wide idle manager dispatchingsite:idle/site:activecustom events ondocumentapp/src/scripts/live-window/components/BlindsComponent.ts— addopenBlinds()/closeBlinds(), removeanimationStartedflag, trackisOpenstateapp/src/scripts/live-window/LiveWindow.ts— expose publiccloseBlinds()/openBlinds(), callopenBlinds()instartUpdates()app/src/pages/index.astro— listen forsite:idle/site:active, call methods on<live-window>