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

358 lines
13 KiB
Markdown

# 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
<?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**
```bash
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:
```css
#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:
```js
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**
```bash
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
<?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
<?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
<?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**
```bash
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:
```php
<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:
```php
<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
<?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:
```php
<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
<?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**
```bash
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:
```bash
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:
```bash
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)**
```bash
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).