Files
mainty/docs/superpowers/plans/2026-05-17-theme-toggle-topbar.md
T

13 KiB

Theme Toggle Top-Bar Relocation Implementation Plan

For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Move the light/dark toggle from floating right-side UI into top-bar controls (left of settings), with consistent visibility and behavior across all user-facing views.

Architecture: Introduce one reusable controls partial (topbar-controls.php) that owns toggle/settings markup, then reuse it from each page header. Keep theme state logic centralized in theme.php while removing floating positioning and binding behavior to the top-bar toggle IDs. Update all templates in views/*.php to ensure complete coverage and consistent top-bar placement.

Tech Stack: PHP 8+, server-rendered views, Tailwind CDN utilities, Bootstrap Icons, cookie-based theme persistence.


File Structure and Responsibilities

  • Create: views/partials/topbar-controls.php
    • Single responsibility: render top-bar controls (theme toggle always, settings link optionally).
  • Modify: views/partials/theme.php
    • Single responsibility: theme token CSS + initialization + toggle behavior script.
    • Remove floating button markup/CSS; keep runtime toggle logic.
  • Modify: views/index.php
    • Use shared top-bar controls in existing header with settings visible.
  • Modify: views/vehicle.php
    • Use shared top-bar controls in existing header with settings visible.
  • Modify: views/settings.php
    • Use shared top-bar controls in existing header with settings hidden.
  • Modify: views/login.php
    • Add slim top header + controls; preserve centered login card in main content area.
  • Modify: views/setup.php
    • Add slim top header + controls; preserve centered setup card in main content area.
  • Modify: views/export.php
    • Add theme partial includes and slim top header + controls, preserving export content.

Chunk 1: Shared Controls + Theme Engine Refactor

Task 1: Add reusable top-bar controls partial

Files:

  • Create: views/partials/topbar-controls.php

  • Step 1: Write topbar-controls.php with explicit include API defaults

<?php
$showSettings = isset($showSettings) ? (bool) $showSettings : false;
$settingsUrl = isset($settingsUrl) ? (string) $settingsUrl : url('/settings');
?>
<div class="flex items-center space-x-4">
    <button
        id="themeToggle"
        type="button"
        class="bg-blue-600 hover:bg-blue-700 text-white p-2 rounded-lg shadow-sm transition"
        aria-label="Switch to dark mode"
        title="Switch to dark mode"
        aria-pressed="false"
    >
        <i id="themeToggleIcon" class="bi bi-moon-stars-fill" aria-hidden="true"></i>
    </button>

    <?php if ($showSettings): ?>
        <a href="<?php echo htmlspecialchars($settingsUrl); ?>" class="theme-text-muted hover:opacity-95">
            <i class="bi bi-gear-fill text-2xl" aria-hidden="true"></i>
            <span class="sr-only">Settings</span>
        </a>
    <?php endif; ?>
</div>

<noscript>
    <style>
        #themeToggle {
            display: none !important;
        }
    </style>
</noscript>
  • Step 2: Run syntax check for new partial

Run: php -l views/partials/topbar-controls.php Expected: No syntax errors detected in views/partials/topbar-controls.php

  • Step 3: Commit partial addition
git add views/partials/topbar-controls.php
git commit -m "feat: add reusable top-bar controls partial"

Task 2: Refactor theme.php to stop rendering floating toggle

Files:

  • Modify: views/partials/theme.php

  • Step 1: Remove floating toggle CSS rules and keep focus-visible styling

Replace floating positioning block with only focus-visible rule:

#themeToggle:focus-visible {
    outline: 3px solid #2563eb;
    outline-offset: 2px;
}
  • Step 2: Remove body-section button markup and keep JS behavior block

Delete the button HTML + <noscript> block from if ($themeSection === 'body') and keep only the script that binds to #themeToggle and #themeToggleIcon.

  • Step 3: Keep graceful missing-element guard and aria/icon sync

Ensure this remains present near script start:

if (!toggleButton || !toggleIcon) {
    return;
}
  • Step 4: Run syntax check for theme partial

Run: php -l views/partials/theme.php Expected: No syntax errors detected in views/partials/theme.php

  • Step 5: Commit theme refactor
git add views/partials/theme.php
git commit -m "refactor: detach theme toggle UI from theme partial"

Chunk 2: View Integration + Cross-View Verification

Task 3: Integrate shared controls into existing authenticated headers

Files:

  • Modify: views/index.php

  • Modify: views/vehicle.php

  • Modify: views/settings.php

  • Step 1: Replace direct settings icon block in views/index.php

Use shared controls in header:

<?php $showSettings = true; include __DIR__ . '/partials/topbar-controls.php'; ?>
  • Step 2: Replace direct settings icon block in views/vehicle.php

Use shared controls in header:

<?php $showSettings = true; include __DIR__ . '/partials/topbar-controls.php'; ?>
  • Step 3: Replace direct settings icon block in views/settings.php

Use shared controls in header without self-link:

<?php $showSettings = false; include __DIR__ . '/partials/topbar-controls.php'; ?>
  • Step 4: Run syntax checks for updated authenticated templates

Run: php -l views/index.php && php -l views/vehicle.php && php -l views/settings.php Expected: three No syntax errors detected lines.

  • Step 5: Commit authenticated-header integration
git add views/index.php views/vehicle.php views/settings.php
git commit -m "refactor: reuse top-bar controls in authenticated headers"

Task 4: Add top headers and controls to login/setup/export

Files:

  • Modify: views/login.php

  • Modify: views/setup.php

  • Modify: views/export.php

  • Step 1: Update views/login.php body layout for top bar + centered main

Target structure:

<body class="theme-page min-h-screen">
    <header class="theme-surface shadow-sm">
        <div class="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
            <a href="<?php echo url('/home'); ?>" class="text-2xl font-bold theme-text hover:opacity-95 transition"><?php echo APP_NAME; ?></a>
            <?php $showSettings = false; include __DIR__ . '/partials/topbar-controls.php'; ?>
        </div>
    </header>

    <main class="min-h-[calc(100vh-72px)] flex items-center justify-center px-4 py-8">
        <!-- existing login card -->
    </main>

    <?php $themeSection = 'body'; include __DIR__ . '/partials/theme.php'; ?>
</body>

Must preserve unchanged in views/login.php:

  • Existing flash message blocks.

  • Existing login form action/inputs/button labels.

  • Existing themeSection = 'body' include placement (moved below new main only if needed).

  • Step 2: Apply same top-bar pattern to views/setup.php

Target structure:

<body class="theme-page min-h-screen">
    <header class="theme-surface shadow-sm">
        <div class="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
            <a href="<?php echo url('/home'); ?>" class="text-2xl font-bold theme-text hover:opacity-95 transition"><?php echo APP_NAME; ?></a>
            <?php $showSettings = false; include __DIR__ . '/partials/topbar-controls.php'; ?>
        </div>
    </header>

    <main class="min-h-[calc(100vh-72px)] flex items-center justify-center px-4 py-8">
        <!-- existing setup card + requirement messages -->
    </main>

    <?php $themeSection = 'body'; include __DIR__ . '/partials/theme.php'; ?>
</body>

Must preserve unchanged in views/setup.php:

  • System requirements panel and PHP/SQLite checks.

  • Setup form action/field names/validation markers.

  • Existing error/validation message blocks.

  • Step 3: Add theme head include to views/export.php

In <head>, add:

<?php $themeSection = 'head'; include __DIR__ . '/partials/theme.php'; ?>
  • Step 4: Add slim top header with shared controls in views/export.php

Near start of <body>, add header:

<header class="theme-surface shadow-sm">
    <div class="max-w-7xl mx-auto px-4 py-4 flex justify-between items-center">
        <a href="<?php echo url('/home'); ?>" class="text-2xl font-bold theme-text hover:opacity-95 transition"><?php echo APP_NAME; ?></a>
        <?php $showSettings = false; include __DIR__ . '/partials/topbar-controls.php'; ?>
    </div>
</header>
  • Step 5: Apply theme layout classes in views/export.php

Make these concrete class updates while preserving content hierarchy:

  • Change <body class="bg-white p-8"> to <body class="theme-page min-h-screen">.

  • Wrap export content in a <main class="max-w-4xl mx-auto px-4 py-8"> container beneath the new header.

  • Change the vehicle info panel container from bg-gray-50 to theme-surface and add theme-border where bordered surfaces are used.

  • Keep export typography/content layout unchanged unless required for theme contrast.

  • Step 6: Add theme body include to views/export.php

Before </body>, add:

<?php $themeSection = 'body'; include __DIR__ . '/partials/theme.php'; ?>
  • Step 7: Run syntax checks for login/setup/export templates

Run: php -l views/login.php && php -l views/setup.php && php -l views/export.php Expected: three No syntax errors detected lines.

  • Step 8: Commit public/export header integration
git add views/login.php views/setup.php views/export.php
git commit -m "feat: surface theme toggle in top bar across public and export views"

Task 5: End-to-end verification of requirements

Files:

  • Verify runtime behavior only (no file creation)

  • Step 1: Run full changed-file syntax sweep

Run:

php -l views/partials/topbar-controls.php
php -l views/partials/theme.php
php -l views/index.php
php -l views/vehicle.php
php -l views/settings.php
php -l views/login.php
php -l views/setup.php
php -l views/export.php

Expected: all files report no syntax errors.

  • Step 2: Manual runtime verification checklist (JS enabled)

Validate in browser:

  • /home, /vehicles/{id}, /settings, /login, /setup, and /vehicles/{id}/export/html (export page in current routes)

  • Toggle is visible in top bar in every view.

  • In views with settings, toggle appears immediately left of settings icon.

  • Theme changes immediately and persists after reload/navigation.

  • Confirm on both desktop and mobile widths that header controls remain visible and usable.

  • Confirm route-to-view coverage by checking all files in views/*.php render topbar-controls.php directly or through a shared header partial (index, vehicle, settings, login, setup, export).

  • Confirm export route parity: top-bar controls are present without breaking export content rendering.

  • Confirm settings icon is hidden on pages using $showSettings = false (/settings, /login, /setup, /vehicles/{id}/export/html).

  • Step 3: Deterministic coverage verification for templates

Run:

grep -n "topbar-controls.php" views/index.php views/vehicle.php views/settings.php views/login.php views/setup.php views/export.php

Expected:

  • Command prints one include line in each required template file.

  • Each required template renders top-bar controls (direct include in this plan; if a shared header partial is introduced later, update this check accordingly).

  • Step 4: Manual runtime verification (JS disabled)

Validate in browser devtools/no-script mode:

  • #themeToggle is hidden (noscript rule works).

  • Layout remains usable and header spacing is not broken.

  • Expected: no major layout shift or overlap in header controls.

  • Step 5: Manual fallback verification for cookie-write failure

Validate by blocking cookies in browser tools or private profile:

  • Toggle still switches theme in current session/view.

  • Reload may revert to resolved default/system theme when cookie persistence is unavailable.

  • No JavaScript errors in console during toggle interaction.

  • Expected: theme updates immediately on click even without persistence.

  • Step 6: Commit final polish/fixes from verification (only if changes were needed)

git add views/partials/theme.php views/partials/topbar-controls.php views/index.php views/vehicle.php views/settings.php views/login.php views/setup.php views/export.php
git commit -m "fix: finalize top-bar theme toggle behavior and cross-view consistency"

If no files changed during verification, skip commit and mark this step complete.

Implementation Notes

  • Keep changes DRY and YAGNI: no additional theme modes, no storage changes, no route/controller changes.
  • Use @superpowers/test-driven-development discipline where possible in this codebase by keeping each change small and verified immediately with syntax + targeted manual checks.
  • Before claiming completion, run @superpowers/verification-before-completion checks (syntax + required manual coverage).