docs: update launcher design for profile and server actions
Document the profile settings added to the launcher design and the new Start Server detail action. The settings contract now includes a persisted username and language choice, and the game detail overlay shows Start Server only for installed games that can host a dedicated server. The reference mock now includes the matching Profile controls, a server icon, server-capable sample catalog entries, and the updated detail/settings artboards so implementation can follow the selected design direction. Test Plan: - git diff --cached --check Refs: design/README.md
This commit is contained in:
+75
-13
@@ -32,6 +32,14 @@ The HTML mock includes two chrome variants — **A (single-row)** and **B (two-r
|
||||
|
||||
---
|
||||
|
||||
## Changes since v1
|
||||
|
||||
- **Settings → Profile section** added at the top of the dialog with two new persisted preferences: **Username** (text input) and **Language** (segmented `English` / `Deutsch`). See "Settings dialog" below for shape + persistence keys.
|
||||
- **Start Server** action added to the **game detail overlay**, next to **Play**, for installed games that support a dedicated server. Driven by a new `canHostServer: true` flag on the game record. See "Detail overlay → Actions row" and "Game data shape" for the full spec.
|
||||
- Grid cards are **unchanged** — Start Server only ever appears in the detail overlay.
|
||||
|
||||
---
|
||||
|
||||
## Screens / views
|
||||
|
||||
### 1. Main library (variant A — primary)
|
||||
@@ -88,12 +96,26 @@ Opens when the user **clicks anywhere on a game card except the action button**.
|
||||
2. **Body** — 22px top, 26px bottom, 28px horizontal:
|
||||
- **Meta grid** — 4-column CSS grid, 12px gap. Each cell: `padding 10px 12px`, `background rgba(255,255,255,0.025)`, `1px solid var(--bd-1)`, `border-radius: 8px`. Cells (in order): `Size` (e.g. 8.2 GB), `Players` (icon + range), `Version` (mono, e.g. 2018.04.12), `Status` (Installed / Local / Not downloaded).
|
||||
- **Description** — 14px / 1.55 line-height, `var(--t-2)`, `text-wrap: pretty`, `max-width: 64ch`.
|
||||
- **Actions row** — flex row, 10px gap, 4px top padding:
|
||||
- Primary action button (44px tall, see "Action button" below — Play / Install / Download depending on state)
|
||||
- If `state === 'installed'`: ghost-button **Uninstall** — 44px, `background rgba(255,255,255,0.04)`, `1px solid var(--bd-2)`, `border-radius: 8px`, text `#f87171`, trash icon. On hover: bg `rgba(239,68,68,0.10)`, border `rgba(239,68,68,0.40)`, text `#fca5a5`.
|
||||
- If `state === 'local'`: ghost-button **Delete from disk** (same danger styling).
|
||||
- Spacer (`flex: 1`).
|
||||
- Ghost-button **View files** (neutral) — opens system file manager at the game folder.
|
||||
- **Actions row** — flex row, 10px gap, 4px top padding. Order, left → right:
|
||||
1. **Primary action button** (44px tall, see "Action button" below — Play / Install / Download depending on state).
|
||||
2. **Start Server** — *only* when `game.canHostServer === true` **and** `state === 'installed'`. Same 44px height as Play, but visually a peer secondary action (see "Start Server button" below). Triggers a Tauri command that spawns the game's dedicated-server executable in headless mode against the local LAN (port + server config out of scope here — leave a `startServer(gameId)` IPC stub).
|
||||
3. If `state === 'installed'`: ghost-button **Uninstall** — 44px, `background rgba(255,255,255,0.04)`, `1px solid var(--bd-2)`, `border-radius: 8px`, text `#f87171`, trash icon. On hover: bg `rgba(239,68,68,0.10)`, border `rgba(239,68,68,0.40)`, text `#fca5a5`.
|
||||
4. If `state === 'local'`: ghost-button **Delete from disk** (same danger styling).
|
||||
5. If `state === 'downloading'`: ghost-button **Cancel** (same danger styling).
|
||||
6. Spacer (`flex: 1`).
|
||||
7. Ghost-button **View files** (neutral) — opens system file manager at the game folder.
|
||||
|
||||
#### Start Server button
|
||||
|
||||
A secondary-but-equal action that sits next to **Play**. The intent is to read as a host-action ("I want to put this game on the LAN") without competing with the green Play button for the player's primary attention.
|
||||
|
||||
- Same shape and height as Play: 44px tall, `border-radius: 8px`, `font 14px / 600`, 8px gap between icon and label, padding `0 22px`.
|
||||
- Surface: `background: color-mix(in srgb, var(--accent) 14%, rgba(255,255,255,0.04))`, `border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent)`, `box-shadow: inset 0 1px 0 rgba(255,255,255,0.06)`. Text in `--t-1`.
|
||||
- **Icon** in `--accent`: a small server-rack glyph (two stacked rounded rectangles each with an LED dot and a hint of wiring). 13×13. SVG in `components.jsx → Icon.server`.
|
||||
- Hover: `background: color-mix(in srgb, var(--accent) 22%, ...)`, border darkens to `color-mix(... 75%, transparent)`. Active: `transform: scale(0.98)` (shared with `.act-btn`).
|
||||
- A future *running* state (live indicator dot + "Server running" label + click-to-stop) is **not** in this round — flag as a follow-up when wiring the real spawn.
|
||||
|
||||
The button is purposefully **not** present on game cards in the grid — hosting a server is intentional and benefits from the context of the detail overlay (player count, version, etc.). Don't add it to cards.
|
||||
|
||||
---
|
||||
|
||||
@@ -108,10 +130,20 @@ Opens when the user clicks **Settings** from the kebab menu. Same modal-scrim tr
|
||||
│ Settings [×] │ ← head: 22 28 18, 1px bottom border
|
||||
├─────────────────────────────────────────┤
|
||||
│ │
|
||||
│ APPEARANCE │ ← section title: 10.5px / 700 / 0.12em / uppercase / --t-3
|
||||
│ PROFILE │ ← section title (new): 10.5px / 700 / 0.12em / uppercase / --t-3
|
||||
│ │
|
||||
│ Accent color │ ← row label: 14px / 600 / --t-1
|
||||
│ Used for primary actions and highlights │ ← row hint: 12px / --t-3
|
||||
│ Username │ ← row label: 14px / 600 / --t-1
|
||||
│ Shown to other players on the LAN │ ← row hint: 12px / --t-3
|
||||
│ [ Enter a username ] │ ← text input (220×36)
|
||||
│ │
|
||||
│ Language │
|
||||
│ Interface language │
|
||||
│ [English│Deutsch] │ ← segmented radio (new)
|
||||
│ │
|
||||
│ APPEARANCE │
|
||||
│ │
|
||||
│ Accent color │
|
||||
│ Used for primary actions and highlights │
|
||||
│ ⬤⬤⬤⬤⬤⬤ │ ← 6 swatches, right-aligned
|
||||
│ │
|
||||
│ Background │
|
||||
@@ -138,6 +170,11 @@ Opens when the user clicks **Settings** from the kebab menu. Same modal-scrim tr
|
||||
- Left (`settings-row-info`): label (14px / 600 / `--t-1`) + hint (3px-top, 12px / `--t-3`)
|
||||
- Right (`settings-row-control`): the control
|
||||
|
||||
**Profile section** (new in this round). Two rows, rendered **above** Appearance — it's the most personal/identity-shaped setting so it's the first thing the user sees in Settings.
|
||||
|
||||
- **Username** — `<input type="text">` wrapped in a styled container: 220px wide, 36px tall, `background var(--bg-3)`, `1px solid var(--bd-1)`, `border-radius: 8px`, `padding: 0 12px`. Input itself is transparent/borderless, `font 13.5px / 600`, color `--t-1`, placeholder `"Enter a username"` in `--t-3` / 500. `maxLength={24}`, `spellCheck={false}`. On focus the container gets `background var(--bg-2)`, border `var(--accent)`, and an accent focus ring `box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent)`.
|
||||
- **Language** — same segmented-radio control as Background / Density / Cover aspect, with two options: `English` (value `'en'`) and `Deutsch` (value `'de'`). Active option gets the accent fill, same as the other segmented radios.
|
||||
|
||||
**Color swatch picker:** flex row of 8px-gapped buttons. Each swatch is 32×32, `border-radius: 9px`, no border. Inside, a 100% × 100% rounded-8 colored dot with inset shadow `0 0 0 1px rgba(255,255,255,0.08)`. Hover: dot scales 1.06. **Active**: dot has ring `box-shadow: 0 0 0 2px var(--bg-2), 0 0 0 4px <swatch-color>` and shows a centered white check icon with drop-shadow `0 1px 2px rgba(0,0,0,0.5)`.
|
||||
|
||||
Six accent options: Blue `#3b82f6`, Cyan `#22d3ee`, Violet `#a855f7`, Green `#22c55e`, Amber `#f59e0b`, Red `#ef4444`.
|
||||
@@ -147,6 +184,8 @@ Six accent options: Blue `#3b82f6`, Cyan `#22d3ee`, Violet `#a855f7`, Green `#22
|
||||
**Done button:** filled button in `--accent`, 36px tall, 13.5px / 600. Closes the dialog.
|
||||
|
||||
Persisted settings (write through to local storage / Tauri config):
|
||||
- `username`: string, max 24 chars. Default `"Commander"` (placeholder — feel free to default to the OS username on first run). Used as the network identity for LAN sessions; the hint copy *"Shown to other players on the LAN"* tells the user what it does.
|
||||
- `language`: `'en'` | `'de'`. Default `'en'`. Drives an i18n layer (introduce one if it doesn't exist yet — `react-i18next` or similar). Initial copy is English-only in the mock; German translations need to be added as part of implementation. Recommend detecting the OS locale on first run and defaulting to `'de'` if the system language starts with `de`.
|
||||
- `accent`: one of the six hex values above. Default `#3b82f6`.
|
||||
- `bg`: `flat` | `gradient` | `animated`. Default `gradient`.
|
||||
- `density`: `compact` | `normal` | `large`. Default `normal`.
|
||||
@@ -363,12 +402,16 @@ type Game = {
|
||||
state: 'installed' | 'local' | 'downloading' | 'none';
|
||||
progress?: number; // 0–1 — present only when state === 'downloading'
|
||||
speed?: number; // MB/s — present only when state === 'downloading'
|
||||
peers?: number; // LAN peers currently seeding
|
||||
players: string; // e.g. "2–32"
|
||||
tags: string[];
|
||||
cover: { c1: string; c2: string; accent: string; mood?: string };
|
||||
canHostServer?: boolean; // true if the game ships with a dedicated-server binary
|
||||
};
|
||||
```
|
||||
|
||||
**Server-capable games** in the mock catalog (`canHostServer: true`): BF1942, BF2, CoD2, CoD4, CoD:UO, CS 1.6, CS:Source, Cube 2/Sauerbraten, Doom 3, L4D2, Minecraft, Quake III, TF2, UT2004. RTS / social-deduction / co-op-only-P2P games (AoE II HD, RA3, Generals ZH, Among Us, Portal 2, StarCraft, Warcraft III, AvP, 8-Bit Armies, BlazeRush) are not flagged — they host in-game. In production the flag should come from the same per-game manifest that drives titles / sizes / cover art. Wire each entry to whatever launch command the dedicated server uses (`hldsexec`, `srcds`, `minecraft_server.jar`, etc.); the IPC stub looks like `startServer(gameId)` returning a handle or process id.
|
||||
|
||||
**UI state:**
|
||||
```ts
|
||||
type LauncherUI = {
|
||||
@@ -380,7 +423,19 @@ type LauncherUI = {
|
||||
};
|
||||
```
|
||||
|
||||
**Persisted settings:** see Settings dialog section. Persist via Tauri's plugin-store or a local JSON file in app data dir.
|
||||
**Persisted settings** (mirror of Settings dialog state):
|
||||
```ts
|
||||
type LauncherSettings = {
|
||||
username: string; // new
|
||||
language: 'en' | 'de'; // new
|
||||
accent: string; // hex from the curated 6-color palette
|
||||
bg: 'flat' | 'gradient' | 'animated';
|
||||
density: 'compact' | 'normal' | 'large';
|
||||
aspect: 'box' | 'square' | 'banner';
|
||||
};
|
||||
```
|
||||
|
||||
Persist via Tauri's plugin-store or a local JSON file in app data dir. Changes from the Settings dialog should write through immediately (no Apply button).
|
||||
|
||||
**Storage figures:** computed by summing game sizes per state, plus free-space query via Tauri.
|
||||
|
||||
@@ -448,7 +503,7 @@ Cover art in the design files is **stylized placeholder art** — generated enti
|
||||
|
||||
In the production app, the launcher should ideally use real cover-art when available (fetch from IGDB / Steam / local game folder) and fall back to the placeholder generator for games without art. The placeholder generator is in `design_reference/components.jsx → GameCover`.
|
||||
|
||||
The icon set (search, play, install, download, folder, kebab, sort, users, close, check, chevron, trash) is in `design_reference/components.jsx → Icon`. They are 12-14px inline SVGs using `currentColor`. Reuse as-is or substitute with the codebase's existing icon library at the same visual weight.
|
||||
The icon set (search, play, **server**, install, download, folder, kebab, sort, users, close, check, chevron, trash) is in `design_reference/components.jsx → Icon`. They are 12-14px inline SVGs using `currentColor`. Reuse as-is or substitute with the codebase's existing icon library at the same visual weight. The `server` glyph is new in this round — two stacked rounded rectangles with LED dots, used only on the Start Server button.
|
||||
|
||||
Fonts to load:
|
||||
```html
|
||||
@@ -475,8 +530,13 @@ design_reference/
|
||||
|
||||
To preview the design in a browser:
|
||||
1. Open `SoftLAN Launcher.html` in a static-server (e.g. `python -m http.server` from the folder).
|
||||
2. You'll see a design canvas with all variants (A, B, C, D, E) side-by-side. Click an artboard's expand button to view it full-screen.
|
||||
3. The "Tweaks" floating panel in the bottom-right is dev-only — it lets you live-change accent / density / aspect / background. In the production app these live in the Settings dialog (variant E).
|
||||
2. You'll see a design canvas with all variants (A, B, C, D, E, F) side-by-side. Click an artboard's expand button to view it full-screen.
|
||||
- **A / B** — chrome variants (A is the chosen direction)
|
||||
- **C** — detail overlay for an installed, server-capable game (Counter-Strike 1.6) → shows **Play + Start Server + Uninstall**
|
||||
- **D** — detail overlay for a downloaded-but-not-installed game (CoD 4) → shows **Install + Delete from disk**
|
||||
- **E** — detail overlay for a downloading game (AvP) → shows the live progress component + **Cancel**
|
||||
- **F** — Settings dialog open, with the new **Profile** section at the top
|
||||
3. The "Tweaks" floating panel in the bottom-right is dev-only — it lets you live-change every persisted setting (username / language / accent / background / density / aspect). In the production app these live in the Settings dialog.
|
||||
|
||||
---
|
||||
|
||||
@@ -487,3 +547,5 @@ To preview the design in a browser:
|
||||
- **Error state on action** — if a Download / Install fails, show inline error on the affected card (red border + retry button), and a toast.
|
||||
- **Progress state** — designed. See "Download progress" section above. The action-button slot is swapped for a live `DownloadProgress` component (card + modal variants with container-query fallback for narrow tiles). Wire it to your real progress events; the rendering layer is dev-ready.
|
||||
- **Keyboard arrow nav** — arrow keys should move focus between cards in the grid; not implemented in the mock but mentioned as a goal.
|
||||
- **"Server running" state** — once Start Server actually spawns a process, the button should switch to a *running* state (live indicator dot + "Server running" label + click-to-stop). Not designed this round — flag for follow-up alongside whatever server-status panel the app grows.
|
||||
- **German translations** — the language toggle is wired in Settings, but the catalog of translated UI strings hasn't been compiled. Stand up `react-i18next` (or equivalent) and seed `en.json` from the existing copy; `de.json` is a translation task for whoever owns localization.
|
||||
|
||||
Reference in New Issue
Block a user