179 lines
9.6 KiB
Markdown
179 lines
9.6 KiB
Markdown
# Lumi UI and theme system
|
|
|
|
Lumi UI is the project-native design layer used by every page rendered through the
|
|
shared EJS layout. It keeps route behavior and page-specific JavaScript separate
|
|
from visual tokens and reusable components.
|
|
|
|
## Files
|
|
|
|
- `src/web/public/lumi-tokens.css`: semantic colors, spacing, radii, shadows,
|
|
typography, compatibility aliases, and reduced-motion behavior.
|
|
- `src/web/public/lumi-layout.css`: application shell, sidebar, content
|
|
containers, responsive grids, stacks, clusters, and mobile navigation.
|
|
- `src/web/public/lumi-components.css`: buttons, forms, cards, tables, lists,
|
|
badges, alerts, tabs, modals, empty/loading/error states, stateful action
|
|
buttons, and tooltips.
|
|
- `src/web/public/lumi-state-button.js` and
|
|
`src/web/views/partials/state-button.ejs`: reusable multi-state button
|
|
behavior for submit/loading/success actions.
|
|
- `src/web/public/lumi-interactions.js`: progressive interaction layer for
|
|
server-sent events, no-auto-refresh notices, dirty settings save bars,
|
|
expandable settings containers, refresh prompts, and soft navigation.
|
|
- `src/services/web-events.js`: small role-aware Server-Sent Events bus exposed
|
|
at `GET /api/events` for authenticated users.
|
|
- `src/web/public/styles.css`: legacy and feature-specific styles that still use
|
|
the shared tokens. New general-purpose styling belongs in the Lumi UI files.
|
|
- `src/web/views/partials/page-header.ejs`: standard page title and description.
|
|
- `src/web/views/partials/theme-vars.ejs`: safe active-theme variables for shell
|
|
and standalone pages.
|
|
- `src/services/themes.js`: built-in themes, custom theme CRUD, validation,
|
|
migration, fallback handling, and active-theme selection.
|
|
|
|
Use `lumi-stack`, `lumi-cluster`, `lumi-split`, `lumi-grid`, `page-header`,
|
|
`button-group`, `card`, `panel`, `table-wrap`, `empty-state`, `loading-state`,
|
|
and `status-indicator` before adding one-off layout rules. Preserve existing IDs,
|
|
field names, data attributes, and JavaScript hooks when restyling a page.
|
|
|
|
## Interaction Rules
|
|
|
|
Pages should not self-refresh for state or progress changes. Core connection
|
|
recovery now displays a notice instead of calling `window.location.reload()`.
|
|
Server-originated events use `GET /api/events` with explicit event names such as
|
|
`server:status`, `server:warning`, `ai:model_status`, and
|
|
`data:new_available`. Admin-only events must be published with `{ role: "admin" }`.
|
|
|
|
List/data updates should announce that new data exists and show a refresh prompt.
|
|
The shared refresh prompt uses a 3-second cooldown before another refresh can be
|
|
requested. It does not replace list contents automatically.
|
|
|
|
Forms that represent page settings should add `data-lumi-settings-form`.
|
|
Action-only forms must not use that attribute. The shared dirty-state layer
|
|
tracks original values, marks changed fields with theme-aware unsaved styling,
|
|
shows a top Save changes bar, warns before accidental navigation, and clears
|
|
markers only after successful saves.
|
|
|
|
Expandable settings rows use `data-lumi-expandable-settings` on a `<details>`
|
|
container. Preview text can be wired with `data-placeholder-preview="#field-id"`;
|
|
known placeholders such as `{gifter_username}`, `{item_name}`,
|
|
`{creator_username}`, and `{amount_display}` render with plausible sample values
|
|
without changing the saved template.
|
|
|
|
Soft navigation progressively enhances same-origin links by replacing
|
|
`main.content`, updating history, and fading content in place. If a fetch fails,
|
|
JavaScript is unavailable, or unsaved settings are present, navigation falls back
|
|
to normal browser behavior.
|
|
|
|
## Themes
|
|
|
|
Lumi ships with six read-only themes: Lumi Default, Lumi Dark, Lumi Light, High
|
|
Contrast, Midnight, and Soft Aurora. Admins select them from **Admin > Theming**.
|
|
Built-in themes cannot be renamed, edited, or deleted.
|
|
|
|
Open a theme's **More actions** section and duplicate it to create an editable
|
|
custom theme. Custom themes can be previewed in light and dark mode, saved,
|
|
applied globally, renamed, duplicated, or deleted. Deleting the active custom
|
|
theme falls back to Lumi Default.
|
|
|
|
The compact editor exposes common colors first. Advanced controls cover
|
|
background glows, raised surfaces, links, buttons, inputs, focus rings, radius,
|
|
shadow strength, and spacing scale. Typography controls use constrained font
|
|
presets plus bounded base-size, heading-scale, and control-density ranges. The
|
|
server accepts only six-digit hex colors, supported font presets, bounded metric
|
|
values, and readable text/button/input contrast.
|
|
|
|
Draft values are isolated to preview roots. The compact preview and pop-out
|
|
preview update colors, role colors, metrics, spacing, and typography before
|
|
save, but the editor shell and live site keep the active saved theme until the
|
|
admin saves/applies the custom theme. The compact preview is hidden on narrow
|
|
phone layouts; use the Preview action to open the synchronized pop-out instead.
|
|
|
|
The compact preview includes representative headings, pills, cards, buttons,
|
|
state buttons, inputs, toggles, alerts/statuses, badges, tables, modal samples,
|
|
dirty-state markers, and spacing samples. The pop-out uses a faithful Lumi page
|
|
shell with safe sample data so admins can test draft themes against dashboard,
|
|
settings, logs, AI, and component-like layouts without exposing real admin data.
|
|
|
|
Missing or invalid stored values are replaced from the custom theme's built-in
|
|
base. Existing installations with modified legacy `theme_light_*`,
|
|
`theme_dark_*`, or `theme_role_*` settings are migrated once into a custom
|
|
**Migrated Theme** and selected automatically. The legacy `/admin/theming` POST
|
|
route remains supported and writes into an editable custom theme.
|
|
|
|
Run `npm run verify:webui` to compile every EJS view and exercise built-in theme
|
|
validation plus custom duplicate, apply, edit validation, typography validation,
|
|
stateful theme actions, localhost login rendering, rename, and delete.
|
|
|
|
## Localhost Login
|
|
|
|
Development builds opened from `localhost`, `127.0.0.1`, or `::1` show a
|
|
**Localhost Login** option. It defaults to username `admin` and password `admin`
|
|
unless those settings have already been changed. The option is not inserted into
|
|
the login list, cannot be used, and does not satisfy setup requirements for
|
|
non-localhost requests.
|
|
|
|
Admins can change the localhost username and password from **Admin > Settings**
|
|
when the settings page itself is accessed through localhost. Leaving the
|
|
password field blank keeps the existing password.
|
|
|
|
## Lumi AI Settings And Feedback
|
|
|
|
Lumi AI's main Selected model dropdown lists only installed/downloaded models.
|
|
If the configured model is missing, the settings page shows a warning and saving
|
|
requires selecting an installed model. Main context, gate context, and output
|
|
token budgets use shared presets from Tiny (256) through Extra extended
|
|
(32768). Unsupported freeform values are rejected server-side.
|
|
|
|
AI feedback supports `feedback_kind` values `strict_correction` and
|
|
`instruction_based`; instruction-based feedback is the default because most
|
|
reviews are guidance for future replies rather than exact replacement answers.
|
|
Feedback tags include `wrong_tool_usage` for cases where the model called the
|
|
wrong tool or failed to call an expected tool. Review, edit, and implementation
|
|
views show both the kind and tag so admins can tell direct answer corrections
|
|
from broader tool-calling or instruction guidance.
|
|
|
|
Model/runtime downloads and the combined Start/Restart runtime control use the
|
|
Lumi state button behavior. Enhanced browsers start downloads and runtime
|
|
actions through fetch, update button state/progress in place, and avoid hard
|
|
page refreshes; the underlying POST routes remain available for non-JavaScript
|
|
fallbacks.
|
|
|
|
## Homepage Content
|
|
|
|
Admins configure homepage external link buttons from Admin > Settings with the
|
|
Homepage content builder. It writes the existing `homepage_link_buttons` JSON
|
|
setting behind the scenes. Each entry may include `enabled`, `label`,
|
|
`description`, `url`, `icon_url`, `permission` (`public`, `user`, `mod`,
|
|
`admin`), and `sort_order`. Links open in a new tab with
|
|
`rel="noopener noreferrer"` and are filtered server-side by permission.
|
|
|
|
Admins configure priority-based hero entries with the same builder; it writes
|
|
the existing `homepage_hero_entries` JSON setting behind the scenes. The
|
|
homepage renders the first enabled, available entry the current user can access.
|
|
Hero entries support type, priority/order, permission, source/embed/image URLs,
|
|
video IDs, availability mode, autoplay mode metadata, and duration fields. Slow
|
|
external availability checks are intentionally avoided; entries fail closed if
|
|
required local configuration is missing.
|
|
|
|
## Admin Dashboard And Logs
|
|
|
|
The admin dashboard polls `GET /api/admin/dashboard-metrics` for process
|
|
uptime, memory, plugin counts, content counts, and recent log severity totals.
|
|
The dashboard renders lightweight SVG graphs using Lumi tokens and does not add
|
|
a frontend framework dependency.
|
|
|
|
The logs page keeps server-side range/severity/limit filters and adds a labeled
|
|
responsive filter bar with search, reset, refresh, and download actions. Search
|
|
filters the loaded entries client-side; changing range, severity, or limit
|
|
reloads the same `/admin/logs` route with query parameters.
|
|
|
|
## Visual references
|
|
|
|
- [Home, desktop](screenshots/lumi-home-desktop.png)
|
|
- [Home, 360px mobile](screenshots/lumi-home-mobile.png)
|
|
- [Custom theme editor, desktop](screenshots/lumi-theme-editor-desktop.png)
|
|
- [Custom theme editor, 360px mobile](screenshots/lumi-theme-editor-mobile.png)
|
|
|
|
The broad sidebar and content structure remains in place. Theme controls moved
|
|
from one long raw color form into the Theme Studio library and grouped custom
|
|
editor; no navigation destination or non-theme control was relocated.
|