Skip to content

Commit c92d023

Browse files
AchoArnoldCopilot
andcommitted
docs: add design for login last-used badge
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 83d5e4b commit c92d023

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Login "Last Used" Badge — Design
2+
3+
## Problem
4+
5+
The login page (`web/app/pages/login.vue``web/app/components/FirebaseAuth.vue`)
6+
offers three authentication methods: Continue with Google, Continue with GitHub,
7+
and Continue with email. Returning users don't get any hint about which method
8+
they used last, so they may pick the wrong provider and end up creating a second
9+
account or failing to sign in.
10+
11+
## Goal
12+
13+
Show a small "Last Used" badge on the button corresponding to the login method
14+
the user most recently used successfully on this device, so they can quickly pick
15+
the right one next time.
16+
17+
## Scope
18+
19+
Single component change: `web/app/components/FirebaseAuth.vue`. No API, store, or
20+
backend changes.
21+
22+
## Approach
23+
24+
### Storage
25+
26+
- Persist the last successful method in `localStorage` under the key
27+
`httpsms_last_login_method`.
28+
- Value is one of `'google' | 'github' | 'email'`.
29+
- The value is written only **after a successful login** (inside `onSuccess`),
30+
never on click/attempt.
31+
32+
### Recording the method
33+
34+
- `onSuccess(user)` is currently shared by all three flows. Extend it to
35+
`onSuccess(user, method)` where `method` is `'google' | 'github' | 'email'`.
36+
- `signInWithGoogle``onSuccess(result.user, 'google')`
37+
- `signInWithGithub``onSuccess(result.user, 'github')`
38+
- `submitEmail``onSuccess(result.user, 'email')`
39+
- Inside `onSuccess`, write the method to `localStorage` before redirecting.
40+
41+
### Reading the method
42+
43+
- A reactive `lastUsedMethod = ref<string | null>(null)`.
44+
- Populated in `onMounted` from `localStorage` (client-only, SSR-safe; the
45+
component is already rendered inside `<ClientOnly>` on the login page).
46+
47+
### Display
48+
49+
- Each of the three method buttons gets `class="position-relative"`.
50+
- A floating `v-chip` is rendered in the top-right corner of the matching button:
51+
- Vuetify `v-chip` with `label`, `size="x-small"`, `color="primary"`.
52+
- `class="position-absolute"` pinned to the top-right corner (slightly
53+
overlapping), text `Last Used`.
54+
- Shown via `v-if="lastUsedMethod === 'google'"` (and `'github'`, `'email'`
55+
respectively).
56+
57+
### Edge cases
58+
59+
- The email button is hidden once the inline email form opens
60+
(`v-if="!showEmailForm"`), so its badge hides with it automatically. No extra
61+
handling needed.
62+
- An unknown/empty stored value shows no badge anywhere.
63+
- `localStorage` access is guarded (wrapped in try/catch or `onMounted` only) so
64+
it never runs during SSR.
65+
66+
## Testing
67+
68+
- Manual verification: sign in with each method, confirm the badge appears on the
69+
correct button on the next visit to the login page.
70+
- Confirm no SSR/hydration errors (badge logic runs client-side only).
71+
72+
## Out of scope
73+
74+
- Syncing the preference across devices.
75+
- Remembering the specific email address used.

0 commit comments

Comments
 (0)