Files
VeillaxandClaude Sonnet 5.5 88487d9744
CI / test (push) Successful in 2m15s
Release / release (push) Successful in 2m51s
Restyle the dashboard to the Lightwell design language
Same tokens, sidebar shell, components and voice as Hammerhead: teal accent,
warm neutrals, status badges with text, dialogs with focus trapping that name
what they affect, empty states, skeleton loading, outline icons, 44px touch
targets and a slide-in drawer on phones. The strict CSP stays: no inline
styles or scripts, so icons and sizes use classes.

Adds docs/design.md and scripts/lint-design.mjs (run in CI), capitalizes
server error messages in one place, and rewrites interface copy to the voice
rules (sentence case, buttons that name the result, no dashes).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-31 00:30:30 -06:00

64 lines
4.5 KiB
Markdown

# Megalodon design language
The dashboard follows the Lightwell design language, the same one Hammerhead uses. The reference is `docs/design.md` in the Lightwell repository, and Hammerhead's own `docs/design.md` records how it is applied there. When this page and Lightwell disagree, Lightwell wins.
## What is shared with Lightwell and Hammerhead
* **Tokens.** Colors, spacing (4px scale), radius (6px and 10px), type sizes (12 to 28px), the single shadow and the dark theme are the Lightwell values, copied from Hammerhead. The accent is Lightwell's teal, `#1f5c5c`, with white text on it. Everything derived from the accent uses `color-mix`.
* **Principles.** Quiet neutrals with one accent, plain and specific wording, one way to do each thing, calm density, and WCAG 2.1 AA.
* **Voice.** No emoji, no em or en dashes, no exclamation marks, sentence case, buttons that name the result ("Ban player", not "OK"), and errors that say what happened and what to do next. Errors that come from the server are capitalized in one place (`fail` in `internal/web/server.go`).
* **Status carries text.** A status is a badge with a label ("Online", "Offline", "Restarting soon"), never a colored dot on its own.
## Where it lives
| File | What it holds |
| --- | --- |
| `internal/web/static/style.css` | All styles. The token block sits between `tokens:begin` and `tokens:end`; raw colors are allowed only there. |
| `internal/web/static/app.js` | The dashboard: the toolkit at the top, then the pages. |
| `internal/web/static/index.html` | An empty shell that loads the two files above. |
Unlike Hammerhead's single page, Megalodon keeps its script and styles in separate files because its Content-Security-Policy forbids inline script and inline `style` attributes. Nothing in the UI sets a style attribute; widths and sizes are classes.
## Components
Built from the helpers at the top of `app.js`. Feature code uses these and does not style one-off.
| Helper | Use |
| --- | --- |
| `card`, `pageHeader` | Surfaces and the page title with its one primary action |
| `field`, `chk` | Label above the control, hint below |
| `badge(text, tone)` | Status pill. Tones: success, warning, danger, accent, or none for neutral |
| `emptyState(icon, title, text, action)` | Dashed outline, icon, a title that says "No X yet", one sentence |
| `modal`, `formDialog` | Dialogs. Focus moves in, Tab stays inside, Escape closes, focus returns to the opener |
| `confirmDialog` | Every destructive action. The title names the object, the body says what is lost and whether it can be undone |
| `toast` | Confirmations at the bottom right. Errors stay longer and are announced as alerts |
| `skeleton` | Placeholder rows while a page loads, not a spinner |
## Icons
Lucide style, outline only, stroke 1.75, round caps, `currentColor`. Sizes are 16, 18 and 22 pixels. They are inline in the `ICONS` table. An icon goes with a text label, and icon-only buttons carry an `aria-label`.
Approved names: `fin`, `servers`, `players`, `bans`, `schedules`, `settings`, `activity`, `out`, `menu`, `close`, `add`, `check`, `light`, `dark`, `alert`. Add a name here and in `ICONS` together.
## Patterns
* **One primary action per view.** It sits in the page header: Add server on the overview, Broadcast on a server, Ban a player on the bans page, New job on schedules. Other buttons use the default (ghost) style.
* **List pages** show the page header, then the table in a card with no second title.
* **Dialogs and forms** end with Cancel and then the primary action, at the bottom right. Labels sit above fields, and rules such as "At least 8 characters" are hints below them, not part of the label.
* **Dates** have the month written out ("Nov 2, 2026"), with `fmtTime`. Event rows show the time of day, with the full date in a tooltip.
* **Empty states** say why the list is empty: nothing yet, or nothing matching the filters.
## Layout
* Content is capped at 1120px. Below 860px the sidebar becomes a slide-in drawer with a top bar, and grids collapse. Phones keep a 16px side gutter.
* On touch screens controls are at least 44px high and inputs are 16px so the page does not zoom.
* Motion is minimal and turns off under `prefers-reduced-motion`. The theme follows the system and can be switched from the sidebar.
## Checking a change
```
node scripts/lint-design.mjs
```
It fails on em and en dashes, emoji, and raw colors outside the token block, in the dashboard files, the docs and the Go source. Then check the page in light and dark, at phone and desktop width, using only the keyboard.