diff options
Diffstat (limited to 'docs/superpowers')
| -rw-r--r-- | docs/superpowers/specs/2026-09-17-sddm-theme-udt-panel-design.md | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/docs/superpowers/specs/2026-09-17-sddm-theme-udt-panel-design.md b/docs/superpowers/specs/2026-09-17-sddm-theme-udt-panel-design.md new file mode 100644 index 0000000..3a87677 --- /dev/null +++ b/docs/superpowers/specs/2026-09-17-sddm-theme-udt-panel-design.md @@ -0,0 +1,238 @@ +# sddm-theme-udt, Left Panel Redesign + +Date: 2026-09-17 +Status: approved, not yet implemented + +This spec supersedes the greeter layout and interaction sections of +`2026-09-17-sddm-theme-udt-design.md` (the centered login card, its single +password flow and its power bar placement). Every other decision there, the +palette, the live `theme.conf.user` tracking, the per-window screen model, the +idle fade, the security model and the colour names, still stands. + +## Goal + +Replace the centered login card with a full-height panel pinned to the left +edge, about 30% of the screen width, blurred underneath. Top to bottom the +panel carries a clock and date, a configurable greeting, the avatar, a single +credential slot that advances from username to password, a row of power +buttons, and the session selector pinned to the bottom. The power button icons +follow the icon theme selected in the `appearance` drawer instead of the four +bundled SVGs, falling back to the bundled set when the theme has no match. + +## Problem + +The current greeter is one card floating in the middle of the screen. It shows +username and password side by side, which is more fields than the flow needs, +and its power icons are fixed line art that does not match the desktop's +selected icon theme. The user asked for a left panel with a staged login and +theme-following power icons. + +## Decisions + +1. **Left panel, flush, square.** The panel is anchored to the left, top and + bottom edges of its greeter window, `panelWidth` of the window width, with + no rounded corners and no left margin. A 2px `accent` border runs along the + exposed edges. The background under it is frosted with the existing + `Backdrop` (wallpaper snapshot, blur, tint), masked to the panel rectangle + with radius 0. Rejected: a detached card with rounded corners and margins + (the user asked for a panel flush to the edge and without rounding). + +2. **One credential slot, two stages.** A single field slot shows the username + first. Confirming it slides the username out to the left and the password in + from the right. Confirming the password logs in. The two fields are never + visible at once, so the slot reads as one control that advances. Rejected: + keeping both fields stacked (the behaviour the redesign replaces). + +3. **Touch-reachable confirm and back.** Besides Enter, each stage has a + confirm arrow button. The password stage also shows a back chevron that + returns to the username, keeping its text. Rejected: Enter-only (a touch + user could not advance) and Esc-only back (the same, for touch). + +4. **Power icons resolved by `udt-accent` from gsettings.** The icon theme name + is read from `org.gnome.desktop.interface icon-theme` while `udt-accent` runs + as the login user. Absolute paths to the four resolved SVGs are written into + the generated `~/.local/share/udt/sddm-theme.conf`, next to the palette, so + the greeter stays data-only and never reads a file. Empty values fall back to + the bundled `theme/icons/*.svg`. Rejected: reading `qt6ct.conf` or gsettings + from inside the greeter (the greeter runs as `sddm`, has no `QML` file-read + API and no user dconf); resolving FreeDesktop icon lookup in QML (fragile, + and the theme spec's decision 1 already closed the file-read path). + +5. **Icon theme switching is picked up on the next `udt-accent` run.** A + wallpaper change already runs it. Switching the icon theme in the drawer + does not, so a manually triggered `udt-accent` is needed until the drawer is + wired to call it. Recorded as a TODO in the quickshell repository rather than + solved here. + +6. **Kept from the original design.** Palette and live tracking through + `theme.conf.user`; one greeter window per screen with the panel shown only + where `uiScreen` matches, else on the primary window; the 1s clock is the + only new timer; `fadeoutMs` idle hide and input wake; `blur`; + `EnableAvatars`; the security argument that the only user-writable input is + INI data. + +## Architecture + +``` +wallpaper change + wallp -> udt-accent <image> + extracts + snaps accent, reads gsettings icon-theme, + resolves the four power icon paths, then writes + ~/.local/share/udt/sddm-theme.conf (0644, world-readable) + palette keys + powerIcon / rebootIcon / suspendIcon / hibernateIcon + (absolute paths, empty when unresolved) + +greeter start (as sddm), one window per screen + reads theme.conf + theme.conf.user into `config` + wallpaper fills the window + panel, blurred, on the uiScreen window only +``` + +The root install block is unchanged. Re-running the root copy is only needed +when theme code changes. + +## Panel layout + +Anchored inside the panel (`panelWidth` wide, 32px horizontal padding): + +| position | element | detail | +| --- | --- | --- | +| top | time | `Text`, `timeFormat` (default `HH:mm`), large | +| | date | `Text`, `dateFormat` (default `dddd, d MMMM`), `subtext0` | +| | greeting | `Text`, `greeting` (default `hello there`) | +| | avatar | 96px circle, `accent` ring, face from `userModel`, initials fallback, centered | +| | credential slot | one field, staged, with confirm arrow and back chevron | +| | message | login failure (`red`) or Caps Lock hint (`yellow`) | +| flexible gap | | | +| bottom | power row | four buttons, centered, ~40px icons on 56px targets | +| bottom | session selector | full panel width, pinned to the bottom edge | + +The clock refreshes from a 1s `Timer` into a `now` property, formatted with +`Qt.formatDateTime(now, fmt)`. + +## Credential flow + +- `stage` is `user` or `pass`. +- `user`: username field prefilled with `userModel.lastUser`; the avatar + reflects the current text. Confirm with Enter or the arrow, ignored when + empty, advances to `pass`. +- Transition: username slides to `-slot.width` and fades, password slides from + `slot.width` to 0, 220ms `OutCubic`. The slot clips. The avatar remains and + follows the confirmed username. +- `pass`: password field focused. Confirm with Enter or the arrow calls + `sddm.login(username, password, sessionBox.currentIndex)`. +- Back: Esc on the password field or the back chevron returns to `user` and + keeps the username; the password is cleared. +- Failure: `sddm.loginFailed` clears the password, shows `Login failed` in + `red`, shakes the panel, and stays in `pass`. Caps Lock shows in `yellow`. +- Idle hide and wake are unchanged; wake focuses the field for the current + stage. + +## Config + +Added to the root `theme.conf` with these defaults, overridden live in the +generated `theme.conf.user`: + +| key | default | meaning | +| --- | --- | --- | +| `panelWidth` | `0.30` | panel width as a fraction of the window width | +| `timeFormat` | `HH:mm` | Qt time format string | +| `dateFormat` | `dddd, d MMMM` | Qt date format string | +| `greeting` | `hello there` | greeting line | +| `powerIcon` | (empty) | absolute path to the shutdown icon | +| `rebootIcon` | (empty) | absolute path to the restart icon | +| `suspendIcon` | (empty) | absolute path to the sleep icon | +| `hibernateIcon` | (empty) | absolute path to the hibernate icon | + +Unchanged: the palette keys, `uiScreen`, `fadeoutMs`, `blur`. + +`udt-accent` gains the four icon keys in its emitted key list and writes the +resolved paths. `theme.conf` keeps them empty so a missing or unreachable icon +falls back to the bundled SVG. + +## Icon resolution in `udt-accent` + +1. Read the icon theme name: + `gsettings get org.gnome.desktop.interface icon-theme`, strip quotes. An + empty or failed read leaves every icon key empty. +2. FreeDesktop names, with fallbacks: + - shutdown: `system-shutdown` + - restart: `system-reboot` + - sleep: `system-suspend` + - hibernate: `system-hibernate`, then `system-suspend-hibernate` +3. Search `~/.local/share/icons/<theme>` then `/usr/share/icons/<theme>` for + `<name>.svg` or `<name>-symbolic.svg`. Prefer a `symbolic` hit, then the + largest size directory; a plain recursive search with that ordering is + enough and avoids parsing `index.theme`. +4. Write the absolute path, or leave the key empty when nothing matches. + +Icons are drawn as a flat silhouette through the existing `MultiEffect` +colorization (`subtext0`, `accent` on hover), so the theme icon contributes its +shape; the UDT palette still supplies the colour. + +## Files touched + +This repository: + +- `theme/Main.qml`: swap `LoginCard` for `Panel`; panel geometry per window. +- `theme/components/Panel.qml` (new): layout, clock, greeting, avatar, power + row, session selector, shake, idle wiring. +- `theme/components/Credentials.qml` (new): the staged slot and its animation. +- `theme/components/PowerBar.qml`: read the four config paths, bundled + fallback, larger targets. +- `theme/components/LoginCard.qml`: deleted. +- `theme/theme.conf`: new keys. +- `README.md`: describe the panel and the new keys. + +Other repositories: + +- `unified-desktop-theme/bin/udt-accent`: add the four icon keys to the emitted + INI, add the resolver, extend `--selftest`. +- `quickshell/TODO.md`: record that the appearance drawer should run + `udt-accent` when the icon theme changes, so the greeter follows without a + wallpaper change. + +## Testing + +- `unified-desktop-theme/bin/udt-accent --selftest`: the emitted INI contains + every key including the four icon keys; with a known theme name the resolver + returns an existing readable path for each icon; an unknown theme leaves the + keys empty. This is the runnable check for the new logic. +- `sddm-greeter-qt6 --test-mode --theme <repo>/theme`: layout, blur, clock, + greeting, staged field, power icon shapes, session selector. +- `sudo -u sddm test -r <resolved icon>` for one resolved path, confirming the + greeter user can read the theme's icons. +- Confirm the generated INI still carries every palette key, so the palette + path is unregressed. + +## Risks + +- **Icon theme switch lag.** Until the quickshell TODO lands, a new icon theme + reaches the greeter at the next wallpaper change or manual `udt-accent` run. +- **`gsettings` unavailable.** If the read fails, all four keys are empty and + the bundled icons draw. Cosmetic only. +- **A theme without the expected names.** Some themes omit a symbolic variant + or use different names; the fallback list and the bundled set cover the + common cases, and the worst case is the bundled icon. +- **`panelWidth` on very wide screens.** A 30% fraction can be wide. It is a + config key, so it can be lowered without a code change. +- **Date locale in the greeter.** `Qt.formatDateTime` uses the greeter's + locale, which may be `C`. If the date must be localized, a future + `QLocale`-based format or a fixed numeric format can be added. +- **Blur needs a working GL context**, as before; the tint alone still reads. + +## Out of scope + +- Wiring the appearance drawer to run `udt-accent` on icon change (TODO only). +- Bundling or installing fonts. +- Displays other than SDDM. +- Light schemes and per-scheme artwork. + +## Development Approach + +This project is developed using AI-assisted tools. Code is generated with the help of AI based on human-provided specifications, design decisions, and iterative feedback. + +All contributions are reviewed, tested, and curated by the maintainer before being included in the codebase. AI is used as a productivity and exploration tool, while human oversight remains central to all decisions. + +The goal is to combine the flexibility of AI-assisted development with standard open-source practices such as transparency, review, and accountability. |
