Shuffle/docs/design/auth-screens.md
cschlaefke ec8b2ab4c1 feat(ui): add auth form components and screen layouts
Refs #1

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 00:03:11 +01:00

13 KiB
Raw Blame History

Auth-Screens: Layout-Skizzen und Texte (Spec #1, Task U1)

Grundlage: docs/specs/1-auth-registrierung-anmeldung.md (§ 4.4 Meldungen, § 5.4 Screens, § 6 Plattform). Komponenten: app/lib/core/widgets/ (siehe docs/design-system.md). Alle Texte unten sind Vorschläge und gehen über l10n (ARB); die ARB-Dateien pflegt der flutter-dev (A1/A2). Schlüssel sind lowerCamelCase mit Präfix auth.

1. Gemeinsames Layout

  • Alle sechs Screens nutzen AppFormScaffold. Kompakt (< 600 dp): Vollbild, scrollbar, Seitenrand 16 dp. Ab 600 dp: zentrierte Karte, max. 480 dp breit (AppBreakpoints.authCardMaxWidth), Innenabstand 24 dp.
  • Inhalt in einer Spalte, Abstand zwischen Feldern 16 dp, zwischen Gruppen 24 dp.
  • Reihenfolge = Lesereihenfolge = Tab-Reihenfolge: Titel, Banner (falls vorhanden), Felder, Checkboxen, Primärknopf, Sekundärlinks.
  • Titel: headlineSmall, darunter optional ein Einleitungssatz in bodyMedium. Titel als Semantics-Überschrift (Semantics(header: true)).
  • Banner (AppBanner) stehen über den Feldern, direkt unter dem Titel. Fehler am Feld stehen unter dem Feld.
  • Genau ein Primärknopf (AppPrimaryButton, volle Breite). Sekundäraktionen sind TextButtons (48 dp).
  • Eingaben bleiben bei jedem Fehler erhalten. Während submitting sind Knopf und Felder gesperrt, der Knopf zeigt den Spinner und den gesprochenen Text authSubmitting.
  • Nach einem Fehler setzt der Screen den Fokus auf das erste fehlerhafte Feld; bei Banner-Fehlern bleibt der Fokus am Knopf, das Banner wird als Live-Region angesagt.
  • Enter im letzten Feld sendet ab (TextInputAction.done), sonst next.

Legende der Skizzen: [ ] Feld, [x] Checkbox, ( ) Primärknopf, <…> Link/TextButton, ! Banner.

2. Skizzen

RegisterScreen (/register)

Konto erstellen                      (Titel)
! Fehler-Banner (nur bei registrationRejected / network / rateLimited / unexpected)
E-Mail
[ name@example.com                 ]  Fehler: authEmailInvalid
Passwort
[ ••••••••••               (Auge) ]  Hinweis: authPasswordRule / Fehler je Regel
Anzeigename
[ Alex                       4/30 ]  Fehler: authDisplayNameEmpty | TooLong | Invalid
[x] Ich bin mindestens 16 Jahre alt           Fehler: authAgeNotConfirmed
[x] Ich habe die <Datenschutzerklärung> gelesen und stimme den <Nutzungsbedingungen> zu
                                              Fehler: authTermsNotAccepted
( Konto erstellen )
<Schon ein Konto? Anmelden>

CheckEmailScreen (/register/check-email, Modus Bestätigung bzw. Reset)

Prüfe dein Postfach                  (Titel)
Wir haben dir eine E-Mail geschickt, falls ... (Text, bodyLarge)
Der Link ist 1 Stunde gültig.  Die E-Mail kann einige Minuten dauern. Schau auch im Spam-Ordner nach.
! Info-Banner "E-Mail wurde erneut gesendet" (nach Resend, auch bei emailSendLimited)
! Fehler-Banner bei rateLimited / network
(nur wenn E-Mail fehlt, z. B. nach Reload:)  E-Mail [ ]
( E-Mail erneut senden )   -> nur Modus Bestätigung, gesperrt solange Anfrage läuft
<Zurück zur Anmeldung>     (Modus Reset: <Andere E-Mail-Adresse eingeben> -> /forgot-password)

LoginScreen (/login)

Anmelden
! Fehler-Banner: authInvalidCredentials | rateLimited | network   (über dem Formular, nie am Feld)
! Info-Banner emailNotConfirmed  + Aktion "Bestätigungs-E-Mail erneut senden"
E-Mail     [ ]
Passwort   [ ••••• (Auge) ]
( Anmelden )
<Passwort vergessen?>
<Konto erstellen>

ForgotPasswordScreen (/forgot-password)

Passwort zurücksetzen
Gib die E-Mail-Adresse deines Kontos ein. Wir senden dir einen Link zum Zurücksetzen.
E-Mail [ ]                      Fehler: authEmailInvalid
( Link senden )
<Zurück zur Anmeldung>

EmailLinkScreen (/auth/confirm)

Zustände: idle (Knopf), submitting, success (nur Bestätigung), error (Link ungültig).

E-Mail-Adresse bestätigen | Neues Passwort festlegen      (Titel je Typ)
Ein Klick genügt, um fortzufahren.
( E-Mail-Adresse bestätigen ) | ( Weiter zum neuen Passwort )

Erfolg:  ! Info-Banner "E-Mail bestätigt"  (+ Mobile-Web: "Du kannst dich jetzt auch in der App anmelden.")
Fehler:  ! Fehler-Banner "Der Link ist abgelaufen ..."  ( Neuen Link anfordern )

ResetPasswordScreen (/reset-password)

Neues Passwort festlegen
Neues Passwort
[ ••••••••• (Auge) ]  Live-Regeln: authPasswordRule, Fehler je Regel / samePassword
( Passwort speichern )
<Abbrechen>           -> signOut
Erfolg: Hinweis authPasswordChanged, dann Weiterleitung nach /

3. Textvorschläge

Ton: du-Form, kurz, sachlich-freundlich, keine Schuldzuweisung. Platzhalter in ICU-Syntax ({n}). Neutrale Texte (Krit. 4, F12) verraten nie, ob eine Adresse registriert ist.

3.1 Meldungen aus § 4.4 (Fehlerabbildung)

Schlüssel de en
authErrorInvalidCredentials E-Mail-Adresse oder Passwort ist nicht korrekt. Email address or password is incorrect.
authErrorEmailNotConfirmed Bestätige zuerst deine E-Mail-Adresse. Wir haben dir dazu eine E-Mail geschickt. Please confirm your email address first. We sent you an email for this.
authActionResendConfirmation Bestätigungs-E-Mail erneut senden Resend confirmation email
authErrorRateLimited Zu viele Versuche. Bitte warte einige Minuten und versuche es erneut. Too many attempts. Please wait a few minutes and try again.
authErrorWeakPasswordLength Das Passwort ist zu kurz. The password is too short.
authErrorWeakPasswordCharacters Das Passwort ist zu einfach. Wähle ein anderes. The password is too simple. Choose a different one.
authErrorWeakPasswordPwned Dieses Passwort ist sehr verbreitet und leicht zu erraten. Wähle ein anderes. This password is very common and easy to guess. Choose a different one.
authErrorSamePassword Wähle ein anderes als dein bisheriges Passwort. Choose a password different from your current one.
authErrorLinkInvalidOrExpired Der Link ist abgelaufen oder wurde schon benutzt. The link has expired or has already been used.
authActionRequestNewLink Neuen Link anfordern Request a new link
authErrorEmailInvalid Gib eine gültige E-Mail-Adresse ein. Enter a valid email address.
authErrorRegistrationRejected Registrierung nicht möglich. Bitte prüfe deine Angaben. Registration is not possible. Please check your details.
authErrorNetwork Keine Verbindung. Für diesen Schritt brauchst du Internet. No connection. You need internet access for this step.
authErrorUnexpected Etwas ist schiefgelaufen. Bitte versuche es erneut. Something went wrong. Please try again.
authActionRetry Erneut versuchen Try again

emailSendLimited hat bewusst keinen eigenen Text: Register/Forgot/CheckEmail zeigen den neutralen Erfolgstext (§ 3.3), nur der Resend im LoginScreen zeigt authErrorRateLimited.

3.2 Meldungen aus § 5.4 (Felder, Banner, Hinweise)

Schlüssel de en
authPasswordTooShort Mindestens 10 Zeichen – es fehlen noch {missing}. At least 10 characters – {missing} more needed.
authPasswordCommon Dieses Passwort ist sehr verbreitet und leicht zu erraten. Wähle ein anderes. This password is very common and easy to guess. Choose a different one.
authPasswordRule Mindestens 10 Zeichen. Kein sehr verbreitetes Passwort. At least 10 characters. Not a very common password.
authPasswordRequired Gib ein Passwort ein. Enter a password.
authDisplayNameEmpty Gib einen Anzeigenamen ein. Enter a display name.
authDisplayNameTooLong Der Anzeigename darf höchstens {max} Zeichen lang sein. The display name can be at most {max} characters long.
authDisplayNameInvalid Dieser Anzeigename ist nicht erlaubt. Verwende sichtbare Zeichen. This display name is not allowed. Use visible characters.
authAgeNotConfirmed Shuffle ist erst ab 16 Jahren nutzbar. Shuffle can only be used from age 16.
authTermsNotAccepted Bitte stimme Datenschutzerklärung und Nutzungsbedingungen zu. Please agree to the privacy policy and the terms of use.
authFieldEmailLabel E-Mail-Adresse Email address
authFieldPasswordLabel Passwort Password
authFieldNewPasswordLabel Neues Passwort New password
authFieldDisplayNameLabel Anzeigename Display name
authPasswordShow Passwort anzeigen Show password
authPasswordHide Passwort verbergen Hide password
authCheckboxAgeLabel Ich bin mindestens 16 Jahre alt I am at least 16 years old
authCheckboxTermsPrefix Ich habe die I have read the
authCheckboxTermsPrivacyLink Datenschutzerklärung privacy policy
authCheckboxTermsMiddle gelesen und stimme den and agree to the
authCheckboxTermsTermsLink Nutzungsbedingungen terms of use
authCheckboxTermsSuffix zu (leer)
authBannerTypeError Fehler Error
authBannerTypeInfo Hinweis Note
authSubmitting Bitte warten … Please wait …

Hinweis zur Checkbox „Nutzungsbedingungen“: Satzbau ist je Sprache verschieden. Der Satz wird deshalb aus den Segmenten Prefix, PrivacyLink, Middle, TermsLink, Suffix zusammengesetzt (AppCheckboxField.rich); im Englischen bleibt Suffix leer. Alternativ ein ICU-Satz mit Platzhaltern, den der Screen an den Linkstellen teilt – Entscheidung beim flutter-dev (A2).

3.3 Screen-Texte

Schlüssel de en
authRegisterTitle Konto erstellen Create account
authRegisterSubmit Konto erstellen Create account
authRegisterHaveAccount Schon ein Konto? Anmelden Already have an account? Sign in
authCheckEmailTitle Prüfe dein Postfach Check your inbox
authCheckEmailBody Wir haben dir eine E-Mail geschickt, falls die Adresse noch nicht registriert ist. Folge dem Link darin, um fortzufahren. We sent you an email if the address is not registered yet. Follow the link in it to continue.
authCheckEmailBodyReset Wir haben dir eine E-Mail mit einem Link zum Zurücksetzen geschickt, falls zu dieser Adresse ein Konto besteht. We sent you an email with a reset link if an account exists for this address.
authCheckEmailDelayHint Die E-Mail kann einige Minuten dauern. Schau auch im Spam-Ordner nach. The email can take a few minutes. Also check your spam folder.
authCheckEmailValidity Der Link ist {duration} gültig. The link is valid for {duration}.
authCheckEmailValidityOneHour 1 Stunde 1 hour
authCheckEmailResend E-Mail erneut senden Resend email
authCheckEmailResent Wir haben die E-Mail erneut gesendet, falls es zu dieser Adresse etwas zu senden gibt. We resent the email, if there is something to send for this address.
authCheckEmailDifferentAddress Andere E-Mail-Adresse eingeben Enter a different email address
authBackToLogin Zurück zur Anmeldung Back to sign in
authLoginTitle Anmelden Sign in
authLoginSubmit Anmelden Sign in
authLoginForgotPassword Passwort vergessen? Forgot password?
authLoginCreateAccount Konto erstellen Create account
authForgotTitle Passwort zurücksetzen Reset password
authForgotBody Gib die E-Mail-Adresse deines Kontos ein. Wir senden dir einen Link zum Zurücksetzen. Enter the email address of your account. We will send you a reset link.
authForgotSubmit Link senden Send link
authConfirmTitle E-Mail-Adresse bestätigen Confirm email address
authConfirmBody Ein Klick genügt, um deine E-Mail-Adresse zu bestätigen. One click is enough to confirm your email address.
authConfirmSubmit E-Mail-Adresse bestätigen Confirm email address
authConfirmSuccess E-Mail bestätigt. Email confirmed.
authConfirmSuccessMobileWeb Du kannst dich jetzt auch in der App anmelden. You can now also sign in in the app.
authRecoveryTitle Neues Passwort festlegen Set a new password
authRecoveryBody Ein Klick genügt, um ein neues Passwort festzulegen. One click is enough to set a new password.
authRecoverySubmit Weiter zum neuen Passwort Continue to new password
authResetTitle Neues Passwort festlegen Set a new password
authResetSubmit Passwort speichern Save password
authResetCancel Abbrechen Cancel
authPasswordChanged Passwort geändert. Andere Geräte werden abgemeldet; das kann bis zu einer Stunde dauern. Password changed. Other devices will be signed out; this can take up to an hour.

4. Barrierefreiheit pro Screen (Checkliste für A2–A4 und T2)

  • Jedes Feld hat ein sichtbares Label (kein Platzhalter-Label); Fehler per errorText (Icon + Text + Live-Region).
  • Banner und Fehler werden beim Erscheinen vorgelesen (Live-Region); keine reinen Farb-Signale.
  • Passwortfelder: AppPasswordField mit isNewPassword: true bei Register/Reset, sonst false; E-Mail mit AutofillHints.email (Login: AutofillHints.username/email), TextInputType.emailAddress.
  • Alle interaktiven Elemente >= 48 dp, Tab-Reihenfolge wie Lesereihenfolge, Fokus sichtbar.
  • Test je Screen mit textScaler 2.0 (Android 320 x 640), androidTapTargetGuideline, labeledTapTargetGuideline, textContrastGuideline, Hell und Dunkel (T2).