Skip to content

Themes: allow multiple active at once; default site theme is opt-in (checkbox) - #312

Merged
WebTigers merged 2 commits into
mainfrom
feat/theme-multi-active-default
Sep 25, 2026
Merged

WebTigers merged 2 commits into
mainfrom
feat/theme-multi-active-default

Conversation

@WebTigers

Copy link
Copy Markdown
Owner

What

Activating a theme no longer deactivates the others. Multiple themes can be active at once (their layouts/assets stay available for pages to use); which one is the default site theme is a separate, opt-in choice.

This is the fix for: "You cannot have two default themes. Keep both active. Add a checkbox: Make [name] the default theme. Only switch if checked." It also supersedes the Flag-3 "multiple active is unpredictable" notice (#311) — multiple active is now the normal, supported case.

Root cause

A theme's "active" state was the single tiger.theme config value, so activating theme B (tiger.theme = B) structurally made A stop matching — an implicit, unavoidable deactivation. Now:

  • "Active" = the module active flag (like every module) — multiple allowed.
  • "Default site theme" = tiger.theme (one), the chrome for / and any page that doesn't pick its own layout.

Changes

  • Tiger_Theme::activate($slug, $makeDefault = true) — always links assets; sets tiger.theme only when $makeDefault (default true preserves the headless installer's behavior).
  • System_Service_Modules::_toggleTheme — maintains the module flag (setActive) and passes make_default through; _isModuleActive (delete guard) reads the flag.
  • ModulesController — theme "active" = the flag; exposes is_default.
  • Modules view — on theme Activate, a confirm with a "Make [name] the default site theme" checkbox (pre-checked only when nothing is default yet); make_default=1 sent only when ticked. A "Default" badge marks the current default theme.
  • tiger.modal.js — TigerModal.confirm gains an optional checkbox: { label, checked }; with it, confirm resolves { confirmed, checked } (backward-compatible — a bare boolean without it).

Proof

  • Client: the shipped handleToggle sends make_default only when the box is ticked (JS harness, 3/3).
  • Server (dev): activate A (default) → activate B without the box → both active, default stays A; activate C (default) → A+B+C active, default C; deactivate the default → default cleared, others stay active.

Follow-up (not in this PR)

Phase 2: per-page layout selection so a page can render in any active theme's layout (today themeContentAction/PageController resolve only the default theme). This PR makes multiple themes active; picking a non-default theme's layout per page is the next step.

🤖 Generated with Claude Code

https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ

WebTigers and others added 2 commits September 25, 2026 12:38
Activating a theme no longer deactivates the others. A theme's "active" state is now the
same module flag every module uses (multiple can be active, their layouts/assets available);
which one is the DEFAULT site theme is the separate `tiger.theme` config, changed only on
request. This replaces the "one active theme per scope" behavior (activating one silently
replaced the previous), and supersedes the Flag 3 "multiple active is unpredictable" notice
(#311) — multiple active is now the normal, supported case.

- library/Tiger/Theme.php: `activate($slug, $makeDefault = true)` — always links assets; sets
  `tiger.theme` only when $makeDefault (default true keeps the headless installer's behavior).
- modules/system/services/Modules.php: `_toggleTheme` maintains the module active flag (setActive)
  and passes `make_default` through to `Tiger_Theme::activate`; `_isModuleActive` (delete guard)
  reads the flag like any module.
- modules/system/controllers/ModulesController.php: theme "active" = the flag; exposes `is_default`
  (the theme whose key == tiger.theme).
- modules/system/views/scripts/modules/index.phtml: on theme Activate, a confirm with a
  "Make <name> the default site theme" CHECKBOX (pre-checked only when nothing is default yet);
  only sends make_default=1 when ticked. A "Default" badge marks the current default theme.
- themes/puma/assets/js/tiger.modal.js: TigerModal.confirm gains an optional `checkbox: {label,
  checked}` — with it, confirm resolves { confirmed, checked } (backward-compatible; without it,
  a bare boolean as before).

Proven: the shipped handleToggle sends make_default only when the box is ticked (JS harness), and
the server keeps every theme active while moving the default only on request (dev: activate B
without the box → A and B both active, default stays A; deactivating the default clears it).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
The theme-activation semantics changed (Themes: allow multiple active): activating a theme
sets the module active FLAG (multiple can be active) and writes tiger.theme only when
make_default is set; Tiger_Theme::activate() returns a 'default' flag. Bring the integration
tests to the new contract.

- ModulesServiceThemeTest: activating sets the flag and does NOT change the default unless
  make_default is passed; deactivating the default clears the flag + tiger.theme.
- ThemeActivateTest: activate() return array now carries 'default' => true.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ASauLLscjqdsNqBNsx2Typ
@WebTigers
WebTigers merged commit b1f5429 into main Sep 25, 2026
14 checks passed
@WebTigers
WebTigers deleted the feat/theme-multi-active-default branch September 25, 2026 19:10
@WebTigers WebTigers mentioned this pull request Sep 26, 2026
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.

1 participant