Rifacimento della UI secondo STILE_UI.md
Adotta lo stile condiviso delle app Integry: superfici piatte, raggi ampi, spaziature a scala fissa, gerarchia data dallo spazio prima che dalla decorazione. La palette storica di SteUP resta intatta; sono stati aggiunti solo i ruoli che mancavano (workspace, surfaceMuted, divider, inkMuted e le triplette dei toni semantici). Fondamenta - tokens.css: ruoli colore, scale di spazio/raggi/tipografia, curve di movimento e scala z-index semantica. Unica fonte di verita': pilotano anche le variabili CSS di MudBlazor. - Inter variabile ospitata in locale (133KB) al posto di Nunito da Google Fonts: l'app lavora offline, un font che arriva dalla rete in campo non arriva. - base.css: shell applicativa e comportamenti da app nativa — niente selezione testo, niente menu al tocco lungo, niente lampo grigio sul tap, niente rimbalzo elastico, niente zoom a doppio tocco, scroll con inerzia. - mudblazor-overrides.css: MudBlazor appiattito (elevation 0, nessun tint, target 44/48, etichette in caso naturale). - Rimossi Bootstrap (CSS, icone e JS) e i 996 righe di CSS con ambito per componente del vecchio sistema: erano tutti inutilizzati. Struttura - Navigazione flottante in basso con icona piena sulla voce attiva; da 720px diventa colonna laterale. Il MudFabMenu e' sostituito da un bottom sheet: stessa funzione, bersagli molto piu' grandi. - Testata alta col titolo a sinistra, fusa con la pagina. - Nel form scheda il salvataggio sta in una barra ancorata in fondo, non in coda a uno scroll lungo. - Scelta di punto vendita e articoli a schermo intero con ricerca; la selezione multipla usa righe da 56px invece di un menu a tendina. - Urgenza scelta a pillole invece che da una select. Stato e riscontro - StatusBadgeHelper: tono, icona ed etichetta di ogni stato in un punto solo, cosi' lo stesso stato si presenta identico ovunque. - Scheletri al posto degli spinner; l'overlay bloccante dice sempre cosa sta facendo; gli stati vuoti suggeriscono la mossa successiva. - Rimosso il ritardo artificiale di 250ms in InspectionCard, che non attendeva nulla. DESIGN.md riscritto sul nuovo sistema. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,276 @@
|
||||
/* =============================================================================
|
||||
SteUP — Base
|
||||
Reset, shell applicativa, tipografia e comportamenti "da app nativa".
|
||||
========================================================================== */
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
/* La WebView non deve comportarsi come un browser: niente rimbalzo elastico
|
||||
ai bordi, niente pull-to-refresh, niente zoom a doppio tocco. */
|
||||
overscroll-behavior: none;
|
||||
touch-action: manipulation;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
background-color: var(--workspace);
|
||||
color: var(--ink);
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--body-lg-size);
|
||||
line-height: var(--body-lg-height);
|
||||
font-weight: 400;
|
||||
/* Inter: cifre a larghezza fissa, cosi' i contatori non "ballano" mentre
|
||||
si aggiornano, e forme delle lettere piu' leggibili in piccolo. */
|
||||
font-feature-settings: "tnum" 1, "cv05" 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
text-rendering: optimizeLegibility;
|
||||
|
||||
/* Niente selezione del testo, niente menu contestuale al tocco lungo,
|
||||
niente lampo grigio sul tap: sono i tre segnali che tradiscono una
|
||||
pagina web dentro un'app. */
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* Il contenuto dei dati resta selezionabile: un barcode o un codice servono
|
||||
anche da copiare. */
|
||||
.selectable,
|
||||
input,
|
||||
textarea {
|
||||
user-select: text;
|
||||
-webkit-user-select: text;
|
||||
-webkit-touch-callout: default;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100dvh;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Tipografia — scala fissa (STILE_UI §4)
|
||||
La gerarchia si fa con peso e dimensione, mai con il maiuscolo spaziato.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.t-headline-md {
|
||||
font-size: var(--headline-md-size);
|
||||
line-height: var(--headline-md-height);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.t-headline-sm {
|
||||
font-size: var(--headline-sm-size);
|
||||
line-height: var(--headline-sm-height);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.t-title-lg {
|
||||
font-size: var(--title-lg-size);
|
||||
line-height: var(--title-lg-height);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.t-title-md {
|
||||
font-size: var(--title-md-size);
|
||||
line-height: var(--title-md-height);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.t-body-lg {
|
||||
font-size: var(--body-lg-size);
|
||||
line-height: var(--body-lg-height);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.t-body-md {
|
||||
font-size: var(--body-md-size);
|
||||
line-height: var(--body-md-height);
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.t-label-lg {
|
||||
font-size: var(--label-lg-size);
|
||||
line-height: 1.25;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.t-label-md {
|
||||
font-size: var(--label-md-size);
|
||||
line-height: 1.25;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Identificativo tecnico sopra il titolo di una card (STILE_UI §4) */
|
||||
.t-ident {
|
||||
font-size: var(--label-sm-size);
|
||||
line-height: 1.3;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.3px;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.t-muted {
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
/* Il testo secondario si distingue per colore, mai per opacita'. */
|
||||
.t-meta {
|
||||
font-size: var(--body-md-size);
|
||||
line-height: var(--body-md-height);
|
||||
font-weight: 600;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
/* Prosa: righe non piu' lunghe di 65-75 caratteri. */
|
||||
.t-prose {
|
||||
max-width: 68ch;
|
||||
text-wrap: pretty;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
text-wrap: balance;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4, h5, h6, p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Shell applicativa
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.app-shell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100dvh;
|
||||
overflow: hidden;
|
||||
background-color: var(--workspace);
|
||||
}
|
||||
|
||||
/* Area scorrevole unica della schermata. Lo scroll con inerzia e il
|
||||
contenimento evitano che il gesto "sfondi" sulla pagina sottostante. */
|
||||
.app-scroll {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
overscroll-behavior: contain;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.app-scroll::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Contenitore di pagina (STILE_UI §6.1): su telefono e' trasparente, su
|
||||
schermo largo tiene una colonna leggibile invece di allargarsi all'infinito. */
|
||||
.page-width {
|
||||
width: 100%;
|
||||
max-width: var(--content-max);
|
||||
margin-inline: auto;
|
||||
padding-inline: var(--space-md);
|
||||
}
|
||||
|
||||
/* Spazio in coda per non finire sotto la barra di navigazione flottante. */
|
||||
.page-body {
|
||||
padding-bottom: calc(var(--nav-clearance) + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
/* Pagine senza barra di navigazione (login, form a schermo pieno). */
|
||||
.page-body--flush {
|
||||
padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
.stack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.stack-xs { gap: var(--space-xs); }
|
||||
.stack-10 { gap: var(--space-10); }
|
||||
.stack-sm { gap: var(--space-sm); }
|
||||
.stack-md { gap: var(--space-md); }
|
||||
.stack-lg { gap: var(--space-lg); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Focus
|
||||
Visibile e coerente ovunque, senza sporcare il tocco: solo da tastiera.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:focus-visible {
|
||||
outline: 2px solid var(--focus-ring);
|
||||
outline-offset: 2px;
|
||||
border-radius: var(--radius-compact);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Risposta al tocco
|
||||
Feedback fisico immediato (principio "Feedback immediato a ogni scan"):
|
||||
l'elemento cede sotto il dito e torna. Niente stati basati sull'hover, che
|
||||
su un touch screen non esiste e lascia elementi "accesi" dopo il tocco.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.pressable {
|
||||
transition: transform var(--duration-fast) var(--ease-out),
|
||||
background-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.pressable:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
@media (hover: hover) and (pointer: fine) {
|
||||
.pressable:hover {
|
||||
background-color: var(--surface-muted);
|
||||
}
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Movimento ridotto — non e' opzionale
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
|
||||
.pressable:active {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user