Ridisegna la schermata di accesso

Ogni campo era un riquadro dentro il riquadro, con l'etichetta che saltava
sopra il testo al primo tocco: un modulo web, non una schermata. Ora i tre
campi stanno in un pannello solo diviso da una linea, come le liste del resto
dell'app, e l'etichetta sta ferma sopra il campo.

Lo sfondo passa alla superficie di lavoro, la stessa dello splash e della prima
schermata: l'avvio non cambia colore tre volte. L'errore di accesso usa il
riquadro di avviso gia' in uso dentro l'app invece di uno stile suo.

Non verificata sul terminale: la sessione sul dispositivo e' aperta e non l'ho
chiusa per non far perdere l'accesso.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-17 12:47:36 +02:00
parent 4e61dc011f
commit 66ed92299b
2 changed files with 93 additions and 44 deletions
+36 -27
View File
@@ -19,32 +19,48 @@
<form class="onboarding__panel" @onsubmit="SignInUser" @onsubmit:preventDefault="true"> <form class="onboarding__panel" @onsubmit="SignInUser" @onsubmit:preventDefault="true">
<img src="_content/SteUp.Shared/images/logo_steup.svg" class="onboarding__logo" alt="SteUP"/> <img src="_content/SteUp.Shared/images/logo_steup.svg" class="onboarding__logo" alt="SteUP"/>
@* Un solo pannello con tre righe divise da una linea, come le liste
del resto dell'app. Prima ogni campo era un riquadro dentro il
riquadro, con l'etichetta che saltava sopra il testo al primo tocco:
un gesto da modulo web, non da applicazione. Qui l'etichetta sta
ferma sopra il campo e non si muove mai. *@
<div class="onboarding__fields"> <div class="onboarding__fields">
<div class="onboarding__field"> <label class="onboarding__field">
<MudTextField @bind-Value="UserData.Username" Label="Username" <span class="onboarding__label">Username</span>
Variant="Variant.Text" Immediate="true" <input class="onboarding__input" type="text" autocomplete="username"
UserAttributes="@(new() { ["autocomplete"] = "username", ["enterkeyhint"] = "next", ["autocapitalize"] = "none" })"/> autocapitalize="none" autocorrect="off" enterkeyhint="next"
</div> value="@UserData.Username" @oninput="@(e => UserData.Username = e.Value?.ToString())"/>
</label>
<div class="onboarding__field"> <label class="onboarding__field">
<MudTextField InputType="@_passwordInput" @bind-Value="UserData.Password" Label="Password" <span class="onboarding__label">Password</span>
Variant="Variant.Text" Immediate="true" <span class="onboarding__input-row">
Adornment="Adornment.End" AdornmentIcon="@_passwordInputIcon" <input class="onboarding__input" type="@(_isShow ? "text" : "password")"
OnAdornmentClick="ShowPassword" autocomplete="current-password" enterkeyhint="next"
AdornmentAriaLabel="@(_isShow ? "Nascondi la password" : "Mostra la password")" value="@UserData.Password" @oninput="@(e => UserData.Password = e.Value?.ToString())"/>
UserAttributes="@(new() { ["autocomplete"] = "current-password", ["enterkeyhint"] = "next" })"/> <button type="button" class="onboarding__reveal" @onclick="ShowPassword"
</div> aria-label="@(_isShow ? "Nascondi la password" : "Mostra la password")">
<i class="@(_isShow ? "ri-eye-off-line" : "ri-eye-line")" aria-hidden="true"></i>
</button>
</span>
</label>
<div class="onboarding__field"> <label class="onboarding__field">
<MudTextField @bind-Value="UserData.CodHash" Label="Profilo azienda" <span class="onboarding__label">Profilo azienda</span>
Variant="Variant.Text" Immediate="true" <input class="onboarding__input" type="text" autocomplete="organization"
UserAttributes="@(new() { ["autocomplete"] = "organization", ["enterkeyhint"] = "go", ["autocapitalize"] = "none" })"/> autocapitalize="none" autocorrect="off" enterkeyhint="go"
</div> value="@UserData.CodHash" @oninput="@(e => UserData.CodHash = e.Value?.ToString())"/>
</label>
</div> </div>
@if (_attemptFailed) @if (_attemptFailed)
{ {
<p class="onboarding__error" role="alert" aria-live="assertive">@ErrorMessage</p> @* Stesso riquadro di avviso usato dentro l'app: l'errore di accesso
non e' un caso speciale che merita un suo stile. *@
<div class="feedback feedback--danger onboarding__error" role="alert" aria-live="assertive">
<i class="feedback__icon ri-error-warning-line" aria-hidden="true"></i>
<span>@ErrorMessage</span>
</div>
} }
<button type="submit" class="onboarding__submit" disabled="@(_busy || !CanSubmit)"> <button type="submit" class="onboarding__submit" disabled="@(_busy || !CanSubmit)">
@@ -73,20 +89,13 @@
private bool _busy; private bool _busy;
private bool _isShow; private bool _isShow;
private InputType _passwordInput = InputType.Password;
private string _passwordInputIcon = Icons.Material.Rounded.VisibilityOff;
private bool CanSubmit => private bool CanSubmit =>
!string.IsNullOrWhiteSpace(UserData.Username) && !string.IsNullOrWhiteSpace(UserData.Username) &&
!string.IsNullOrWhiteSpace(UserData.Password) && !string.IsNullOrWhiteSpace(UserData.Password) &&
!string.IsNullOrWhiteSpace(UserData.CodHash); !string.IsNullOrWhiteSpace(UserData.CodHash);
private void ShowPassword() private void ShowPassword() => _isShow = !_isShow;
{
_isShow = !_isShow;
_passwordInputIcon = _isShow ? Icons.Material.Rounded.Visibility : Icons.Material.Rounded.VisibilityOff;
_passwordInput = _isShow ? InputType.Text : InputType.Password;
}
protected override void OnInitialized() protected override void OnInitialized()
{ {
+57 -17
View File
@@ -881,7 +881,7 @@
padding: var(--space-lg); padding: var(--space-lg);
padding-top: calc(var(--space-lg) + env(safe-area-inset-top, 0px)); padding-top: calc(var(--space-lg) + env(safe-area-inset-top, 0px));
padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom, 0px)); padding-bottom: calc(var(--space-lg) + env(safe-area-inset-bottom, 0px));
background-color: var(--surface-muted); background-color: var(--workspace);
} }
.onboarding__panel { .onboarding__panel {
@@ -892,40 +892,80 @@
} }
.onboarding__logo { .onboarding__logo {
height: 128px; height: 104px;
object-fit: contain; object-fit: contain;
margin-inline: auto; margin-inline: auto;
} }
/* Un pannello solo, tre righe divise da una linea: la stessa forma delle
liste dell'app, invece di tre riquadri che galleggiano separati. */
.onboarding__fields { .onboarding__fields {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-md);
margin-top: var(--space-xl); margin-top: var(--space-xl);
background-color: var(--surface);
border-radius: var(--radius-surface);
overflow: hidden;
} }
.onboarding__field { .onboarding__field {
background-color: var(--surface); display: block;
border: 1px solid var(--divider); padding: var(--space-sm) var(--space-md);
border-radius: var(--radius-control); transition: background-color var(--duration-fast) var(--ease-out);
padding: var(--space-xs) var(--space-md);
transition: border-color var(--duration-fast) var(--ease-out),
box-shadow var(--duration-fast) var(--ease-out);
} }
.onboarding__field:focus-within { .onboarding__field + .onboarding__field { border-top: 1px solid var(--divider); }
border-color: var(--primary-dark);
box-shadow: inset 0 0 0 1px var(--primary-dark); .onboarding__field:focus-within { background-color: var(--surface-muted); }
/* L'etichetta sta sopra il campo e non si muove: niente testo che scivola
quando appoggi il dito. */
.onboarding__label {
display: block;
font-size: var(--label-md-size);
line-height: 1.25;
font-weight: 500;
color: var(--ink-muted);
} }
.onboarding__error { .onboarding__input-row {
margin-top: var(--space-lg); display: flex;
text-align: center; align-items: center;
gap: var(--space-xs);
}
.onboarding__input {
width: 100%;
min-width: 0;
min-height: 34px;
border: none;
background: none;
outline: none;
font-family: inherit;
font-size: var(--body-lg-size); font-size: var(--body-lg-size);
font-weight: 600; font-weight: 500;
color: var(--danger-ink); color: var(--ink);
} }
.onboarding__reveal {
flex: 0 0 auto;
display: flex;
align-items: center;
justify-content: center;
width: var(--touch-min);
height: var(--touch-min);
margin-right: calc(var(--space-xs) * -1);
border: none;
border-radius: var(--radius-pill);
background: none;
color: var(--ink-muted);
font-size: 20px;
}
.onboarding__reveal:active { background-color: var(--surface-muted); }
.onboarding__error { margin-top: var(--space-md); }
/* Bottone a pillola, alto 52: e' l'unico gesto della schermata. */ /* Bottone a pillola, alto 52: e' l'unico gesto della schermata. */
.onboarding__submit { .onboarding__submit {
display: flex; display: flex;