Skip to content

Add Bootstrap 5.3 color mode (data-bs-theme) support#435

Open
dereuromark wants to merge 6 commits into
masterfrom
feature-color-mode
Open

Add Bootstrap 5.3 color mode (data-bs-theme) support#435
dereuromark wants to merge 6 commits into
masterfrom
feature-color-mode

Conversation

@dereuromark
Copy link
Copy Markdown
Member

@dereuromark dereuromark commented May 11, 2026

Summary

Adds Bootstrap 5.3 color mode (data-bs-theme) support — the flagship BS5.3 feature that the plugin currently has zero coverage for (a grep -rn 'data-bs-theme\|color-mode' src/ templates/ webroot/ against master returns nothing).

The new ColorModeHelper provides the two pieces an app needs to actually use color modes without writing custom JS:

$this->ColorMode->script() — applies the stored theme on page load

Emits a small inline IIFE that:

  • reads the user's choice from localStorage (default key: bs-theme),
  • resolves auto against window.matchMedia('(prefers-color-scheme: dark)'),
  • sets data-bs-theme on the configured target (default: <html>),
  • re-resolves when the OS preference changes while in auto mode,
  • exposes window.BootstrapUIColorMode.{get, set}(mode) for app code,
  • dispatches a bs-theme-changed DOM event whenever the resolved theme changes.

Placed near the top of <head>, it prevents the flash of unstyled theme that every other "add dark mode in the layout" approach has.

$this->ColorMode->toggle() — ready-made switcher widget

Renders a Bootstrap btn-group with one button per configured mode (default: light / dark / auto). Clicking a button calls BootstrapUIColorMode.set(), toggles aria-pressed and the active class, and fires the event. ARIA-labelled, escapes user-supplied labels.

Usage

// Layout <head>, as early as possible:
<?= $this->ColorMode->script() ?>

// Navbar or wherever the switcher belongs:
<?= $this->ColorMode->toggle() ?>

Config knobs (per-call or via loadHelper): storageKey, default, target, modes, labels, ariaLabel, wrapperClass, buttonClass, activeClass. Labels go through __() if you pass them through; the helper itself escapes them.

Wiring

  • New class: src/View/Helper/ColorModeHelper.php
  • Auto-loaded by UIViewTrait as $this->ColorMode.
  • @property added to UIView docblock.
  • README has a new section under Usage explaining usage, public JS API, and config keys.

Notes

  • This is a feature, not a fix. Independent of Fix five real defects in helpers and console commands #434 (bug-fix PR) — either can land first.
  • No new asset files; the JS is inlined so apps don't have to ship a separate file or symlink anything new.
  • No changes to existing helpers — purely additive.
  • Existing layouts/examples still ship neutral CSS classes like bg-light/text-dark in places; those are not touched here. A follow-up could audit templates/layout/examples/* and FlashHelper.php for hardcoded neutrals if you want full dark-mode parity in the bundled layouts.

A new ColorModeHelper provides the two pieces that have been
missing for color-mode adoption since the BS5.3 migration:

- `script()` emits an inline IIFE that reads the user's stored
  preference from localStorage (falling back to the OS preference
  for `auto`), applies `data-bs-theme` to the configured target
  (default `<html>`), re-resolves on `prefers-color-scheme`
  changes while in auto mode, and exposes a tiny public API
  (`window.BootstrapUIColorMode.{get,set}` plus a
  `bs-theme-changed` DOM event). Placed in `<head>` it prevents
  the flash of unstyled theme.
- `toggle()` renders a Bootstrap button group with one button per
  configured mode. Clicks call `BootstrapUIColorMode.set()`,
  update the active state, and announce the change via the event.

Configurable: storageKey, default, target, modes, labels (i18n
hook via `__()`), ariaLabel, wrapperClass, buttonClass,
activeClass.

The helper is auto-loaded by `UIViewTrait` as `$this->ColorMode`.
README has a new "Color modes" section under Usage.

Tests cover default and custom-config rendering for both methods
and verify user-supplied labels are HTML-escaped.
Comment thread src/View/Helper/ColorModeHelper.php Outdated
Per review: extract the three string constants (MODE_LIGHT,
MODE_DARK, MODE_AUTO) into a BootstrapUI\View\Helper\ColorMode
enum. The helper's `default` and `modes` config keys now accept
either enum cases or plain strings interchangeably, so existing
apps that pass `'light'` / `'dark'` / `'auto'` keep working while
new code can use the typed API.

A small `_modeValue()` helper coerces a value to its string form
for places that render or serialize.

Updates the README example to use the enum and notes that strings
are still accepted. Adds tests covering enum usage on both
`modes` and `default`.
@dereuromark
Copy link
Copy Markdown
Member Author

Addressed in 2112231. Extracted the three string constants into a BootstrapUI\View\Helper\ColorMode backed-string enum. The helper's default and modes config keys accept either enum cases or plain strings interchangeably so existing apps that pass 'light'/'dark'/'auto' keep working, while new code can use the typed API:

use BootstrapUI\View\Helper\ColorMode;

echo $this->ColorMode->toggle([
    'modes' => [ColorMode::Light, ColorMode::Dark],
    'default' => ColorMode::Dark,
]);

A small _modeValue() helper coerces either form to its string value for rendering. README updated with the enum import. Two new tests cover enum usage on both modes and default.

Comment thread src/View/Helper/ColorModeHelper.php Outdated
ColorMode now implements Cake's EnumLabelInterface and provides its own
translated label() — matches FormHelper's enum-label convention and removes
the now-redundant 'labels' config on the helper. Custom string modes still
fall back to ucfirst().
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants