Files
Encelado/Encelado/docs/UI_GUIDELINES.md
T
Alby96andClaude Fable 5.1 e9ace47501 5.0: avvio in locale nella sandbox deploy/local, script di avvio e screenshot, arresto pulito del container verificato
Per vedere e provare il bot senza Unraid: F5 in VS Code, scripts/run-dev e
scripts/run-docker usano tutti deploy/local come /config e /data, con la stessa
disposizione del container, così chiavi e configurazione valgono in ogni modo.
ENCELADO_DATA_DIR separa i dati anche fuori dal container. scripts/screenshots
rigenera docs/img dal server campione; /api/health in --sample non finge più un
motore acceso. docker stop ora termina in un secondo con «SIGTERM: arresto»
(PosixSignalRegistration), provato sull'immagine 5.0.0 costruita dalla catena.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-23 13:59:56 +02:00

8.5 KiB
Raw Blame History

Linee guida dell'interfaccia web

Aggiornato: 2026-09-23 (5.0, ADR-0007). L'interfaccia è servita dal bot stesso (src/Encelado.Server/Web/wwwroot/: index.html, login.html, app.css, app.js, icon.svg, manifest.webmanifest, incorporati nell'assembly). Nessuna libreria, nessun font remoto, nessun <script src=http…>: un test lo verifica (EmbeddedUiTests).

Principi

  1. La UI non decide niente. Legge lo snapshot (/api/snapshot, /api/stream) e manda comandi (POST /api/commands/<nome>). Ogni regola di rischio sta nel motore.
  2. Le stesse informazioni della dashboard di sempre: equity, P&L di oggi, P&L aperto (conto e basket), drawdown, basket aperti con in attesa / orfane / esterne, margine; la tabella dei basket; prossimo evento, collegamento eToro, Telegram; l'attività. I dettagli stanno nei tooltip (title) e nel log, non in più riquadri.
  3. Ogni numero ha un tooltip con la formula o la fonte; ogni importo convertito porta nel tooltip il valore in USD e il tasso usato. Il ledger resta in USD.
  4. Gli orari a schermo sono nel fuso scelto (ui.timeZone, TZ); la barra in alto mostra sempre anche l'UTC, che è l'ora del ledger.
  5. Le azioni irreversibili chiedono conferma in un dialogo: chiusura di un basket, kill-switch (con la spunta «chiudi anche le esterne», deselezionata), reset (motivazione ≥ 10 caratteri), rimozione delle chiavi, ripristino della configurazione, avvio Live (frase CONFERMO LIVE scritta per intero).

Material 3 senza libreria

Colori (token CSS in :root)

Ruolo Scuro (default) Chiaro Uso
--primary / --on-primary #adc6ff / #002e69 #005ac1 / #ffffff pulsante AVVIA, tab attiva, focus, curva dell'equity
--primary-container / --on-primary-container #1f4e9c / #d8e2ff #d8e2ff / #001a41 voce attiva del rail
--surface, --surface-container-low/-/high/highest #101418, #181c20, #1c2024, #262a2f, #31353a #f8f9ff, #f2f3f9, #eceef4, #e6e8ee, #e0e2e8 sfondo, rail, card, KPI, intestazioni delle tabelle
--on-surface / --on-surface-variant #e0e2e8 / #c3c6d0 #191c20 / #43474e testo, testo secondario
--outline / --outline-variant #8d9099 / #43474e #74777f / #c3c6d0 bordi di input e tabelle
--error / --error-container #ffb4ab / #93000a #ba1a1a / #ffdad6 kill-switch, banner rosso, stato Halted
--up / --down / --warn #7fd39a / #ff8a80 / #f5b74f #1b7f3b / #c62828 / #9a6400 solo P&L, pip, stati (verde/rosso), avvisi (giallo)

Una sola tinta d'accento; contrasto ≥ 4,5:1 per il testo. Il tema si sceglie in Impostazioni ▸ Interfaccia (ui.theme: dark | light) e viene ricordato nel browser (localStorage, solo comodità per chi guarda); prefers-color-scheme è rispettato quando il file dice dark ma il sistema è chiaro solo per color-scheme.

Tipografia

Roboto, "Segoe UI", system-ui, sans-serif; monospazio Cascadia Mono, JetBrains Mono, Consolas per log, id e attività. Scala: titolo di pagina 20 px (title-large), titoli delle card 16 px (title-medium), KPI 24 px (headline-small), corpo 14 px, etichette 12 px. Cifre tabulari (font-variant-numeric: tabular-nums) su ogni numero.

Forma, elevazione, stati

Angoli 12 px (card, banner), 16 px (dialoghi grandi 28 px come da M3), pulsanti a pillola (999 px). Elevazione tonale (superfici a livelli), niente ombre salvo dialoghi e snackbar. State layer su hover (8 %) e pressed (12 %) tramite ::after. :focus-visible con anello di 2 px in --primary.

Componenti

Componente Dove Note
Navigation rail sinistra, 80 px chiuso / 256 px aperto quattro voci: Dashboard, Storico ordini, Log, Impostazioni; stato ricordato (ui.navExpanded e localStorage); sotto 600 px diventa un drawer con scrim; in fondo i chip ambiente e stato
Top app bar sopra la pagina titolo della pagina, ora UTC e ora nel fuso, selettore della valuta, AVVIA/FERMA, KILL-SWITCH (attivo solo a motore acceso); linear progress durante un comando
Cards dashboard, contesto, impostazioni KPI con etichetta, valore, riga secondaria
Data table compatta basket, storico, log intestazione fissa, righe da 32 px, allineamento a destra dei numeri; sotto 600 px la tabella dei basket diventa cards
Chips ambiente (PAPER blu, DEMO giallo, LIVE rosso), stato del motore, stato del basket, origine della posizione testo in minuscolo per gli stati
Buttons filled (AVVIA, Salva, conferme), tonal (Applica, Avvia il ripristino), outlined danger (KILL-SWITCH), text (Chiudi, Esporta) mai due filled affiancati
Select, input, switch filtri, impostazioni, Segui nel log validazione lato server con messaggio accanto al campo
Dialog conferma, prompt (motivazione, CONFERMO LIVE), ripristino in cinque passi <dialog> nativo, showModal, Esc chiude
Snackbar esito dei comandi 4 s, 8 s se errore
Banner dashboard rosso per errore, kill-switch con residuo, equity stop, sospensione; giallo per entrate bloccate, non riconciliate, orfane
Tooltip title su ogni numero e riga la formula, la fonte, il valore in USD

Classi di finestra

Classe Larghezza Layout
compact < 600 px rail nascosto (menu ☰), KPI su due colonne, basket a cards, orologi nascosti
medium 600-839 px rail 80 px, KPI su due colonne, contesto su una colonna, impostazioni su una colonna
expanded ≥ 840 px rail 80/256 px, KPI su tre colonne (due righe), contesto su tre, impostazioni su due

Accessibilità

Tastiera completa (Tab su rail, pulsanti, tabelle, dialoghi; Esc chiude drawer e dialoghi), aria-label su icone e selettori, aria-current="page" sulla voce attiva, role="tablist"/"tab"/"tabpanel" nello storico, role="status" su banner e snackbar, link «Vai al contenuto», prefers-reduced-motion (nessuna transizione), prefers-color-scheme.

Pagine

  • Dashboard: banner, sei KPI, tabella dei basket (nome e cross, stato, z, ρ, HL, pip, TP, P&L, costo, prossimo evento, Chiudi), preset, tre card di contesto, attività (ultime righe di log).
  • Storico ordini: tre tab. Ordini (da orders.jsonl: unità richieste ed eseguite, prezzi, slippage, stato, esito, id), Posizioni (storico eToro classificato basket / orfana-bot / esterna / movimento di cassa, con P&L lordo, fee, netto, pip, durata, motivo), Profitti per periodo (oggi, ieri, 7 e 30 giorni, mese corrente e precedente, anno, tutto, intervallo personalizzato; curva dell'equity realizzata in SVG). Filtri e Esporta CSV (;, colonna motivazione).
  • Log: livello, ricerca, «Segui», 2000 righe per pagina lette a incrementi (/api/log?after=).
  • Impostazioni: configurazione a gruppi (eToro, esecuzione, notifiche, interfaccia/valuta, log) con validazione; chiavi eToro (verifica e salvataggio cifrato); ripristino in cinque passi e ripristino dei valori predefiniti; Ricerca (stato del modello in ombra, bandit, volatilità, criterio di riattivazione, «Esegui ciclo di apprendimento»); Diagnostica (strategia e run, percorsi, .NET, sistema, uptime, quote API, fuso, bonifica); Informazioni (nome, autore, versione, data di build, commit, licenza, documentazione).
  • Login: solo con ENCELADO_WEB_TOKEN; cookie HttpOnly per 30 giorni.

Flusso dei dati

/api/stream (SSE, event: snapshot, uno al secondo) → apply(snapshot)render(); se il browser non ha EventSource, polling di /api/snapshot ogni 2 s; ?once=1 scatta una sola lettura (per gli screenshot). I comandi rispondono {ok, message, …} e finiscono nella snackbar; l'esito vero arriva con lo snapshot successivo. Il log legge /api/log ogni 1,5 s solo mentre la pagina Log è aperta.

Screenshot

docs/img/ (dashboard, storico, log, impostazioni, mobile), presi dal server in modalità campione con scripts\screenshots.ps1 (o sh scripts/screenshots.sh): avvia il server con --sample su una porta libera, apre ogni pagina con Edge headless (?once=1, 1440×900 e 420×860) e lo ferma. A mano, una pagina:

dotnet run --project src/Encelado.Server -- --sample --port 8085
& "C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe" --headless=new --disable-gpu --hide-scrollbars --window-size=1440,900 --virtual-time-budget=5000 --user-data-dir=$env:TEMP\edge-shot --screenshot=docs\img\dashboard.png "http://127.0.0.1:8085/?once=1#/dashboard"

Prima di dichiarare finita una modifica: EmbeddedUiTests e WebHostTests verdi, screenshot rifatti se cambia una pagina, revisione visiva con l'utente.