From 3dfe054fcc2cc7ac49db541fc07bd49c9f04fa64 Mon Sep 17 00:00:00 2001 From: Arthur Belleville Date: Fri, 15 May 2026 20:45:27 +0200 Subject: [PATCH] docs(08): UI design contract --- .../phases/08-social-sign-in/08-UI-SPEC.md | 256 ++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 .planning/phases/08-social-sign-in/08-UI-SPEC.md diff --git a/.planning/phases/08-social-sign-in/08-UI-SPEC.md b/.planning/phases/08-social-sign-in/08-UI-SPEC.md new file mode 100644 index 0000000..03c6824 --- /dev/null +++ b/.planning/phases/08-social-sign-in/08-UI-SPEC.md @@ -0,0 +1,256 @@ +--- +phase: 8 +slug: social-sign-in +status: approved +shadcn_initialized: false +preset: none +created: 2026-05-15 +--- + +# Phase 8 — UI Design Contract + +> Visual and interaction contract for the Social Sign-in phase. This phase changes the login/signup surfaces and adds a minimal linked-providers account view. It should stay functional and restrained; the user will provide a more polished UI later. + +--- + +## Design System + +| Property | Value | +|----------|-------| +| Tool | none | +| Preset | not applicable | +| Component library | local templ components in `backend/internal/web/ui` | +| Icon library | none required for Phase 8 | +| Font | inherited app font | + +### Existing Surface To Preserve + +- Keep the centered auth card layout used by `LoginPage` and `SignupPage`. +- Keep the current card width: `w-full max-w-sm`. +- Keep the current card padding: `px-6 py-8`. +- Keep existing form labels, inputs, and validation error patterns. +- Do not introduce a marketing-style auth page, hero area, decorative background, split layout, or large illustration. + +--- + +## Interaction Contract + +### Login and Signup Pages + +Both `/login` and `/signup` must show: + +1. Page heading +2. Equal-prominence Google and Apple provider buttons +3. A visual separator between provider buttons and the email/password form +4. Existing email/password form +5. Existing inline validation/error rendering behavior + +Provider buttons: + +- Google and Apple are peers; neither is styled as primary over the other. +- Buttons link to provider start routes when configured. +- Buttons render disabled when required provider config is missing. +- Disabled state must be visible and non-clickable. +- Disabled state copy must be short and plain, not diagnostic. +- Provider buttons must not submit the email/password form. + +Successful social sign-in redirects to `/`; no provider-specific welcome page. + +### Linked Providers View + +Add a protected, minimal linked-providers status view. + +Required content: + +- Heading: `Linked providers` +- One row for Google +- One row for Apple +- Each row shows one of: + - `Connected` + - `Not connected` +- If connected, show the stored provider email. +- No unlink action in Phase 8. +- No add-password UI in Phase 8. + +The view may live at `/account` or `/account/providers`; planner decides route naming. + +--- + +## Spacing Scale + +Declared values (must be multiples of 4): + +| Token | Value | Usage | +|-------|-------|-------| +| xs | 4px | Provider button inner gaps if icons are later added | +| sm | 8px | Button stack gap, inline provider row gap | +| md | 16px | Default form/provider group spacing | +| lg | 24px | Auth section separator margin | +| xl | 32px | Page card inner section breaks | +| 2xl | 48px | Account page section spacing | +| 3xl | 64px | Existing auth page top spacing equivalent | + +Exceptions: none + +Auth card layout: + +- Heading margin-bottom: 24px (`mb-6`) remains acceptable. +- Form/provider section gap: 20px (`space-y-5`) remains acceptable because it already exists; do not introduce additional non-4px spacing. +- Provider button stack gap: 8px. +- Separator vertical margin: 16px above and below. + +--- + +## Typography + +| Role | Size | Weight | Line Height | +|------|------|--------|-------------| +| Body | 16px | 400 | 1.5 | +| Label | 14px | 500 | 1.25 | +| Helper / status | 14px | 400 | 1.4 | +| Heading | 24px | 600 | 1.25 | +| Account section heading | 20px | 600 | 1.3 | + +Rules: + +- Do not use viewport-scaled font sizes. +- Do not use negative letter spacing. +- Keep provider button labels at 16px / 600 if using `ui.Button`, matching existing primary button weight. +- Disabled explanatory copy uses 14px normal weight. + +--- + +## Color + +| Role | Value | Usage | +|------|-------|-------| +| Dominant (60%) | `#ffffff` | Auth card and account content surfaces | +| Secondary (30%) | `#f8fafc` | Page background or subtle status surfaces | +| Text | `#0f172a` | Primary headings/body | +| Muted text | `#64748b` | Helper text, disabled provider explanation | +| Border | `#e2e8f0` | Provider buttons, separators, provider status rows | +| Accent (10%) | `#2563eb` | Existing primary email/password submit button and focus ring only | +| Destructive | `#b91c1c` | Error text or future destructive actions only | + +Accent reserved for: + +- Existing primary email/password submit button +- Focus rings +- Links if needed + +Provider buttons: + +- Use neutral/outline styling rather than blue primary styling. +- Background: `#ffffff` +- Border: `#e2e8f0` +- Text: `#0f172a` +- Hover when enabled: `#f8fafc` +- Disabled background: `#f1f5f9` +- Disabled text: `#94a3b8` + +--- + +## Copywriting Contract + +| Element | Copy | +|---------|------| +| Google button | `Continue with Google` | +| Apple button | `Continue with Apple` | +| Disabled Google button | `Google sign-in not configured` | +| Disabled Apple button | `Apple sign-in not configured` | +| Auth separator | `or` | +| Provider callback generic error | `Could not sign you in with this provider. Try another sign-in method.` | +| Unverified email error | `This provider did not return a verified email. Try another sign-in method.` | +| Social-only signup conflict | `An account already exists for this email. Sign in with your provider.` | +| Linked providers heading | `Linked providers` | +| Connected status | `Connected` | +| Not connected status | `Not connected` | +| No unlink copy | No visible copy needed; simply omit unlink controls | + +Error copy rules: + +- Do not expose provider tokens, codes, claim names, key IDs, or raw OAuth errors in the UI. +- Server logs may contain structured error categories, but UI copy stays generic unless the user can act on it. + +--- + +## Component Contract + +### Provider Button + +Create a provider button pattern rather than reusing the solid blue primary submit button. + +Acceptable implementation options: + +- Extend `ui.Button` with neutral outline/disabled support. +- Add a small auth-local provider button templ component. + +Required behavior: + +- Full width inside the auth card. +- Stable height of at least 44px. +- Does not resize based on provider config. +- Uses native disabled semantics for button form controls, or `aria-disabled="true"` plus no actionable `href` for links. +- Keyboard focus ring is visible when enabled. + +### Separator + +Use a simple horizontal rule pattern: + +- Left line +- Center text `or` +- Right line + +No decorative icons or large text. + +### Linked Provider Row + +Each row: + +- Provider name on the left. +- Status and email on the right or below on small screens. +- Bordered row or subtle card row. +- Minimum row height 44px. +- No nested cards inside cards. + +--- + +## Responsive Contract + +- Auth card remains centered and no wider than `max-w-sm`. +- Provider buttons are stacked vertically on all viewports in Phase 8; do not use a two-column button layout. +- Linked providers view uses a single column on mobile. +- Text must not overflow provider buttons; if future localization makes labels long, allow wrapping before reducing font size. +- No horizontal scrolling. + +--- + +## Accessibility Contract + +- Provider buttons must be reachable by keyboard. +- Disabled provider controls must communicate disabled state to assistive tech. +- Separator `or` must not be announced as a form control. +- Error messages must be associated with the relevant auth surface and visible near the provider/form area. +- Connected provider rows should expose status text as real text, not only color. + +--- + +## Registry Safety + +| Registry | Blocks Used | Safety Gate | +|----------|-------------|-------------| +| shadcn official | none | not required | +| third-party blocks | none | not allowed for Phase 8 | + +--- + +## Checker Sign-Off + +- [x] Dimension 1 Copywriting: PASS +- [x] Dimension 2 Visuals: PASS +- [x] Dimension 3 Color: PASS +- [x] Dimension 4 Typography: PASS +- [x] Dimension 5 Spacing: PASS +- [x] Dimension 6 Registry Safety: PASS + +**Approval:** approved 2026-05-15