fix(auth): make login/signup fields password-manager friendly
Password managers (1Password, Bitwarden, …) could not reliably detect or fill the auth fields because the inputs were loose labels inside a div with no real form, no name attributes, and a static autocomplete hint. Changes: - Wrap the auth card in a real <form @submit.prevent> so password managers recognize the credential form and its submit flow - Add id/name attributes to all fields (username, displayName, password) - Use a dynamic autocomplete hint on the password field: current-password for login (autofill) and new-password for registration (offer a generated strong password) - Set autocomplete="nickname" on the display-name field so it is not mistaken for a username or password field - Mark the close, tab-switch, and OIDC buttons as type="button" so they no longer default to type="submit" and trigger form submission - Make the primary action a type="submit" button so Enter submits natively - Add margin: 0 to .card since it is now a form element
This commit is contained in:
parent
d400a4a2a0
commit
f97b4f92f0
1 changed files with 17 additions and 11 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { login, oidcLogin, register } from '@/game/auth'
|
||||
import { store } from '@/game/store'
|
||||
|
||||
|
|
@ -10,6 +10,11 @@ const displayName = ref('')
|
|||
const busy = ref(false)
|
||||
const error = ref('')
|
||||
|
||||
// Password managers (1Password, Bitwarden, …) rely on distinct autocomplete
|
||||
// hints: "current-password" for login, "new-password" so a strong password is
|
||||
// suggested/saved during registration.
|
||||
const passwordAutocomplete = computed(() => (mode.value === 'login' ? 'current-password' : 'new-password'))
|
||||
|
||||
function close(): void {
|
||||
store.auth.showAuth = false
|
||||
error.value = ''
|
||||
|
|
@ -33,40 +38,40 @@ async function submit(): Promise<void> {
|
|||
|
||||
<template>
|
||||
<div v-if="store.auth.showAuth" class="backdrop" @click.self="close">
|
||||
<div class="card">
|
||||
<button class="close" @click="close">✕</button>
|
||||
<form class="card" @submit.prevent="submit">
|
||||
<button type="button" class="close" @click="close">✕</button>
|
||||
<h2>{{ mode === 'login' ? 'Anmelden' : 'Konto erstellen' }}</h2>
|
||||
<p class="sub">Speichere Kristalle, Forschung & Statistiken über alle Runden hinweg.</p>
|
||||
|
||||
<div class="tabs">
|
||||
<button :class="{ active: mode === 'login' }" @click="mode = 'login'">Anmelden</button>
|
||||
<button :class="{ active: mode === 'register' }" @click="mode = 'register'">Registrieren</button>
|
||||
<button type="button" :class="{ active: mode === 'login' }" @click="mode = 'login'">Anmelden</button>
|
||||
<button type="button" :class="{ active: mode === 'register' }" @click="mode = 'register'">Registrieren</button>
|
||||
</div>
|
||||
|
||||
<label class="field">
|
||||
<span>Benutzername</span>
|
||||
<input v-model="username" maxlength="16" autocomplete="username" @keyup.enter="submit" />
|
||||
<input id="username" name="username" v-model="username" maxlength="16" autocomplete="username" />
|
||||
</label>
|
||||
<label v-if="mode === 'register'" class="field">
|
||||
<span>Anzeigename (optional)</span>
|
||||
<input v-model="displayName" maxlength="24" @keyup.enter="submit" />
|
||||
<input id="displayName" name="displayName" v-model="displayName" maxlength="24" autocomplete="nickname" />
|
||||
</label>
|
||||
<label class="field">
|
||||
<span>Passwort</span>
|
||||
<input v-model="password" type="password" autocomplete="current-password" @keyup.enter="submit" />
|
||||
<input id="password" name="password" v-model="password" type="password" :autocomplete="passwordAutocomplete" />
|
||||
</label>
|
||||
|
||||
<p v-if="error" class="error">{{ error }}</p>
|
||||
|
||||
<button class="primary" :disabled="busy" @click="submit">
|
||||
<button type="submit" class="primary" :disabled="busy">
|
||||
{{ busy ? '…' : mode === 'login' ? '▶ Anmelden' : '▶ Konto erstellen' }}
|
||||
</button>
|
||||
|
||||
<div v-if="store.auth.oidcEnabled" class="divider"><span>oder</span></div>
|
||||
<button v-if="store.auth.oidcEnabled" class="oidc" @click="oidcLogin">🔑 {{ store.auth.oidcLabel }}</button>
|
||||
<button type="button" v-if="store.auth.oidcEnabled" class="oidc" @click="oidcLogin">🔑 {{ store.auth.oidcLabel }}</button>
|
||||
|
||||
<p class="hint">Als Gast spielen? Einfach schließen – Fortschritt wird lokal gespeichert.</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -83,6 +88,7 @@ async function submit(): Promise<void> {
|
|||
}
|
||||
.card {
|
||||
position: relative;
|
||||
margin: 0;
|
||||
background: var(--panel);
|
||||
border: 1px solid var(--panel-border);
|
||||
border-radius: 16px;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue