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:
@@ -1,335 +0,0 @@
|
||||
html {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.page, article, main {
|
||||
height: 100% !important;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#app {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
html, body {
|
||||
font-family: "Nunito", sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 1.8;
|
||||
color: black;
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "Nunito", sans-serif !important;
|
||||
}
|
||||
|
||||
html ::-webkit-scrollbar {
|
||||
width: 3px;
|
||||
height: 3px;
|
||||
}
|
||||
|
||||
html ::-webkit-scrollbar-thumb {
|
||||
background: #bbb;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.mud-button-label {
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
a, .btn-link {
|
||||
/*color: #006bb7;*/
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
article {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/*ServicesIsDown" : "SystemOk" : "NetworkKo*/
|
||||
|
||||
.Connection {
|
||||
padding: 0 .75rem;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: 1rem;
|
||||
font-size: larger;
|
||||
transition: all 0.5s ease;
|
||||
opacity: 0;
|
||||
transform: translateY(-35px);
|
||||
min-height: 35px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.Connection.ServicesIsDown, .Connection.NetworkKo {
|
||||
background-color: var(--mud-palette-error);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.Connection.SystemOk {
|
||||
background-color: var(--mud-palette-success);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.Connection.Show {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.Connection.Hide ~ .page {
|
||||
transition: all 0.5s ease;
|
||||
transform: translateY(-35px);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
color: #fff;
|
||||
background-color: var(--primary-color);
|
||||
border-color: var(--darker-color);
|
||||
}
|
||||
|
||||
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
|
||||
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-top: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
h1:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.valid.modified:not([type=checkbox]) {
|
||||
outline: 1px solid #26b050;
|
||||
}
|
||||
|
||||
.invalid {
|
||||
outline: 1px solid #e50000;
|
||||
}
|
||||
|
||||
.validation-message {
|
||||
color: #e50000;
|
||||
}
|
||||
|
||||
#blazor-error-ui {
|
||||
background: lightyellow;
|
||||
bottom: 0;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
|
||||
display: none;
|
||||
left: 0;
|
||||
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
#blazor-error-ui .dismiss {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 0.75rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
.blazor-error-boundary {
|
||||
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
|
||||
padding: 1rem 1rem 1rem 3.7rem;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.blazor-error-boundary::after {
|
||||
content: "An error has occurred."
|
||||
}
|
||||
|
||||
.status-bar-safe-area {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: x-large;
|
||||
font-weight: 800;
|
||||
margin: 0;
|
||||
line-height: normal;
|
||||
color: var(--mud-palette-text-primary);
|
||||
}
|
||||
|
||||
.custom-mudfab {
|
||||
position: fixed !important;
|
||||
bottom: 4rem;
|
||||
margin-bottom: 16px;
|
||||
right: 16px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
display: block;
|
||||
width: 100%;
|
||||
border: .05rem solid var(--mud-palette-lines-inputs);
|
||||
}
|
||||
|
||||
.pb-safe-area {
|
||||
padding-bottom: 75px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/*Spinner*/
|
||||
|
||||
.spinner-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 100vh;
|
||||
align-items: center;
|
||||
color: var(--mud-palette-primary);
|
||||
}
|
||||
|
||||
.not-fullScreen {
|
||||
height: auto !important;
|
||||
padding: 2rem 0 !important;
|
||||
}
|
||||
|
||||
.loader {
|
||||
width: 50px;
|
||||
aspect-ratio: 1;
|
||||
border-radius: 50%;
|
||||
border: 8px solid #0000;
|
||||
border-right-color: var(--mud-palette-primary);
|
||||
position: relative;
|
||||
animation: l24 1s infinite linear;
|
||||
}
|
||||
|
||||
.loader:before,
|
||||
.loader:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
inset: -8px;
|
||||
border-radius: 50%;
|
||||
border: inherit;
|
||||
animation: inherit;
|
||||
animation-duration: 2s;
|
||||
}
|
||||
|
||||
.loader:after {
|
||||
animation-duration: 4s;
|
||||
}
|
||||
|
||||
@keyframes l24 {
|
||||
100% {
|
||||
transform: rotate(1turn)
|
||||
}
|
||||
}
|
||||
|
||||
/*MudBlazor Personalization*/
|
||||
|
||||
.mud-button-group-horizontal:not(.mud-button-group-rtl) > .mud-button-root:not(:last-child), .mud-button-group-horizontal:not(.mud-button-group-rtl) > :not(:last-child) .mud-button-root {
|
||||
border-top-right-radius: 0 !important;
|
||||
border-bottom-right-radius: 0 !important;
|
||||
}
|
||||
|
||||
.mud-button-group-horizontal:not(.mud-button-group-rtl) > .mud-button-root:not(:first-child), .mud-button-group-horizontal:not(.mud-button-group-rtl) > :not(:first-child) .mud-button-root {
|
||||
border-top-left-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
}
|
||||
|
||||
.customDialog-form .mud-dialog-content {
|
||||
padding: 0 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.custom-item-select {
|
||||
padding: 6px 16px;
|
||||
}
|
||||
|
||||
.custom-item-select .mud-typography-body1 {
|
||||
font-weight: 600;
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding-right: var(--m-page-x) !important;
|
||||
padding-left: var(--m-page-x) !important;
|
||||
}
|
||||
|
||||
.lm-container {
|
||||
padding-right: calc(var(--m-page-x) * 0.5) !important;
|
||||
padding-left: calc(var(--m-page-x) * 0.5) !important;
|
||||
}
|
||||
|
||||
.mud-message-box > .mud-dialog-title > h6 {
|
||||
font-weight: 800 !important;
|
||||
}
|
||||
|
||||
.mud-dialog-actions button {
|
||||
margin-left: .5rem !important;
|
||||
margin-right: .5rem !important;
|
||||
}
|
||||
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
.status-bar-safe-area {
|
||||
display: flex;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
height: env(safe-area-inset-top);
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
background-color: var(--mud-palette-surface);
|
||||
}
|
||||
|
||||
.modal {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
}
|
||||
|
||||
.safe-area-bottom {
|
||||
margin-bottom: env(safe-area-inset-bottom) !important;
|
||||
}
|
||||
|
||||
.pb-safe-area {
|
||||
padding-bottom: env(safe-area-inset-bottom) !important;
|
||||
}
|
||||
|
||||
#app {
|
||||
margin-top: env(safe-area-inset-top);
|
||||
height: calc(100vh - env(safe-area-inset-top));
|
||||
}
|
||||
|
||||
.flex-column, .navbar-brand {
|
||||
padding-left: env(safe-area-inset-left);
|
||||
}
|
||||
|
||||
.customDialog-form .mud-dialog-content {
|
||||
margin-top: env(safe-area-inset-top);
|
||||
}
|
||||
}
|
||||
|
||||
/*Ripple*/
|
||||
.ripple-container {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
transform: translateZ(0);
|
||||
}
|
||||
|
||||
.ripple {
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
transform: scale(0);
|
||||
animation: ripple-effect 0.6s linear;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
@keyframes ripple-effect {
|
||||
to {
|
||||
transform: scale(4);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ripple-white .ripple {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
/*---Blazor custom---*/
|
||||
|
||||
.mud-snackbar {
|
||||
border-radius: 1em !important;
|
||||
}
|
||||
|
||||
.mud-paper {
|
||||
border-radius: 1em !important;
|
||||
}
|
||||
|
||||
.mud-dialog {
|
||||
border-radius: 1em !important;
|
||||
}
|
||||
|
||||
.mud-overlay.on-top {
|
||||
z-index: 10001 !important;
|
||||
}
|
||||
|
||||
.mud-popover.mud-popover-open {
|
||||
border-radius: 1em !important;
|
||||
}
|
||||
|
||||
.mud-picker-popover-paper {
|
||||
border-radius: 1em !important;
|
||||
}
|
||||
|
||||
.mud-skeleton {
|
||||
border-radius: .5em !important;
|
||||
}
|
||||
|
||||
/*.mud-expand-panel{*/
|
||||
/* background: var(--light-card-background) !important;*/
|
||||
/* box-shadow: unset !important;*/
|
||||
/*}*/
|
||||
|
||||
.mud-expansion-panels {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ripple-container .mud-ripple-effect {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.ripple-container .mud-ripple-effect-expanding {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.ripple-container .mud-button:focus-visible, .ripple-container .mud-button:active{
|
||||
background-color: unset !important;
|
||||
}
|
||||
|
||||
.ripple-container .mud-button-outlined:focus-visible, .ripple-container .mud-button-outlined:active{
|
||||
background-color: unset !important;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
:root {
|
||||
/*Color*/
|
||||
--card-border-color: hsl(from var(--mud-palette-gray-light) h s 86%);
|
||||
--gray-for-shadow: hsl(from var(--mud-palette-overlay-dark)h s 40%);
|
||||
/*Utility*/
|
||||
--exception-box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.3);
|
||||
--custom-box-shadow: 1px 2px 5px var(--gray-for-shadow);
|
||||
/* Ombra morbida a due livelli, tinta col navy del brand: stacca le card dallo sfondo senza pesare */
|
||||
--card-box-shadow: 0 1px 2px rgba(0, 35, 57, 0.08), 0 6px 16px rgba(0, 35, 57, 0.10);
|
||||
--mud-default-borderradius: 20px !important;
|
||||
--m-page-x: 1rem;
|
||||
--mh-header: 4rem;
|
||||
|
||||
--light-card-background: hsl(from var(--mud-palette-background-gray) h s 97%);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* =============================================================================
|
||||
SteUP — Carattere
|
||||
Inter variabile, ospitato in locale. Non si carica da Google Fonts: l'app
|
||||
lavora in negozio con la rete incerta o assente, e un carattere che arriva
|
||||
dalla rete e' un carattere che in campo non arriva.
|
||||
========================================================================== */
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url("../fonts/inter-latin.woff2") format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
|
||||
U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url("../fonts/inter-latin-ext.woff2") format("woff2");
|
||||
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
|
||||
U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
|
||||
U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
.title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.customDialog-form.disable-safe-area .mud-dialog-content {
|
||||
margin-top: unset !important;
|
||||
}
|
||||
|
||||
.customDialog-form.disable-safe-area .content {
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.customDialog-form.mud-dialog {
|
||||
border-radius: unset !important;
|
||||
}
|
||||
|
||||
.customDialog-form .content {
|
||||
height: calc(100vh - (.6rem + 40px));
|
||||
overflow: auto;
|
||||
gap: 1.5rem;
|
||||
padding-top: unset !important;
|
||||
padding-bottom: 2rem !important;
|
||||
padding-left: .75rem !important;
|
||||
padding-right: .75rem !important;
|
||||
}
|
||||
|
||||
@supports (-webkit-touch-callout: none) {
|
||||
.customDialog-form .content {
|
||||
height: calc(100vh - (.6rem + 40px) - env(safe-area-inset-top)) !important;
|
||||
}
|
||||
|
||||
.customDialog-form.disable-safe-area .content {
|
||||
height: 100% !important;
|
||||
}
|
||||
|
||||
.customDialog-form.disable-safe-area .mud-dialog-content {
|
||||
margin-top: unset !important;
|
||||
}
|
||||
}
|
||||
|
||||
.customDialog-form .header {
|
||||
padding: 0 .75rem !important;
|
||||
}
|
||||
|
||||
.input-card {
|
||||
width: 100%;
|
||||
background: var(--mud-palette-background-gray);
|
||||
border-radius: 9px;
|
||||
padding: .5rem 1rem;
|
||||
}
|
||||
|
||||
.input-card.clearButton {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: .4rem 1rem !important;
|
||||
}
|
||||
|
||||
.input-card.clearButton.custom-border-bottom {
|
||||
border-bottom: .1rem solid var(--card-border-color);
|
||||
}
|
||||
|
||||
.input-card > .divider {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
min-height: 35px;
|
||||
}
|
||||
|
||||
.form-container > span {
|
||||
font-weight: 700;
|
||||
width: 50%;
|
||||
margin-right: .3rem;
|
||||
}
|
||||
|
||||
.form-container > .warning-text {
|
||||
font-weight: 700;
|
||||
color: var(--mud-palette-gray-darker);
|
||||
width: unset;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.form-container > .disable-full-width {
|
||||
width: unset !important;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dateTime-picker {
|
||||
display: flex;
|
||||
gap: .3rem;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/*Custom mudBlazor*/
|
||||
|
||||
.form-container .mud-input.mud-input-underline:before {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.form-container .mud-input.mud-input-underline:after {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.form-container.text-align-end .mud-input-slot {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.input-card .mud-input.mud-input-underline:before {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.input-card .mud-input.mud-input-underline:after {
|
||||
border-bottom: none !important;
|
||||
}
|
||||
|
||||
.form-container .customIcon-select .mud-icon-root.mud-svg-icon {
|
||||
rotate: 90deg !important;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.form-container .customIcon-select .mud-input-slot {
|
||||
text-align: end;
|
||||
}
|
||||
|
||||
.input-card .mud-input {
|
||||
width: 100%;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.container-button {
|
||||
width: 100%;
|
||||
background: var(--mud-palette-table-striped);
|
||||
padding: .5rem 0;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.container-button.remove-backgroud {
|
||||
background: unset !important;
|
||||
}
|
||||
|
||||
.container-button.mud-elevation-1 {
|
||||
background: unset !important;
|
||||
}
|
||||
|
||||
.container-button .divider {
|
||||
margin: .5rem 0 .5rem 3rem;
|
||||
width: unset;
|
||||
}
|
||||
|
||||
.container-button .button-settings {
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.container-button .button-settings .mud-icon-root {
|
||||
border-radius: 6px;
|
||||
padding: 2px;
|
||||
min-width: 25px;
|
||||
min-height: 25px;
|
||||
}
|
||||
|
||||
.container-button > .mud-button-root {
|
||||
padding-top: .15rem;
|
||||
padding-bottom: .15rem;
|
||||
}
|
||||
|
||||
.container-button .button-settings.gray-icon .mud-icon-root {
|
||||
border: 1px solid hsl(from var(--mud-palette-gray-darker) h s 88%);
|
||||
background: hsl(from var(--mud-palette-gray-darker) h s 88%);
|
||||
color: var(--mud-palette-dark);
|
||||
}
|
||||
|
||||
.container-button .button-settings.primary-icon .mud-icon-root {
|
||||
border: 1px solid hsl(from var(--mud-palette-primary) h s 95%);
|
||||
background: hsl(from var(--mud-palette-primary-lighten) h s 95%);
|
||||
color: var(--mud-palette-primary-darken);
|
||||
}
|
||||
|
||||
.container-button .button-settings.green-icon .mud-icon-root {
|
||||
border: 1px solid hsl(from var(--mud-palette-success-lighten) h s 95%);
|
||||
background: hsl(from var(--mud-palette-success-lighten) h s 95%);
|
||||
color: var(--mud-palette-success-darken);
|
||||
}
|
||||
|
||||
.container-button .button-settings.red-icon .mud-icon-root {
|
||||
border: 1px solid hsl(from var(--mud-palette-error-lighten) h s 95%);
|
||||
background: hsl(from var(--mud-palette-error-lighten) h s 95%);
|
||||
color: var(--mud-palette-error-darken);
|
||||
}
|
||||
|
||||
.container-button .button-settings .mud-button-label {
|
||||
justify-content: flex-start;
|
||||
text-transform: capitalize;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.container-button.ripple-container{
|
||||
overflow: clip;
|
||||
}
|
||||
|
||||
.container-button .button-settings.exit {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.container-button .button-settings.exit .mud-button-label {
|
||||
justify-content: center;
|
||||
font-size: 1.1rem;
|
||||
line-height: normal;
|
||||
}
|
||||
@@ -0,0 +1,392 @@
|
||||
/* =============================================================================
|
||||
SteUP — Form
|
||||
Il form scheda e' il cuore dell'app: si compila in piedi, con una mano.
|
||||
Ogni campo e' un blocco largo e tappabile, non una riga di tabella.
|
||||
========================================================================== */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Gruppo di campo — un Panel con la sua etichetta
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.form-group {
|
||||
background-color: var(--surface);
|
||||
border-radius: var(--radius-surface);
|
||||
padding: var(--space-md);
|
||||
}
|
||||
|
||||
.form-group__label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: var(--space-xs);
|
||||
font-size: var(--label-md-size);
|
||||
line-height: 1.25;
|
||||
font-weight: 600;
|
||||
color: var(--ink-muted);
|
||||
margin-bottom: var(--space-6);
|
||||
}
|
||||
|
||||
.form-group__count {
|
||||
font-size: var(--label-md-size);
|
||||
font-weight: 700;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
/* Il valore del campo: testo grande, tocco comodo. */
|
||||
.form-group .mud-input-control { margin: 0; }
|
||||
|
||||
.form-group .mud-input-slot,
|
||||
.form-group input,
|
||||
.form-group .mud-select-input {
|
||||
font-size: var(--body-lg-size);
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
min-height: var(--touch-min);
|
||||
}
|
||||
|
||||
.form-group--required .form-group__label::after {
|
||||
content: "obbligatorio";
|
||||
font-size: var(--label-sm-size);
|
||||
font-weight: 700;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.form-group--invalid { box-shadow: inset 0 0 0 1px var(--danger-solid); }
|
||||
|
||||
.form-error {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-6);
|
||||
margin-top: var(--space-xs);
|
||||
font-size: var(--body-md-size);
|
||||
font-weight: 600;
|
||||
color: var(--danger-ink);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Riga di scelta rapida (scadenza, priorita'): pillole invece di una select
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.option-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--space-xs);
|
||||
}
|
||||
|
||||
.option {
|
||||
flex: 1 1 auto;
|
||||
min-width: 96px;
|
||||
min-height: var(--touch-min);
|
||||
padding: var(--space-xs) var(--space-sm);
|
||||
border-radius: var(--radius-pill);
|
||||
border: 1px solid var(--divider);
|
||||
background-color: var(--surface-muted);
|
||||
color: var(--ink-muted);
|
||||
font-family: inherit;
|
||||
font-size: var(--label-lg-size);
|
||||
font-weight: 600;
|
||||
transition: background-color var(--duration-fast) var(--ease-out),
|
||||
border-color var(--duration-fast) var(--ease-out),
|
||||
color var(--duration-fast) var(--ease-out),
|
||||
transform var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.option:active { transform: scale(0.97); }
|
||||
|
||||
.option[aria-pressed="true"] {
|
||||
background-color: var(--info-surface);
|
||||
border-color: var(--primary);
|
||||
color: var(--primary-dark);
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.option:active { transform: none; }
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Campo barcode manuale — affiancato al pulsante di invio
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.barcode-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
padding: var(--space-xs) var(--space-xs) var(--space-xs) var(--space-md);
|
||||
border-radius: var(--radius-pill);
|
||||
background-color: var(--surface-muted);
|
||||
border: 1.5px solid transparent;
|
||||
transition: border-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.barcode-field:focus-within { border-color: var(--primary); }
|
||||
|
||||
.barcode-field input {
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
min-height: var(--touch-min);
|
||||
border: none;
|
||||
background: none;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
font-size: var(--body-lg-size);
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
/* Il codice si legge cifra per cifra: cifre a larghezza fissa. */
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.barcode-field input::placeholder { color: var(--ink-muted); font-weight: 400; }
|
||||
|
||||
.barcode-field__send {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--touch-min);
|
||||
height: var(--touch-min);
|
||||
border: none;
|
||||
border-radius: var(--radius-pill);
|
||||
background-color: var(--primary);
|
||||
color: var(--on-primary);
|
||||
font-size: 20px;
|
||||
transition: transform var(--duration-fast) var(--ease-out),
|
||||
background-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.barcode-field__send:active { transform: scale(0.92); background-color: var(--primary-pressed); }
|
||||
.barcode-field__send:disabled { background-color: var(--divider); color: var(--ink-muted); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Articoli scansionati
|
||||
L'ultimo letto entra dall'alto: e' la conferma visiva della scansione.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.art-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-xs);
|
||||
}
|
||||
|
||||
.art-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
padding: var(--space-10) var(--space-sm);
|
||||
border-radius: var(--radius-control);
|
||||
background-color: var(--surface-muted);
|
||||
animation: art-enter var(--duration-slow) var(--ease-out);
|
||||
}
|
||||
|
||||
@keyframes art-enter {
|
||||
from { opacity: 0; transform: translateY(-6px); }
|
||||
to { opacity: 1; transform: none; }
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.art-item { animation: none; }
|
||||
}
|
||||
|
||||
.art-item__text { flex: 1 1 auto; min-width: 0; }
|
||||
|
||||
.art-item__name {
|
||||
font-size: var(--body-lg-size);
|
||||
line-height: 1.25;
|
||||
font-weight: 700;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.art-item__code {
|
||||
margin-top: var(--space-2);
|
||||
font-size: var(--label-md-size);
|
||||
font-weight: 600;
|
||||
color: var(--ink-muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.art-item__remove {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--touch-min);
|
||||
height: var(--touch-min);
|
||||
border: none;
|
||||
border-radius: var(--radius-pill);
|
||||
background: none;
|
||||
color: var(--ink-muted);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.art-item__remove:active { background-color: var(--danger-surface); color: var(--danger-ink); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Foto allegate — striscia orizzontale scorrevole
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.attach-strip {
|
||||
display: flex;
|
||||
gap: var(--space-xs);
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
padding-inline: var(--space-md);
|
||||
margin-inline: calc(var(--space-md) * -1);
|
||||
}
|
||||
|
||||
.attach-strip::-webkit-scrollbar { display: none; }
|
||||
|
||||
.attach-item {
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
width: 104px;
|
||||
border-radius: var(--radius-control);
|
||||
overflow: hidden;
|
||||
background-color: var(--surface-muted);
|
||||
}
|
||||
|
||||
.attach-item__img {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
object-fit: cover;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.attach-item__placeholder {
|
||||
width: 104px;
|
||||
height: 104px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--ink-muted);
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.attach-item__remove {
|
||||
position: absolute;
|
||||
top: var(--space-4);
|
||||
right: var(--space-4);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border: none;
|
||||
border-radius: var(--radius-pill);
|
||||
background-color: rgba(0, 0, 0, 0.62);
|
||||
color: #ffffff;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.attach-item__remove:active { background-color: var(--danger-solid); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Bottone di azione secondaria con icona in pastiglia
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.action-tile {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
width: 100%;
|
||||
min-height: 56px;
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
border: 1px solid var(--divider);
|
||||
border-radius: var(--radius-control);
|
||||
background-color: var(--surface);
|
||||
font-family: inherit;
|
||||
font-size: var(--body-lg-size);
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
text-align: left;
|
||||
transition: transform var(--duration-fast) var(--ease-out),
|
||||
background-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.action-tile:active { transform: scale(0.99); background-color: var(--surface-muted); }
|
||||
.action-tile:disabled { color: var(--ink-muted); }
|
||||
|
||||
.action-tile__icon {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
border-radius: var(--radius-compact);
|
||||
font-size: 20px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.action-tile__icon--neutral { background-color: var(--neutral-surface); color: var(--neutral-ink); }
|
||||
.action-tile__icon--primary { background-color: var(--danger-surface); color: var(--primary); }
|
||||
.action-tile__icon--success { background-color: var(--success-surface); color: var(--success-ink); }
|
||||
.action-tile__icon--danger { background-color: var(--danger-surface); color: var(--danger-ink); }
|
||||
.action-tile__icon--info { background-color: var(--info-surface); color: var(--info-ink); }
|
||||
|
||||
.action-tile__label { flex: 1 1 auto; min-width: 0; }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.action-tile:active { transform: none; }
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Riga di selezione multipla
|
||||
Una riga larga e tappabile al posto di un menu a tendina: con i guanti si
|
||||
centra un bersaglio da 56px, non una casella da 18.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.select-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
width: 100%;
|
||||
min-height: 56px;
|
||||
padding: var(--space-10) var(--space-sm);
|
||||
border: none;
|
||||
border-radius: var(--radius-control);
|
||||
background-color: var(--surface);
|
||||
font-family: inherit;
|
||||
text-align: left;
|
||||
transition: background-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.select-row[aria-pressed="true"] { background-color: var(--info-surface); }
|
||||
|
||||
.select-row__check {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
border-radius: var(--radius-compact);
|
||||
border: 2px solid var(--divider);
|
||||
background-color: var(--surface);
|
||||
color: transparent;
|
||||
font-size: 18px;
|
||||
transition: background-color var(--duration-fast) var(--ease-out),
|
||||
border-color var(--duration-fast) var(--ease-out),
|
||||
color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.select-row[aria-pressed="true"] .select-row__check {
|
||||
background-color: var(--primary);
|
||||
border-color: var(--primary);
|
||||
color: var(--on-primary);
|
||||
}
|
||||
|
||||
.select-row__text { flex: 1 1 auto; min-width: 0; }
|
||||
|
||||
.select-row__title {
|
||||
font-size: var(--body-lg-size);
|
||||
line-height: 1.3;
|
||||
font-weight: 600;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.select-row__meta {
|
||||
margin-top: var(--space-2);
|
||||
font-size: var(--label-md-size);
|
||||
font-weight: 600;
|
||||
color: var(--ink-muted);
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
@@ -0,0 +1,409 @@
|
||||
/* =============================================================================
|
||||
SteUP — MudBlazor riportato allo stile condiviso
|
||||
MudBlazor e' Material 2 di default: ombre per costruire gerarchia, tinte
|
||||
automatiche sulle superfici, target stretti. Qui lo si appiattisce secondo
|
||||
STILE_UI §1 e §5, cosi' i controlli di libreria e i componenti propri
|
||||
parlano la stessa lingua.
|
||||
========================================================================== */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Aggancio delle variabili di MudBlazor ai token del progetto.
|
||||
I token restano l'unica fonte di verita': cambiare un ruolo in tokens.css
|
||||
aggiorna sia i componenti propri sia quelli di libreria.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
:root {
|
||||
--mud-palette-primary: var(--primary);
|
||||
--mud-palette-primary-text: var(--on-primary);
|
||||
--mud-palette-secondary: var(--primary-dark);
|
||||
--mud-palette-tertiary: var(--info-surface);
|
||||
--mud-palette-surface: var(--surface);
|
||||
--mud-palette-background: var(--workspace);
|
||||
--mud-palette-background-gray: var(--workspace);
|
||||
--mud-palette-text-primary: var(--ink);
|
||||
--mud-palette-text-secondary: var(--ink-muted);
|
||||
--mud-palette-text-disabled: var(--ink-muted);
|
||||
--mud-palette-action-default: var(--ink-muted);
|
||||
--mud-palette-lines-default: var(--divider);
|
||||
--mud-palette-lines-inputs: var(--divider);
|
||||
--mud-palette-divider: var(--divider);
|
||||
--mud-palette-divider-light: var(--divider);
|
||||
--mud-palette-error: var(--danger-solid);
|
||||
--mud-palette-error-text: #ffffff;
|
||||
--mud-palette-success: var(--success-solid);
|
||||
--mud-palette-warning: var(--warning-solid);
|
||||
--mud-palette-info: var(--info-solid);
|
||||
|
||||
--mud-default-borderradius: var(--radius-control);
|
||||
|
||||
/* Tipografia: stessa scala dei token (STILE_UI §4). */
|
||||
--mud-typography-default-family: "Inter", "SF Pro Display", "Roboto", system-ui, sans-serif;
|
||||
--mud-typography-default-size: var(--body-lg-size);
|
||||
--mud-typography-default-weight: 400;
|
||||
--mud-typography-default-lineheight: var(--body-lg-height);
|
||||
--mud-typography-default-letterspacing: normal;
|
||||
|
||||
--mud-typography-h5-family: var(--mud-typography-default-family);
|
||||
--mud-typography-h5-size: var(--headline-sm-size);
|
||||
--mud-typography-h5-weight: 700;
|
||||
--mud-typography-h5-lineheight: var(--headline-sm-height);
|
||||
|
||||
--mud-typography-h6-family: var(--mud-typography-default-family);
|
||||
--mud-typography-h6-size: var(--title-lg-size);
|
||||
--mud-typography-h6-weight: 700;
|
||||
--mud-typography-h6-lineheight: var(--title-lg-height);
|
||||
|
||||
--mud-typography-subtitle1-family: var(--mud-typography-default-family);
|
||||
--mud-typography-subtitle1-size: var(--title-md-size);
|
||||
--mud-typography-subtitle1-weight: 700;
|
||||
--mud-typography-subtitle1-lineheight: var(--title-md-height);
|
||||
|
||||
--mud-typography-subtitle2-family: var(--mud-typography-default-family);
|
||||
--mud-typography-subtitle2-size: var(--body-md-size);
|
||||
--mud-typography-subtitle2-weight: 600;
|
||||
|
||||
--mud-typography-body1-family: var(--mud-typography-default-family);
|
||||
--mud-typography-body1-size: var(--body-lg-size);
|
||||
--mud-typography-body1-lineheight: var(--body-lg-height);
|
||||
|
||||
--mud-typography-body2-family: var(--mud-typography-default-family);
|
||||
--mud-typography-body2-size: var(--body-md-size);
|
||||
--mud-typography-body2-lineheight: var(--body-md-height);
|
||||
|
||||
--mud-typography-button-family: var(--mud-typography-default-family);
|
||||
--mud-typography-button-size: var(--label-lg-size);
|
||||
--mud-typography-button-weight: 600;
|
||||
--mud-typography-button-transform: none;
|
||||
--mud-typography-button-letterspacing: normal;
|
||||
|
||||
--mud-typography-caption-family: var(--mud-typography-default-family);
|
||||
--mud-typography-caption-size: var(--label-md-size);
|
||||
--mud-typography-caption-weight: 600;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
§1 Superfici piatte, nessun tint automatico
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-paper,
|
||||
.mud-card,
|
||||
.mud-expansion-panels .mud-expand-panel,
|
||||
.mud-toolbar,
|
||||
.mud-appbar {
|
||||
box-shadow: none !important;
|
||||
background-image: none !important;
|
||||
background-color: var(--surface);
|
||||
border-radius: var(--radius-surface);
|
||||
}
|
||||
|
||||
.mud-elevation-0, .mud-elevation-1, .mud-elevation-2, .mud-elevation-3,
|
||||
.mud-elevation-4, .mud-elevation-5, .mud-elevation-6, .mud-elevation-8,
|
||||
.mud-elevation-12, .mud-elevation-16, .mud-elevation-24 {
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* I livelli che galleggiano davvero conservano un contorno, non un'ombra. */
|
||||
.mud-popover.mud-popover-open,
|
||||
.mud-picker-popover-paper,
|
||||
.mud-menu-popover {
|
||||
border-radius: var(--radius-control) !important;
|
||||
border: 1px solid var(--divider);
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
§5 Bottoni — target 44/48, raggio control, etichette in caso naturale
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-button-root {
|
||||
min-height: var(--touch-min);
|
||||
border-radius: var(--radius-control);
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--label-lg-size);
|
||||
font-weight: 600;
|
||||
line-height: 1.25;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
transition: transform var(--duration-fast) var(--ease-out),
|
||||
background-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.mud-button-root:active { transform: scale(0.97); }
|
||||
|
||||
.mud-button-filled {
|
||||
min-height: var(--button-height);
|
||||
box-shadow: none !important;
|
||||
padding-inline: var(--space-lg);
|
||||
}
|
||||
|
||||
.mud-button-filled.mud-button-filled-primary {
|
||||
background-color: var(--primary);
|
||||
color: var(--on-primary);
|
||||
}
|
||||
|
||||
.mud-button-filled.mud-button-filled-primary:hover,
|
||||
.mud-button-filled.mud-button-filled-primary:active {
|
||||
background-color: var(--primary-pressed);
|
||||
}
|
||||
|
||||
.mud-button-outlined {
|
||||
min-height: var(--button-height);
|
||||
border: 1px solid var(--divider);
|
||||
color: var(--ink);
|
||||
padding-inline: var(--space-lg);
|
||||
}
|
||||
|
||||
.mud-button-text { min-height: var(--touch-min); }
|
||||
|
||||
.mud-icon-button {
|
||||
min-width: var(--touch-min);
|
||||
min-height: var(--touch-min);
|
||||
border-radius: var(--radius-pill);
|
||||
transition: transform var(--duration-fast) var(--ease-out),
|
||||
background-color var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.mud-icon-button:active { transform: scale(0.92); }
|
||||
|
||||
/* Il FAB circolare al centro e' una firma Android di serie (§1.7): qui i FAB
|
||||
sono rettangolari e stondati come il resto dei controlli. */
|
||||
.mud-fab {
|
||||
box-shadow: none !important;
|
||||
border-radius: var(--radius-control);
|
||||
min-height: var(--touch-min);
|
||||
font-family: var(--font-sans);
|
||||
font-weight: 600;
|
||||
text-transform: none;
|
||||
letter-spacing: normal;
|
||||
}
|
||||
|
||||
.mud-fab.mud-fab-primary { background-color: var(--primary); color: var(--on-primary); }
|
||||
.mud-fab.mud-fab-default { background-color: var(--surface-muted); color: var(--ink); }
|
||||
.mud-fab:active { transform: scale(0.96); }
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
.mud-button-root:active,
|
||||
.mud-icon-button:active,
|
||||
.mud-fab:active { transform: none; }
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
§5 Campi — riempiti, raggio control, bordo 1px a riposo e 2px in focus
|
||||
La sottolineatura Material viene rimossa: i campi sono schede, non righe.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-input.mud-input-text,
|
||||
.mud-input.mud-input-filled,
|
||||
.mud-input-control .mud-input-slot {
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--body-lg-size);
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.mud-input:before,
|
||||
.mud-input:after,
|
||||
.mud-input-filled:before,
|
||||
.mud-input-filled:after,
|
||||
.mud-input-underline:before,
|
||||
.mud-input-underline:after {
|
||||
display: none !important;
|
||||
border: none !important;
|
||||
}
|
||||
|
||||
.field-shell {
|
||||
background-color: var(--surface);
|
||||
border: 1px solid var(--divider);
|
||||
border-radius: var(--radius-control);
|
||||
padding: var(--space-md);
|
||||
transition: border-color var(--duration-fast) var(--ease-out),
|
||||
box-shadow var(--duration-fast) var(--ease-out);
|
||||
}
|
||||
|
||||
.field-shell:focus-within {
|
||||
border-color: var(--primary);
|
||||
box-shadow: inset 0 0 0 1px var(--primary);
|
||||
}
|
||||
|
||||
.field-shell--error { border-color: var(--danger-solid); }
|
||||
.field-shell--muted { background-color: var(--surface-muted); }
|
||||
|
||||
.mud-input-label,
|
||||
.mud-input-helper-text {
|
||||
font-family: var(--font-sans);
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.mud-input-helper-text.mud-input-error,
|
||||
.mud-input-error .mud-input-helper-text {
|
||||
color: var(--danger-ink);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Il testo segnaposto deve restare leggibile al sole: stesso contrasto del
|
||||
testo secondario, non il grigio chiarissimo di serie. */
|
||||
.mud-input input::placeholder,
|
||||
.mud-input textarea::placeholder {
|
||||
color: var(--ink-muted);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.mud-select .mud-input-adornment .mud-icon-root { color: var(--ink-muted); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Select, liste e voci di menu
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-list-item {
|
||||
min-height: var(--touch-min);
|
||||
border-radius: var(--radius-compact);
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--body-lg-size);
|
||||
}
|
||||
|
||||
.mud-list-item.mud-selected-item {
|
||||
background-color: var(--info-surface);
|
||||
color: var(--primary-dark);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.custom-item-select { padding-block: var(--space-xs); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Chip
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-chip {
|
||||
border-radius: var(--radius-pill);
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--label-sm-size);
|
||||
font-weight: 700;
|
||||
letter-spacing: normal;
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
.mud-chip.mud-chip-filled.mud-chip-color-default {
|
||||
background-color: var(--neutral-surface);
|
||||
color: var(--neutral-ink);
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Pannelli a fisarmonica — nessun bordo di serie, nessuna ombra
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-expansion-panels { width: 100%; }
|
||||
|
||||
.mud-expand-panel {
|
||||
background-color: transparent !important;
|
||||
border: none !important;
|
||||
margin-block: 0 !important;
|
||||
}
|
||||
|
||||
.mud-expand-panel .mud-expand-panel-header {
|
||||
padding: var(--space-sm) 0;
|
||||
min-height: var(--touch-min);
|
||||
}
|
||||
|
||||
.mud-expand-panel .mud-expand-panel-content { padding: 0; }
|
||||
.mud-expand-panel::before { display: none !important; }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
§6.10 Dialog
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-dialog {
|
||||
border-radius: var(--radius-surface) !important;
|
||||
background-color: var(--surface);
|
||||
box-shadow: none !important;
|
||||
max-width: 420px;
|
||||
width: calc(100vw - 48px);
|
||||
}
|
||||
|
||||
.mud-dialog-title {
|
||||
padding: var(--space-lg) var(--space-lg) 0;
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--title-md-size);
|
||||
line-height: var(--title-md-height);
|
||||
font-weight: 700;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.mud-dialog-content {
|
||||
padding: var(--space-xs) var(--space-lg) 0;
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--body-lg-size);
|
||||
line-height: 1.45;
|
||||
color: var(--ink-muted);
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.mud-dialog-actions {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
padding: var(--space-lg);
|
||||
}
|
||||
|
||||
.mud-dialog-actions > * { flex: 1 1 0; margin: 0 !important; }
|
||||
|
||||
/* Il form scheda e' a schermo pieno: e' una schermata, non un riquadro. */
|
||||
.mud-dialog.customDialog-form {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-height: 100%;
|
||||
margin: 0;
|
||||
border-radius: 0 !important;
|
||||
background-color: var(--workspace);
|
||||
}
|
||||
|
||||
.mud-dialog.customDialog-form .mud-dialog-content {
|
||||
padding: 0;
|
||||
max-height: 100%;
|
||||
height: 100%;
|
||||
color: var(--ink);
|
||||
}
|
||||
|
||||
.mud-overlay { z-index: var(--z-overlay); }
|
||||
.mud-overlay.on-top { z-index: var(--z-modal) !important; }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
§6.9 Toast — riempimento pieno del tono, testo bianco, l'unica ombra
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-snackbar {
|
||||
border-radius: var(--radius-control) !important;
|
||||
box-shadow: var(--shadow-toast) !important;
|
||||
font-family: var(--font-sans);
|
||||
font-size: var(--body-lg-size);
|
||||
font-weight: 600;
|
||||
line-height: 1.35;
|
||||
color: #ffffff !important;
|
||||
padding: var(--space-sm) var(--space-14) !important;
|
||||
z-index: var(--z-toast);
|
||||
}
|
||||
|
||||
.mud-snackbar.mud-alert-filled-success { background-color: var(--success-solid) !important; }
|
||||
.mud-snackbar.mud-alert-filled-error { background-color: var(--danger-solid) !important; }
|
||||
.mud-snackbar.mud-alert-filled-warning { background-color: var(--warning-solid) !important; }
|
||||
.mud-snackbar.mud-alert-filled-info { background-color: var(--info-solid) !important; }
|
||||
.mud-snackbar .mud-snackbar-content-message { color: #ffffff !important; }
|
||||
.mud-snackbar .mud-icon-root { color: #ffffff !important; }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Progresso
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.mud-progress-linear { border-radius: var(--radius-compact); height: 8px; }
|
||||
.mud-progress-linear .mud-progress-linear-bar { background-color: var(--primary); }
|
||||
.mud-progress-circular.mud-primary-text { color: var(--primary); }
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
Il ripple di Mud viene disattivato dove il contenitore ha il proprio
|
||||
feedback al tocco, per non avere due risposte sovrapposte allo stesso dito.
|
||||
-------------------------------------------------------------------------- */
|
||||
|
||||
.ripple-container .mud-ripple-effect,
|
||||
.ripple-container .mud-ripple-effect-expanding {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.mud-skeleton { border-radius: var(--radius-compact) !important; }
|
||||
@@ -0,0 +1,167 @@
|
||||
/* =============================================================================
|
||||
SteUP — Token di design
|
||||
Implementa STILE_UI.md §2 (ruoli colore) e §3 (scale) sulla palette SteUP.
|
||||
Regola: nelle pagine si usano SOLO questi token. Un colore o un raggio
|
||||
scritto a mano in una schermata e' un difetto, non una scorciatoia.
|
||||
========================================================================== */
|
||||
|
||||
:root {
|
||||
/* -------------------------------------------------------------------------
|
||||
COLORE — ruoli semantici (STILE_UI §2)
|
||||
La palette storica di SteUP resta intatta: corallo azione, navy ancora,
|
||||
azzurro tenue informativo. Sono stati aggiunti solo i ruoli che
|
||||
mancavano: workspace, surfaceMuted, divider, inkMuted e le coppie
|
||||
(foreground forte / superficie tenue) dei toni semantici.
|
||||
---------------------------------------------------------------------- */
|
||||
|
||||
/* Accento unico di azione. La sua rarita' e' cio' che lo rende un segnale. */
|
||||
--primary: #ec4c41;
|
||||
--primary-pressed: #d23a30;
|
||||
--on-primary: #ffffff;
|
||||
|
||||
/* Ancora della struttura: testo forte, icone metrica, foreground su info. */
|
||||
--primary-dark: #002339;
|
||||
|
||||
/* Superfici: lo sfondo pagina e' piu' freddo delle superfici di lavoro.
|
||||
Tre gradini netti, cosi' i pannelli staccano senza bisogno di ombre. */
|
||||
--workspace: #e9edf2;
|
||||
--surface: #ffffff;
|
||||
--surface-muted: #f4f6f9;
|
||||
--divider: #d9e0e8;
|
||||
|
||||
/* Testo. Inchiostro pieno per la lettura in pieno sole (Regola del
|
||||
Contrasto da Sole): niente grigio chiaro sul corpo del testo. */
|
||||
--ink: #000000;
|
||||
--ink-muted: #465563; /* 8.3:1 su surface, 7.4:1 su workspace */
|
||||
|
||||
/* --- Toni semantici -----------------------------------------------------
|
||||
Ogni tono e' una tripletta:
|
||||
-ink foreground forte: testo e icone sopra la superficie tenue
|
||||
-surface riempimento tenue: badge, pannelli, cerchi-icona dei dialog
|
||||
-solid riempimento pieno: toast (testo bianco sopra)
|
||||
Gli -ink sono scelti per superare 4.5:1 sulla propria superficie tenue:
|
||||
i colori "puri" della palette restano per icone e riempimenti pieni,
|
||||
dove il contrasto di testo non e' in gioco.
|
||||
-------------------------------------------------------------------- */
|
||||
|
||||
/* Danger — errori, azioni distruttive, priorita' massima */
|
||||
--danger-ink: #b3120c;
|
||||
--danger-surface: #fdeceb;
|
||||
--danger-solid: #e50000;
|
||||
|
||||
/* Warning — attenzione, dati incompleti, bozze da completare */
|
||||
--warning-ink: #8a4f00;
|
||||
--warning-surface: #fdf0db;
|
||||
--warning-solid: #b26a00;
|
||||
|
||||
/* Success — conferme, completamenti, sincronizzato */
|
||||
--success-ink: #10702f;
|
||||
--success-surface: #e4f5e9;
|
||||
--success-solid: #26b050;
|
||||
|
||||
/* Info — stato informativo, pannelli di riepilogo, selezione */
|
||||
--info-ink: #002339;
|
||||
--info-surface: #dff2ff;
|
||||
--info-solid: #1877d8;
|
||||
|
||||
/* Neutral — stati senza carica semantica */
|
||||
--neutral-ink: #465563;
|
||||
--neutral-surface: #f4f6f9;
|
||||
--neutral-solid: #465563;
|
||||
|
||||
/* Focus da tastiera */
|
||||
--focus-ring: #258cfb;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
SPAZIATURA (STILE_UI §3)
|
||||
---------------------------------------------------------------------- */
|
||||
--space-xs: 8px;
|
||||
--space-sm: 12px;
|
||||
--space-md: 16px;
|
||||
--space-lg: 24px;
|
||||
--space-xl: 32px;
|
||||
|
||||
/* Micro-distanze derivate, d'uso frequente */
|
||||
--space-2: 2px;
|
||||
--space-4: 4px;
|
||||
--space-6: 6px;
|
||||
--space-10: 10px; /* tra le card di una lista */
|
||||
--space-14: 14px;
|
||||
--space-18: 18px; /* padding dei pannelli di testata */
|
||||
--space-20: 20px;
|
||||
--space-22: 22px;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
RAGGI (STILE_UI §3)
|
||||
Superfici piu' arrotondate dei controlli; stati completamente stondati.
|
||||
---------------------------------------------------------------------- */
|
||||
--radius-compact: 8px;
|
||||
--radius-control: 16px;
|
||||
--radius-surface: 20px;
|
||||
--radius-pill: 999px;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
TIPOGRAFIA (STILE_UI §4)
|
||||
Scala fissa: si legge a colpo d'occhio, non fa effetto editoriale.
|
||||
---------------------------------------------------------------------- */
|
||||
--font-sans: "Inter", "SF Pro Display", "Roboto", system-ui, sans-serif;
|
||||
|
||||
--headline-md-size: 34px;
|
||||
--headline-md-height: 1.2;
|
||||
--headline-sm-size: 28px;
|
||||
--headline-sm-height: 1.25;
|
||||
--title-lg-size: 22px;
|
||||
--title-lg-height: 1.3;
|
||||
--title-md-size: 18px;
|
||||
--title-md-height: 1.35;
|
||||
--body-lg-size: 16px;
|
||||
--body-lg-height: 1.5;
|
||||
--body-md-size: 15px;
|
||||
--body-md-height: 1.45;
|
||||
--label-lg-size: 14px;
|
||||
--label-md-size: 13px;
|
||||
--label-sm-size: 12px;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
MISURE STRUTTURALI
|
||||
---------------------------------------------------------------------- */
|
||||
--appbar-height: 80px;
|
||||
--navbar-height: 68px;
|
||||
--touch-min: 44px;
|
||||
--button-height: 48px;
|
||||
--content-max: 920px;
|
||||
|
||||
/* Spazio che le pagine lasciano in fondo per non finire sotto la barra
|
||||
flottante di navigazione (STILE_UI §6.15). */
|
||||
--nav-clearance: 116px;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
MOVIMENTO
|
||||
Curve esponenziali in uscita: il movimento serve allo stato, mai alla
|
||||
scena. Durate da prodotto, l'utente e' dentro un compito.
|
||||
---------------------------------------------------------------------- */
|
||||
--ease-out: cubic-bezier(0.22, 1, 0.36, 1);
|
||||
--ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
|
||||
--duration-fast: 120ms;
|
||||
--duration-base: 200ms;
|
||||
--duration-slow: 280ms;
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
PROFONDITA' — scala semantica, mai valori arbitrari
|
||||
Le superfici sono piatte (STILE_UI §1): questi livelli ordinano solo
|
||||
cio' che galleggia davvero.
|
||||
---------------------------------------------------------------------- */
|
||||
--z-base: 0;
|
||||
--z-sticky: 10;
|
||||
--z-navbar: 20;
|
||||
--z-connection: 30;
|
||||
--z-overlay: 40;
|
||||
--z-modal: 50;
|
||||
--z-toast: 60;
|
||||
|
||||
/* L'unica ombra del sistema: il toast (STILE_UI §6.9). */
|
||||
--shadow-toast: 0 6px 20px rgba(0, 0, 0, 0.24);
|
||||
|
||||
/* Breakpoint (STILE_UI §3) — documentati qui, usati nelle media query:
|
||||
rail 720px · twoColumn 900px · contentMax 1180px */
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,105 +1,14 @@
|
||||
// Funzione goBack
|
||||
// Interoperabilità minima con l'host. Il feedback al tocco e gli stati sono
|
||||
// gestiti in CSS: qui resta solo ciò che il CSS non può fare.
|
||||
|
||||
window.goBack = function () {
|
||||
console.log("goBack");
|
||||
history.back();
|
||||
};
|
||||
|
||||
// Funzione per monitorare bottom-sheet-container e gestire la navbar
|
||||
function monitorBottomSheetClass(mutations) {
|
||||
const bottomSheet = document.querySelector(".bottom-sheet-container");
|
||||
const navbar = document.querySelector(".animated-navbar");
|
||||
|
||||
if (!bottomSheet || !navbar) return;
|
||||
|
||||
mutations.forEach(function (mutation) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target === bottomSheet) {
|
||||
if (bottomSheet.classList.contains("show")) {
|
||||
navbar.classList.remove("show-nav");
|
||||
navbar.classList.add("hide-nav");
|
||||
console.log("Navbar nascosta (hide-nav)");
|
||||
} else {
|
||||
navbar.classList.remove("hide-nav");
|
||||
navbar.classList.add("show-nav");
|
||||
console.log("Navbar mostrata (show-nav)");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Observer combinato per tutte le funzionalità
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
// Monitora bottom-sheet-container
|
||||
monitorBottomSheetClass(mutations);
|
||||
});
|
||||
|
||||
// Osserva sia i cambiamenti nel DOM che gli attributi
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true,
|
||||
attributeFilter: ['class']
|
||||
});
|
||||
|
||||
// Sync iniziale per la navbar (nel caso la pagina parte già con .show)
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
const bottomSheet = document.querySelector(".bottom-sheet-container");
|
||||
const navbar = document.querySelector(".animated-navbar");
|
||||
|
||||
if (bottomSheet && navbar) {
|
||||
if (bottomSheet.classList.contains("show")) {
|
||||
navbar.classList.remove("show-nav");
|
||||
navbar.classList.add("hide-nav");
|
||||
} else {
|
||||
navbar.classList.remove("hide-nav");
|
||||
navbar.classList.add("show-nav");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
(function () {
|
||||
// Ascoltiamo l'evento 'mousedown' su tutto il documento
|
||||
document.addEventListener('mousedown', function (event) {
|
||||
|
||||
// Cerca se l'elemento cliccato (o un suo genitore) ha la classe .ripple-container
|
||||
const target = event.target.closest('.ripple-container');
|
||||
|
||||
if (target) {
|
||||
createRipple(event, target);
|
||||
}
|
||||
});
|
||||
|
||||
function createRipple(event, element) {
|
||||
const circle = document.createElement("span");
|
||||
const diameter = Math.max(element.clientWidth, element.clientHeight);
|
||||
const radius = diameter / 2;
|
||||
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
circle.style.width = circle.style.height = `${diameter}px`;
|
||||
circle.style.left = `${event.clientX - rect.left - radius}px`;
|
||||
circle.style.top = `${event.clientY - rect.top - radius}px`;
|
||||
circle.classList.add("ripple");
|
||||
|
||||
// Rimuovi l'elemento dal DOM alla fine dell'animazione per non intasare la memoria
|
||||
const ripple = element.getElementsByClassName("ripple")[0];
|
||||
if (ripple) {
|
||||
ripple.remove();
|
||||
}
|
||||
|
||||
element.appendChild(circle);
|
||||
|
||||
// Pulizia automatica dopo 600ms (durata animazione CSS)
|
||||
setTimeout(() => {
|
||||
circle.remove();
|
||||
}, 600);
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
// Tastiera: porta il campo attivo dentro l'area visibile.
|
||||
// Il layout e' a 100vh con overflow:hidden, quindi quando l'host riduce la
|
||||
// WebView per la tastiera il browser non scrolla da solo sul campo col focus.
|
||||
// Il layout e' a piena altezza con lo scroll in un contenitore, quindi quando
|
||||
// l'host riduce la WebView per la tastiera il browser non scrolla da solo sul
|
||||
// campo col focus.
|
||||
(function () {
|
||||
const SELECTOR = 'input, textarea, [contenteditable="true"]';
|
||||
let pending = null;
|
||||
@@ -130,3 +39,16 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
window.addEventListener('resize', schedule);
|
||||
}
|
||||
})();
|
||||
|
||||
// Un doppio tocco ravvicinato su una WebView fa zoomare la pagina: e' il
|
||||
// gesto del browser, non quello di un'app. Il viewport lo vieta gia', questo
|
||||
// copre i casi in cui Android lo reintroduce.
|
||||
(function () {
|
||||
let lastTouch = 0;
|
||||
|
||||
document.addEventListener('touchend', function (event) {
|
||||
const now = Date.now();
|
||||
if (now - lastTouch <= 320) event.preventDefault();
|
||||
lastTouch = now;
|
||||
}, {passive: false});
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user