librelad aef0c15726 refactor(webui/backups): backup center sub-tabs use canonical tabs-wrapper
The embedded backup center's fragment kept its standalone-page skeleton
(.container + .sidebar restyled by a pile of overview.css overrides).
.container's fixed viewport height inflated the Backups tab pane to
~100vh, stretching the pane surface far past the content and under the
footer buttons, and the restyled strip never matched the app-detail
Config sub-tabs.

Rebuild backup-content.html on the canonical sub-tab idiom instead —
.tabs-wrapper > .tabs-list (emoji tab-buttons) + .tabs-content card,
with a .backup-actions footer below the card mirroring .config-actions.
The bespoke overview.css restyle block, the nebula special-cases, the
embed's id-stripping and BackupPage's dead page-header updater all fall
away; the export menu now opens upward from the footer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
2026-07-04 21:08:03 +01:00
..

Custom Themes

Drop a folder here named after your theme and refresh the browser — the topbar dropdown will pick it up automatically.

Minimum

frontend/themes/<your-name>/
  theme.css       (required) — palette inside a [data-theme="<your-name>"] block
  meta.json       (optional) — { "displayName": "Pretty Name", "author": "you" }

The folder name (<your-name>) becomes the data-theme value. Use lowercase + dashes — no spaces, no slashes.

Tokens

Copy frontend/themes/example/theme.css as a starting point. Every CSS variable defined there is what style.css and friends consume — change the values, keep the names.

The visible-essentials list (override these at minimum):

Token What it controls
--surface-bg Body background (gradient or solid)
--text-primary Default text colour
--accent Theme's signature colour (manage btn)
--accent-rgb Same colour as r,g,b for rgba() mixes
--text-rgb 255,255,255 (dark) or 0,0,0 (light)
--bg-rgb The opposite of --text-rgb

Status colours (--status-success, --status-danger, --status-warning, --status-info) are usually safe to leave as the defaults — they're brand-stable across themes.

How discovery works

On page load the frontend calls GET /api/themes/list. The backend walks this directory, returns one entry per folder containing a theme.css, and the frontend (js/system/theme-registry.js) injects each entry's CSS into <head> and adds it to the topbar dropdown. The currently-saved theme is <link>-loaded synchronously by the inline bootstrap in index.html so first paint has the right palette — no flash.

The built-in themes (nebula, dark-blue, light) live in this folder too — their meta.json files set "builtin": true so a future UI can distinguish them (e.g. a "reset to built-ins" affordance). If you delete a built-in folder you'll remove it from the dropdown; the app survives but the deleted theme is gone until you put it back.

The dropdown orders themes by:

  1. nebula, dark-blue, light (built-ins, in that fixed order)
  2. Everything else, sorted by display name.