The device console is a default-grey tkinter window with no hierarchy: no grouping, no state colour, no type scale, the privilege warning buried in a monospace paragraph, "Çık" duplicated at two sizes, and an output area that looks editable. Every measurement is in the delivered work; the point here is that the fix is a system, not a repaint. Adds PRODUCT.md (product truth: who uses this, from where, under what constraints), docs/DESIGN.md (the direction contract and the shared status vocabulary) and web/static/tokens.css (the values both surfaces read). The vocabulary is the load-bearing part. Four severities -- ok / warn / danger / info -- plus one action accent, and one Turkish word per device stage (KURULDU / KAYITLI / HAZIR / HATA / YOK) used identically on the device and in the central panel. A fifth hue is a bug, and colour is never the only carrier: every badge ships its word, so the fleet list stays readable in greyscale. The ground is light on purpose. The console runs in workshops and dealer service areas in daylight; a near-black ops console loses its own body text there and its state colours collapse into equal-brightness smudges. No webfont: the fleet installs offline from a committed pool, so a font CDN is a broken page on every device.
80 lines
4.2 KiB
Markdown
80 lines
4.2 KiB
Markdown
# Blueforce Field OS — Design System
|
|
|
|
Two operator surfaces, one visual language: the **device console** (Python/tkinter,
|
|
ships on each field PC) and the **central panel** (Python stdlib `http.server`,
|
|
browser). Both describe the same fleet from opposite ends, so they share a status
|
|
vocabulary and a token set. Palette values live in `web/static/tokens.css`; the
|
|
console reads the same values through `bfos/ui_theme.py`.
|
|
|
|
## Direction contract
|
|
|
|
**THESIS.** The device's state is the subject, and it must be legible from a step
|
|
back — on a workshop laptop, in daylight, with someone waiting. This surface
|
|
refuses the category default it would otherwise inherit: a near-black "ops
|
|
console" with grey body text, six hues fighting for meaning, and status buried in
|
|
a log. Instead: a light ground, dark text with real contrast, and saturation
|
|
spent only where it carries a state.
|
|
|
|
**OWN-WORLD.** Light neutral ground (`--bg-app #f6f7f8`) with white raised panels
|
|
and hairline borders; one dark region, the app header, which anchors the frame.
|
|
One action accent (`--accent #1d4ed8`) marking the action the operator came to
|
|
take and the selected row, nothing else. Four state severities — ok / warn /
|
|
danger / info — each with a strong and a soft form, so a badge or a row can be
|
|
built from one palette without inventing a second. Data (ids, counts, exit codes,
|
|
timestamps) set in monospace so columns align; UI text in the platform face.
|
|
Buttons and inputs share one height; rows share one height; a 4px space rhythm.
|
|
|
|
**STORY.** The operator sees at a glance whether the device (or the fleet) is
|
|
ready, what stage it reached, and what the one next action is. A technician
|
|
understands an install's outcome without reading the log; an operator scanning
|
|
700 devices finds the ones that need attention without opening them.
|
|
|
|
**FIRST VIEWPORT.** Header band (dark, 56px) carrying the product name, the
|
|
target identity, and privilege level on the right — privilege is never a buried
|
|
sentence. Below it, a two-column body: left, the fleet/device list with a state
|
|
badge per row, sorted so non-ready devices surface first, with a filter bar and a
|
|
summary strip of counts by state (the one large figure per view). Right, the
|
|
selected device's detail: state, target id, hostname, wave, and the channel
|
|
verification list. The primary action sits in the header, not below the fold.
|
|
|
|
**FORM.** Operate surface. The world is a *control room board*: fixed regions,
|
|
legible readouts, one accent, state as signal. No decorative motion; the only
|
|
transition is a state change and a row selection.
|
|
|
|
**FINISH.** unreviewed and undocumented is unfinished; this build ends with the
|
|
finish review, the verdict, DESIGN.md, and every shipping raster carrying its
|
|
provenance.
|
|
|
|
## Status vocabulary
|
|
|
|
One word per state, Turkish, used identically in both surfaces.
|
|
|
|
| State | Token | Meaning |
|
|
|---|---|---|
|
|
| `KURULDU` | `--state-provisioned` | Provisioned offline, not yet enrolled |
|
|
| `KAYITLI` | `--state-enrolled` | Enrolled, channels not all verified |
|
|
| `HAZIR` | `--state-ready` | Every channel verified; the only shippable state |
|
|
| `HATA` | `--state-failed` | A check failed; the device needs a person |
|
|
| `YOK` | `--state-absent` | Not reachable / never seen |
|
|
|
|
Colour is never the only carrier: every badge ships its word, and the fleet table
|
|
sorts non-ready first, so the list is readable in greyscale.
|
|
|
|
## Privilege
|
|
|
|
Read-only and full privilege are visually distinct states, not a log line: the
|
|
header states the current level, and the console disables rather than hides
|
|
write operations when unprivileged, with the reason on the control.
|
|
|
|
## Rules
|
|
|
|
1. Saturation carries meaning. A colour is a state or the action accent; it is
|
|
never decoration, and a fifth hue is a bug.
|
|
2. Badges carry words. Greyscale must not lose the state.
|
|
3. One loud figure per view. Everything else is quiet and aligned.
|
|
4. No webfont. The fleet installs offline; the UI face is whatever the platform
|
|
ships and the data face is monospace.
|
|
5. Destructive actions look different and ask twice. Approval and the root gate
|
|
are design, not an afterthought.
|
|
6. The log is evidence, not the interface. Outcomes surface as state and
|
|
structure first; raw output stays available, collapsed.
|