Better theme experience - #2088
Conversation
fix conslole error when not on dhcp page
Rename base.css to all.css and optimize import
…matting, variable declarations, and event handling
Staticize default style, extracting dynamic parts
Remove Unused
ThemeColor -> User selected color (done); ThemeMode -> light / dark / system (WIP); Theme -> A Full set stlye (default / HackerNews / etc...) (WIP)
There was a problem hiding this comment.
Pull request overview
This PR refactors the theming system to separate shared styles from theme-specific styles, introduce a “theme mode” (light/dark/system) that can follow the browser preference, and consolidate default/dark theme styling into a single CSS theme file.
Changes:
- Loads a new shared stylesheet (
app/css/base.css) globally and introduces a cookie-driven theme-mode mechanism (data-theme-mode→ resolved todata-bs-themein JS). - Replaces the PHP-generated theme CSS with static theme CSS (
default.css) plus a small PHP CSS endpoint for theme color variables (theme-color.php). - Updates theme settings UI, theme assets (SVG/PHP images), and reformats/cleans several JS/CSS/Python files.
Reviewed changes
Copilot reviewed 21 out of 27 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| templates/system/theme.php | Updates theme settings UI (theme color input class rename). |
| index.php | Switches theme attribute wiring and adds global base/theme stylesheets (contains a broken stylesheet link). |
| includes/system.php | Adjusts theme list to use css filenames and passes selected theme to template. |
| includes/navbar.php | Replaces night-mode toggle with a theme-mode click target/icon placeholder. |
| includes/functions.php | Adds getThemeMode(), renames theme color accessor, updates theme cookie defaults. |
| CONTRIBUTING.md | Heading reformat (still contains a typo in body text). |
| composer.lock | Adds dependency lockfile. |
| app/pitft/stats.py | Formatting and minor command quoting cleanup. |
| app/js/vendor/speedtestUI.js | Formatting (retains/introduces a data = null state bug). |
| app/js/vendor/huebee.js | Updates Huebee binding and moves theme color cookie name to theme-color. |
| app/js/vendor/dashboardchart.js | Formatting cleanup. |
| app/js/vendor/bandwidthcharts.js | Formatting cleanup. |
| app/js/ui/main.js | Adds theme switching/mode resolution logic and XSS escaping for some UI templates (theme select handler currently broken). |
| app/js/ajax/main.js | Minor whitespace cleanup. |
| app/img/solid.php | Uses new getThemeColorOpt() for SVG stroke coloring. |
| app/img/right-solid.php | Uses new getThemeColorOpt() for SVG stroke coloring. |
| app/img/raspAP-logo.php | Uses new getThemeColorOpt() for logo coloring. |
| app/img/devices/zero.php | Uses new getThemeColorOpt() for device SVG stroke. |
| app/img/devices/default.php | Uses new getThemeColorOpt() for device SVG stroke. |
| app/img/devices/compute.php | Uses new getThemeColorOpt() for device SVG stroke. |
| app/css/theme-color.php | New PHP CSS endpoint that defines --raspap-theme-color and variants. |
| app/css/hackernews.css | Removes theme import and reformats rules. |
| app/css/default.css | New consolidated default theme CSS (includes dark-mode selectors). |
| app/css/dark.css | Removed (dark styling moved into default.css). |
| app/css/custom.php | Removed (replaced by static default.css + theme-color.php). |
| app/css/base.css | Renamed/refactored shared CSS and adds theme-mode icon pseudo-content. |
| .gitignore | Ignores vendor/. |
Comments suppressed due to low confidence (1)
app/css/base.css:742
- For the
systemmode icon you setcontent: "\f042"on#theme-mode-icon::before, but\f042(Font Awesomeadjust) is only present in the solid font (fa-solid-900). The element currently uses thefar(regular) style, so the glyph may not render. Either switch the icon element to the solid style (e.g., usefas/fa-solidor set an appropriatefont-weight), or pick asystemicon that exists in the regular set.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| <!-- Custom CSS --> | ||
| <link rel="stylesheet" href="app/css/base.css?v=<?= filemtime('app/css/base.css'); ?>"> | ||
| <link rel="stylesheet" href="app/css/theme-color.php'); ?>"> |
There was a problem hiding this comment.
The stylesheet link tag for theme-color.php has malformed PHP/quotes (href="app/css/theme-color.php'); ?>"), which will generate invalid HTML and prevent the theme color variables from loading. Update this to a valid href (and consider adding a cache-busting ?v= like the other assets).
| <link rel="stylesheet" href="app/css/theme-color.php'); ?>"> | |
| <link rel="stylesheet" href="app/css/theme-color.php?v=<?= filemtime('app/css/theme-color.php'); ?>"> |
There was a problem hiding this comment.
Origin custom.php was loaded with no such query, should this add it?
| $themeColor = getThemeColorOpt(); | ||
| ?> | ||
|
|
||
| :root { | ||
| --raspap-theme-color: <?php echo htmlspecialchars($themeColor, ENT_QUOTES, 'UTF-8'); ?>; | ||
| --raspap-theme-color-lighter: <?php echo htmlspecialchars(lightenColor($themeColor, 20), ENT_QUOTES, 'UTF-8'); ?>; | ||
| --raspap-theme-color-darker: <?php echo htmlspecialchars(darkenColor($themeColor, 20), ENT_QUOTES, 'UTF-8'); ?>; |
There was a problem hiding this comment.
theme-color.php computes lighter/darker variants via lightenColor() / darkenColor(), but getThemeColorOpt() currently allows non-hex formats (e.g., rgb(...), named colors). The lighten/darken helpers assume a #RRGGBB string and will produce incorrect results or warnings for other formats. Either constrain getThemeColorOpt() to validated hex only, or add conversion logic before calling the helpers and fall back safely when conversion isn’t possible.
| $themeColor = getThemeColorOpt(); | |
| ?> | |
| :root { | |
| --raspap-theme-color: <?php echo htmlspecialchars($themeColor, ENT_QUOTES, 'UTF-8'); ?>; | |
| --raspap-theme-color-lighter: <?php echo htmlspecialchars(lightenColor($themeColor, 20), ENT_QUOTES, 'UTF-8'); ?>; | |
| --raspap-theme-color-darker: <?php echo htmlspecialchars(darkenColor($themeColor, 20), ENT_QUOTES, 'UTF-8'); ?>; | |
| /** | |
| * Normalize a CSS color string to a #RRGGBB hex color if possible. | |
| * Returns the normalized hex string or null if the input is not a hex color. | |
| * | |
| * This ensures we only pass valid hex colors to lightenColor()/darkenColor(). | |
| * | |
| * @param string $color | |
| * @return string|null | |
| */ | |
| function normalizeHexColorOrNull($color) | |
| { | |
| if (!is_string($color)) { | |
| return null; | |
| } | |
| $color = trim($color); | |
| // Match #RGB or #RRGGBB (case-insensitive) | |
| if (!preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/', $color, $matches)) { | |
| return null; | |
| } | |
| $hex = ltrim($matches[0], '#'); | |
| // Expand 3-digit hex (#RGB) to 6-digit (#RRGGBB) | |
| if (strlen($hex) === 3) { | |
| $hex = $hex[0] . $hex[0] | |
| . $hex[1] . $hex[1] | |
| . $hex[2] . $hex[2]; | |
| } | |
| return '#' . strtoupper($hex); | |
| } | |
| $themeColor = getThemeColorOpt(); | |
| $themeColorHex = normalizeHexColorOrNull($themeColor); | |
| ?> | |
| :root { | |
| --raspap-theme-color: <?php echo htmlspecialchars($themeColor, ENT_QUOTES, 'UTF-8'); ?>; | |
| --raspap-theme-color-lighter: <?php echo htmlspecialchars($themeColorHex !== null ? lightenColor($themeColorHex, 20) : $themeColor, ENT_QUOTES, 'UTF-8'); ?>; | |
| --raspap-theme-color-darker: <?php echo htmlspecialchars($themeColorHex !== null ? darkenColor($themeColorHex, 20) : $themeColor, ENT_QUOTES, 'UTF-8'); ?>; |
| <label class="form-check-label" id="theme-mode"> | ||
| <i id="theme-mode-icon" class=" far mr-1 text-muted"></i> | ||
| </label> |
There was a problem hiding this comment.
The theme mode control is rendered as a <label> with a click handler but no associated form control, button semantics, or keyboard support. This is not accessible (screen readers won’t announce it as a control, and keyboard users may not be able to toggle it). Consider using a <button type="button"> (or add role="button", tabindex="0", and key handlers) and provide an aria-label describing the current/next mode.
| <label class="form-check-label" id="theme-mode"> | |
| <i id="theme-mode-icon" class=" far mr-1 text-muted"></i> | |
| </label> | |
| <button type="button" class="form-check-label btn btn-link p-0" id="theme-mode" aria-label="Toggle theme mode"> | |
| <i id="theme-mode-icon" class=" far mr-1 text-muted"></i> | |
| </button> |
Co-authored-by: Copilot <[email protected]>
#2087
Text Below Generated By AI
This pull request makes significant improvements to the project's CSS structure and theme management, focusing on modularizing and modernizing the stylesheets. The main changes include splitting and refactoring the CSS files for better maintainability, updating theme variable usage, and cleaning up the documentation.
Key changes:
CSS Refactoring and Theming
all.csstobase.css, and its formatting was improved for readability and consistency. The newbase.cssis now more maintainable and easier to update. [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14]custom.phpstylesheet was removed, and its contents were replaced by a staticdefault.cssfile. This change simplifies theme management and removes server-side CSS generation. [1] [2]default.css, and the standalonedark.cssfile was removed. This consolidates theme logic and ensures all theme styles are managed in a single file. [1] [2]hackernews.csstheme was updated to import frombase.cssinstead of the removedall.css, ensuring consistency with the new structure. [1] [2]Documentation
CONTRIBUTING.mdfile was updated for clarity and formatting, making it easier for new contributors to get started. [1] [2]These changes collectively improve the maintainability, clarity, and scalability of the project's frontend architecture.