From 25027da86e48a08746a44d23450f9e73c739a798 Mon Sep 17 00:00:00 2001 From: librelad Date: Sat, 23 May 2026 01:01:01 +0100 Subject: [PATCH] style(backup): add icons to location buttons; move nebula CSS into theme folder Buttons: the per-location Save changes / Delete location buttons had no icons, unlike the apps-config action buttons. Add a save (floppy) icon and a trash icon so they match the reference; colour comes from the nebula button groups they already belong to. Theme refactor: move the theme-specific [data-theme="nebula"] button/topbar/CTA rules out of the shared css/themes.css and into themes/nebula/theme.css, where the README says theme overrides belong. css/themes.css keeps only the generic, non-theme-scoped defaults (solid status/accent buttons, danger-zone, warning-banner) shared by dark-blue/light. No behaviour change: the nebula file loads after css/themes.css so the moved rules still win. Co-Authored-By: Claude Opus 4.7 Signed-off-by: librelad --- .../libreportal/frontend/css/themes.css | 161 ------------------ .../js/components/backup/backup-page.js | 19 ++- .../frontend/themes/nebula/theme.css | 161 ++++++++++++++++++ 3 files changed, 178 insertions(+), 163 deletions(-) diff --git a/containers/libreportal/frontend/css/themes.css b/containers/libreportal/frontend/css/themes.css index d211dd3..fc25e2b 100644 --- a/containers/libreportal/frontend/css/themes.css +++ b/containers/libreportal/frontend/css/themes.css @@ -170,170 +170,9 @@ border-color: #e0a800 !important; } -/* ------------------------------------------------------------------ - Nebula-only: outline + tint buttons — copied from the .service-button - "Welcome" recipe (rgba(, 0.10) bg + rgba(, 0.30) - border + neutral text). Topbar pills use that exact alpha for the - light feel; in-content CTAs (Install/Manage/Uninstall) bump the - alphas a bit and add a subtle coloured outer glow so they feel - weightier without becoming solid. - ------------------------------------------------------------------ */ - -/* --- Topbar pills (light, transparent) --------------------------- */ -[data-theme="nebula"] .topbar .donate-btn { - background: rgba(var(--accent-rgb), 0.10) !important; - color: var(--text-primary) !important; - border: 1px solid rgba(var(--accent-rgb), 0.30) !important; - box-shadow: none !important; - text-shadow: none; - font-weight: 600; - transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease, box-shadow 0.2s ease !important; -} - -[data-theme="nebula"] .topbar .donate-btn:hover:not(:disabled) { - background: rgba(var(--accent-rgb), 0.20) !important; - border-color: rgba(var(--accent-rgb), 0.55) !important; - transform: translateY(-1px); -} - -[data-theme="nebula"] .topbar .logout-btn { - background: rgba(var(--status-danger-rgb), 0.10) !important; - color: var(--text-primary) !important; - border: 1px solid rgba(var(--status-danger-rgb), 0.30) !important; - box-shadow: none !important; - text-shadow: none; - font-weight: 600; - transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease, box-shadow 0.2s ease !important; -} - -[data-theme="nebula"] .topbar .logout-btn:hover:not(:disabled) { - background: rgba(var(--status-danger-rgb), 0.20) !important; - border-color: rgba(var(--status-danger-rgb), 0.55) !important; - transform: translateY(-1px); -} - -/* --- Topbar active nav (App Center / etc.) — translucent pill ---- - Replaces the solid var(--primary-color) fill so the active page - indicator matches the Donate / Logout pill style. */ -[data-theme="nebula"] .topbar-nav .nav-item.nav-active, -[data-theme="nebula"] .topbar-nav .nav-item.active { - background: rgba(var(--accent-rgb), 0.18) !important; - color: var(--text-primary) !important; - border-color: rgba(var(--accent-rgb), 0.50) !important; -} - -[data-theme="nebula"] .topbar-nav .nav-item.nav-active:hover, -[data-theme="nebula"] .topbar-nav .nav-item.active:hover { - background: rgba(var(--accent-rgb), 0.28) !important; - color: var(--text-primary) !important; - border-color: rgba(var(--accent-rgb), 0.70) !important; -} - -/* --- In-content CTAs (more solid than the topbar but still - transparent — alpha set above the body's accent-glow so the - brand colour reads clearly against Nebula's gradient.) ------- */ -[data-theme="nebula"] .install-btn, -[data-theme="nebula"] .btn-install, -[data-theme="nebula"] .app-card .install-btn { - background: rgba(var(--status-success-rgb), 0.55) !important; - color: var(--text-primary) !important; - border: 1px solid rgba(var(--status-success-rgb), 0.90) !important; - text-shadow: none; - font-weight: 600 !important; - transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important; -} - -[data-theme="nebula"] .install-btn:hover:not(:disabled), -[data-theme="nebula"] .btn-install:hover:not(:disabled), -[data-theme="nebula"] .app-card .install-btn:hover:not(:disabled) { - background: rgba(var(--status-success-rgb), 0.70) !important; - border-color: rgba(var(--status-success-rgb), 1.00) !important; - transform: translateY(-1px); -} - -/* "Open" button on installed app cards — same success recipe. */ -[data-theme="nebula"] .service-trigger-icon { - background: rgba(var(--status-success-rgb), 0.35) !important; - color: var(--text-primary) !important; - border: 1px solid rgba(var(--status-success-rgb), 0.65) !important; -} - -[data-theme="nebula"] .service-trigger:hover .service-trigger-icon, -[data-theme="nebula"] .service-trigger.open .service-trigger-icon { - background: rgba(var(--status-success-rgb), 0.50) !important; - border-color: rgba(var(--status-success-rgb), 0.85) !important; -} - -[data-theme="nebula"] .uninstall-btn, -[data-theme="nebula"] .btn-uninstall, -[data-theme="nebula"] .btn-danger, -[data-theme="nebula"] .backup-danger-btn { - background: rgba(var(--status-danger-rgb), 0.35) !important; - color: var(--text-primary) !important; - border: 1px solid rgba(var(--status-danger-rgb), 0.65) !important; - text-shadow: none; - font-weight: 600 !important; - transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important; -} - -[data-theme="nebula"] .uninstall-btn:hover:not(:disabled), -[data-theme="nebula"] .btn-uninstall:hover:not(:disabled), -[data-theme="nebula"] .btn-danger:hover:not(:disabled), -[data-theme="nebula"] .backup-danger-btn:hover:not(:disabled) { - background: rgba(var(--status-danger-rgb), 0.50) !important; - border-color: rgba(var(--status-danger-rgb), 0.85) !important; - transform: translateY(-1px); -} - -[data-theme="nebula"] .manage-btn, -[data-theme="nebula"] .btn-manage, -[data-theme="nebula"] .btn-primary, -[data-theme="nebula"] .backup-primary-btn, -[data-theme="nebula"] .app-card .manage-btn, -[data-theme="nebula"] .app-card-actions .manage-btn { - background: rgba(var(--accent-rgb), 0.35) !important; - color: var(--text-primary) !important; - border: 1px solid rgba(var(--accent-rgb), 0.65) !important; - text-shadow: none; - font-weight: 600 !important; - transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important; -} - -[data-theme="nebula"] .manage-btn:hover:not(:disabled), -[data-theme="nebula"] .btn-manage:hover:not(:disabled), -[data-theme="nebula"] .btn-primary:hover:not(:disabled), -[data-theme="nebula"] .backup-primary-btn:hover:not(:disabled), -[data-theme="nebula"] .app-card .manage-btn:hover:not(:disabled), -[data-theme="nebula"] .app-card-actions .manage-btn:hover:not(:disabled) { - background: rgba(var(--accent-rgb), 0.50) !important; - border-color: rgba(var(--accent-rgb), 0.85) !important; - transform: translateY(-1px); -} - -[data-theme="nebula"] .install-btn:disabled, -[data-theme="nebula"] .btn-install:disabled, -[data-theme="nebula"] .uninstall-btn:disabled, -[data-theme="nebula"] .btn-uninstall:disabled, -[data-theme="nebula"] .manage-btn:disabled, -[data-theme="nebula"] .btn-manage:disabled, -[data-theme="nebula"] .btn-primary:disabled, -[data-theme="nebula"] .btn-danger:disabled, -[data-theme="nebula"] .topbar .donate-btn:disabled, -[data-theme="nebula"] .topbar .logout-btn:disabled { - opacity: 0.50; - cursor: not-allowed; -} - /* Warning banner — amber tint that reads in every theme. */ .warning-banner { background: rgba(var(--status-warning-rgb), 0.12); border: 1px solid rgba(var(--status-warning-rgb), 0.35); color: var(--text-primary); } - -/* Nebula: the cyan accent is bright enough that a dark glyph (the - theme's text-on-accent = #0a1426) still reads, but white reads - better with the rest of nebula's white-text-on-glass system. */ -[data-theme="nebula"] .tooltip::after { - color: #ffffff; -} diff --git a/containers/libreportal/frontend/js/components/backup/backup-page.js b/containers/libreportal/frontend/js/components/backup/backup-page.js index 8a42fdc..7c76b35 100644 --- a/containers/libreportal/frontend/js/components/backup/backup-page.js +++ b/containers/libreportal/frontend/js/components/backup/backup-page.js @@ -672,8 +672,23 @@ class BackupPage {
- - + +
`; } diff --git a/containers/libreportal/frontend/themes/nebula/theme.css b/containers/libreportal/frontend/themes/nebula/theme.css index 05fa8a0..86d0efa 100644 --- a/containers/libreportal/frontend/themes/nebula/theme.css +++ b/containers/libreportal/frontend/themes/nebula/theme.css @@ -149,3 +149,164 @@ border-color: rgba(252, 165, 165, 0.65); color: #fca5a5; } + +/* ------------------------------------------------------------------ + Outline + tint buttons — copied from the .service-button "Welcome" + recipe (rgba(, 0.10) bg + rgba(, 0.30) border + + neutral text). Topbar pills use that exact alpha for the light feel; + in-content CTAs (Install/Manage/Uninstall) bump the alphas a bit and + add a subtle coloured outer glow so they feel weightier without + becoming solid. + ------------------------------------------------------------------ */ + +/* --- Topbar pills (light, transparent) --------------------------- */ +[data-theme="nebula"] .topbar .donate-btn { + background: rgba(var(--accent-rgb), 0.10) !important; + color: var(--text-primary) !important; + border: 1px solid rgba(var(--accent-rgb), 0.30) !important; + box-shadow: none !important; + text-shadow: none; + font-weight: 600; + transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease, box-shadow 0.2s ease !important; +} + +[data-theme="nebula"] .topbar .donate-btn:hover:not(:disabled) { + background: rgba(var(--accent-rgb), 0.20) !important; + border-color: rgba(var(--accent-rgb), 0.55) !important; + transform: translateY(-1px); +} + +[data-theme="nebula"] .topbar .logout-btn { + background: rgba(var(--status-danger-rgb), 0.10) !important; + color: var(--text-primary) !important; + border: 1px solid rgba(var(--status-danger-rgb), 0.30) !important; + box-shadow: none !important; + text-shadow: none; + font-weight: 600; + transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease, box-shadow 0.2s ease !important; +} + +[data-theme="nebula"] .topbar .logout-btn:hover:not(:disabled) { + background: rgba(var(--status-danger-rgb), 0.20) !important; + border-color: rgba(var(--status-danger-rgb), 0.55) !important; + transform: translateY(-1px); +} + +/* --- Topbar active nav (App Center / etc.) — translucent pill ---- + Replaces the solid var(--primary-color) fill so the active page + indicator matches the Donate / Logout pill style. */ +[data-theme="nebula"] .topbar-nav .nav-item.nav-active, +[data-theme="nebula"] .topbar-nav .nav-item.active { + background: rgba(var(--accent-rgb), 0.18) !important; + color: var(--text-primary) !important; + border-color: rgba(var(--accent-rgb), 0.50) !important; +} + +[data-theme="nebula"] .topbar-nav .nav-item.nav-active:hover, +[data-theme="nebula"] .topbar-nav .nav-item.active:hover { + background: rgba(var(--accent-rgb), 0.28) !important; + color: var(--text-primary) !important; + border-color: rgba(var(--accent-rgb), 0.70) !important; +} + +/* --- In-content CTAs (more solid than the topbar but still + transparent — alpha set above the body's accent-glow so the + brand colour reads clearly against Nebula's gradient.) ------- */ +[data-theme="nebula"] .install-btn, +[data-theme="nebula"] .btn-install, +[data-theme="nebula"] .app-card .install-btn { + background: rgba(var(--status-success-rgb), 0.55) !important; + color: var(--text-primary) !important; + border: 1px solid rgba(var(--status-success-rgb), 0.90) !important; + text-shadow: none; + font-weight: 600 !important; + transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important; +} + +[data-theme="nebula"] .install-btn:hover:not(:disabled), +[data-theme="nebula"] .btn-install:hover:not(:disabled), +[data-theme="nebula"] .app-card .install-btn:hover:not(:disabled) { + background: rgba(var(--status-success-rgb), 0.70) !important; + border-color: rgba(var(--status-success-rgb), 1.00) !important; + transform: translateY(-1px); +} + +/* "Open" button on installed app cards — same success recipe. */ +[data-theme="nebula"] .service-trigger-icon { + background: rgba(var(--status-success-rgb), 0.35) !important; + color: var(--text-primary) !important; + border: 1px solid rgba(var(--status-success-rgb), 0.65) !important; +} + +[data-theme="nebula"] .service-trigger:hover .service-trigger-icon, +[data-theme="nebula"] .service-trigger.open .service-trigger-icon { + background: rgba(var(--status-success-rgb), 0.50) !important; + border-color: rgba(var(--status-success-rgb), 0.85) !important; +} + +[data-theme="nebula"] .uninstall-btn, +[data-theme="nebula"] .btn-uninstall, +[data-theme="nebula"] .btn-danger, +[data-theme="nebula"] .backup-danger-btn { + background: rgba(var(--status-danger-rgb), 0.35) !important; + color: var(--text-primary) !important; + border: 1px solid rgba(var(--status-danger-rgb), 0.65) !important; + text-shadow: none; + font-weight: 600 !important; + transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important; +} + +[data-theme="nebula"] .uninstall-btn:hover:not(:disabled), +[data-theme="nebula"] .btn-uninstall:hover:not(:disabled), +[data-theme="nebula"] .btn-danger:hover:not(:disabled), +[data-theme="nebula"] .backup-danger-btn:hover:not(:disabled) { + background: rgba(var(--status-danger-rgb), 0.50) !important; + border-color: rgba(var(--status-danger-rgb), 0.85) !important; + transform: translateY(-1px); +} + +[data-theme="nebula"] .manage-btn, +[data-theme="nebula"] .btn-manage, +[data-theme="nebula"] .btn-primary, +[data-theme="nebula"] .backup-primary-btn, +[data-theme="nebula"] .app-card .manage-btn, +[data-theme="nebula"] .app-card-actions .manage-btn { + background: rgba(var(--accent-rgb), 0.35) !important; + color: var(--text-primary) !important; + border: 1px solid rgba(var(--accent-rgb), 0.65) !important; + text-shadow: none; + font-weight: 600 !important; + transition: background 0.18s ease, border-color 0.18s ease, transform 0.15s ease !important; +} + +[data-theme="nebula"] .manage-btn:hover:not(:disabled), +[data-theme="nebula"] .btn-manage:hover:not(:disabled), +[data-theme="nebula"] .btn-primary:hover:not(:disabled), +[data-theme="nebula"] .backup-primary-btn:hover:not(:disabled), +[data-theme="nebula"] .app-card .manage-btn:hover:not(:disabled), +[data-theme="nebula"] .app-card-actions .manage-btn:hover:not(:disabled) { + background: rgba(var(--accent-rgb), 0.50) !important; + border-color: rgba(var(--accent-rgb), 0.85) !important; + transform: translateY(-1px); +} + +[data-theme="nebula"] .install-btn:disabled, +[data-theme="nebula"] .btn-install:disabled, +[data-theme="nebula"] .uninstall-btn:disabled, +[data-theme="nebula"] .btn-uninstall:disabled, +[data-theme="nebula"] .manage-btn:disabled, +[data-theme="nebula"] .btn-manage:disabled, +[data-theme="nebula"] .btn-primary:disabled, +[data-theme="nebula"] .btn-danger:disabled, +[data-theme="nebula"] .topbar .donate-btn:disabled, +[data-theme="nebula"] .topbar .logout-btn:disabled { + opacity: 0.50; + cursor: not-allowed; +} + +/* The cyan accent is bright enough that a dark glyph (text-on-accent + = #0a1426) still reads, but white matches nebula's white-on-glass + system better. */ +[data-theme="nebula"] .tooltip::after { + color: #ffffff; +}