358 lines
13 KiB
Markdown
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).
|