Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

07 — Component Library (Auth Module)

Module-specific components built from shared App* primitives (00-shared/03). Props, states, animation, a11y, tokens, Flutter mapping. Reuse over new — only components that don't exist in the shared library are defined here.


A. Brand & chrome

AppBrandMark (Auth-specific)

  • Purpose: StudyLyon lockup at top of pre-auth screens; differentiator + trust.
  • Props: expanded (bool, tablet/desktop), onTap (unused on pre-auth).
  • State: single, tinted (primaryContainer tile). a11y: Semantics(image, label: "StudyLyon").
  • Flutter: AppAvatar-style CircleAvatar + Text with themed lockup; branding override from organization.branding (future).

AppPasswordField

  • Purpose: obscured input with reveal toggle — used in login/register/reset.
  • Props: label, hint?, validator, textInputAction, onSubmitted, autofillHints (new-password|current-password), enabled, errorText, helperText (suggested account lockspace), strengthHint optional (register).
  • State: base / focus / error / disabled / loading(suffix spinner) / reveal.
  • Animation: Mo-fast icon swap; error slide-in.
  • a11y: label + Semantics(error), error announced; reveal button Semantics(toggled:obscure).
  • Flutter: TextFormField + suffix IconButton (visibility/visibility_off) with Tooltip "Show password".

B. TOTP & code entry

AppTotpInput (6-digit)

  • Purpose: enter TOTP 6–8 digits (backend default 6 env.ts:78, accept 6/8 sloppy with authenticator.check tolerant drift).
  • Props: length (default 6), onCompleted(code), error, loading, autofocus, readOnly.
  • Behaviors: 6 boxes, auto-advance, overwrite, paste full code, Backspace to previous; digit-only filter.
  • States: empty, partial, valid, error (error ring) — validates against authenticator.check(code, secret) only server-side; client validates RegExp(r'^\d{6,8}$') locally.
  • A11y: single grouped field label "One-time code", Semantics groups boxes; talkback reads "digit 2 of 6".
  • Flutter: custom Row of 6 TextField 48dp focused with movement arrows / single TextField with LetterSpacing 8px + lengthFormatter (recommend single hidden-real-width input).
  • Motion: Mo-fast slide between boxes; error AnimatedSwitcher shake.

AppTotpChip (status pill)

AppBadge variant: ON → success, OFF → outline.

C. Session representation

AppSessionCard

  • Purpose: one authenticated device row.
  • Props: deviceName?, browser?, os?, platform?, ip?, location?, expiresAt, activityAt, isCurrent, onLogout, menu?.
  • Renders: leading icon from platform map, title, subtitle ("browser · OS · ip · location"), meta lastActivityAt/expiresAt, AppMenu (Log out).
  • Current device marker: primaryContainer tile + "You" chip.
  • data-* fields: exactly the user_session doc fields (user-session.schema.ts:15-29).
  • Flutter: ListTile inside AppCard (elevation e-0), icon map fn.

AppActiveBadge (AppBadge) — enumerates session count for Security Hub.

D. API-key artifacts

AppApiKeyCard

FieldSpec
PurposeOne non-revoked key summary
Propsprefix, name, scopes[], createdAt, lastUsedAt?, onRevoke
Renderingname titleMedium, prefix**** mono + copy-prefix icon, chips of scopes, footer ${lastUsed ?? 'never used'} · created ${createdAt} in bodySmall
a11ycard button + menu; Semantics(label: "API key <name>")
TokenssurfaceContainerLow, R-md, El-e-1

AppSecretReveal (one-time key reveal)

FieldSpec
PurposeDisplay raw key after create; warning that it's shown once (auth.service.ts:414).
Propssecret, copyable, dismissible
Renderingmono body, wrapped card with copy; warning AppBanner(warning) "Copy now – you won't see this again."
CopyClipboard.setData + Snackbar("Copied"), lightImpact.
a11ySemantics(liveRegion) on copy result; scrolled-into view.

E. Status & feedback

  • AppSecurityBanner — security anniversary: "Change your password" / "Verify email" prompts.
  • Reuses AppBanner, AppSnackbar, AppErrorState, AppEmptyState, AppOfflineBanner from 00-shared/03 with no module changes.

F. Only elements the API supports

  • Sessions/API keys lists → no items (directly empty) — no infinite scroll needed (findByUserId returns full arrays, user-session.repository.ts:19, api-key.repository.ts:20).

G. Flutter widget map (module)

ComponentFlutter widgets
AppAuthHeaderWrap + Text in Padding
AppPasswordFieldTextFormField + IconButton
AppTotpInputcustom FormField<int?> over a single TextField 6-digit mask
AppSessionCardCard + ListTile + MenuAnchor
AppApiKeyCardCard + Row + ActionChips
AppSecretRevealCard + SelectableText + Clipboard
AppTotpChip`Badge``
AppSecurityBannerMaterialBanner

H. Golden tests (base 00-shared/03 G)

Every module component: golden at phone/tablet/desktop + dark mode; error/all-secret states for AppTotpInput, AppSecretReveal, AppSessionCard.