Skip to content

Slice 9 — Themes (Classic, Energetic, Plain) (#10) - #31

Merged
cbaucom merged 3 commits into
mainfrom
feat/10-themes-classic-energetic-plain
Jun 11, 2026
Merged

cbaucom merged 3 commits into
mainfrom
feat/10-themes-classic-energetic-plain

Conversation

@cbaucom

@cbaucom cbaucom commented Jun 11, 2026 •

Copy link
Copy Markdown
Owner

Closes #10

Summary

  • Adds three theme presets as pure data (THEMES record in timeline-core/settings.ts): Classic (crossfade, Ken Burns, 4s), Energetic (cut, Ken Burns zoom-in-only, 2s), Plain (cut, no Ken Burns, 5s)
  • kenBurnsMode?: 'alternate' | 'zoom-in-only' added to GlobalSettings; planner selects zoom-in-only KB presets when set
  • applyTheme(name) returns a fresh copy of the theme settings
  • Theme selector UI (3 buttons) in GlobalSettingsPanel; active theme highlighted; manual settings edit clears active selection
  • themeName persisted in slideshow.json and restored on project open

Acceptance criteria

  • Given each theme applied, when played, then global behavior matches its definition — verified by unit tests on THEMES presets (transition type, Ken Burns, pacing) and by Playwright smoke check confirming settings panel updates correctly
  • Switching themes is non-destructive to per-slide overrides — themes only replace globalSettings; per-slide overrides are untouched
  • Given Plain theme, when played, then there are zero transitions and zero motion, images hold exactly the configured duration, and videos play as-is — THEMES.plain = { transitionType: 'cut', kenBurns: false, imageDurationSecs: 5 }; verified by unit test and planner behavior; HITL aesthetics sign-off required before merge
  • HITL: owner reviews each theme on a real photo/video set and signs off on aesthetics

Approach

Themes are purely data — no special-cased code paths. A theme is a GlobalSettings object; applying one calls setGlobalSettings(applyTheme(name)) (full replacement, not merge), so no stale fields survive a theme switch. kenBurnsMode flows through the existing resolve() cascade.

Code review verdict

APPROVE — zero blocking findings from --effort high review. Both candidate concerns (stale kenBurnsMode on theme switch, invalid themeName crash on load) were REFUTED: theme application does a full state replacement, and applyTheme is never called during project load.

Screenshot

Theme selector visible in settings panel; Energetic active (blue highlight), Transition = Cut, Duration = 2s:

Theme selector

Follow-ups noted

  • No UI control to set kenBurnsMode independently of themes (zoom-in-only is only reachable via Energetic theme); fine for v1 since it's an aesthetic preference

cbaucom and others added 3 commits June 10, 2026 23:29
…tings.

- THEMES record and applyTheme() in timeline-core/settings
- KenBurnsMode type with 'zoom-in-only' for Energetic theme
- Planner selects zoom-in-only KB presets when mode is set

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Schema: themeName persisted in slideshow.json
- App: tracks theme state, applies theme settings on selection
- GlobalSettingsPanel: three-button theme picker with active highlight
- Switching individual settings clears active theme selection

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cbaucom
cbaucom merged commit d9e18a3 into main Jun 11, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Slice 9 — Themes (Classic, Energetic, Plain)

1 participant