Merge pull request #2393 from hoobnn/fix/totp-autofill
fix: add autocomplete for TOTP autofill support
This commit is contained in:
commit
6a88e560c2
@ -24,6 +24,18 @@
|
||||
|
||||
<!-- Code Input -->
|
||||
<div class="mb-6">
|
||||
<!-- Hidden input for password manager autofill (autocomplete="one-time-code") -->
|
||||
<input
|
||||
ref="hiddenOtpInputRef"
|
||||
type="text"
|
||||
inputmode="numeric"
|
||||
autocomplete="one-time-code"
|
||||
maxlength="6"
|
||||
class="pointer-events-none absolute left-0 top-0 h-px w-px opacity-0"
|
||||
aria-hidden="true"
|
||||
tabindex="-1"
|
||||
@input="handleHiddenOtpInput"
|
||||
/>
|
||||
<div class="flex justify-center gap-2">
|
||||
<input
|
||||
v-for="(_, index) in 6"
|
||||
@ -33,6 +45,7 @@
|
||||
maxlength="1"
|
||||
inputmode="numeric"
|
||||
pattern="[0-9]"
|
||||
autocomplete="off"
|
||||
class="h-12 w-10 rounded-lg border border-gray-300 text-center text-lg font-semibold focus:border-primary-500 focus:ring-primary-500 dark:border-dark-600 dark:bg-dark-700"
|
||||
:disabled="verifying"
|
||||
@input="handleCodeInput($event, index)"
|
||||
@ -82,6 +95,7 @@ const appStore = useAppStore()
|
||||
const verifying = ref(false)
|
||||
const code = ref<string[]>(['', '', '', '', '', ''])
|
||||
const inputRefs = ref<(HTMLInputElement | null)[]>([])
|
||||
const hiddenOtpInputRef = ref<HTMLInputElement | null>(null)
|
||||
|
||||
// Watch for code changes and auto-submit when 6 digits are entered
|
||||
watch(
|
||||
@ -104,6 +118,10 @@ defineExpose({
|
||||
inputRefs.value.forEach(input => {
|
||||
if (input) input.value = ''
|
||||
})
|
||||
// Clear hidden autofill input
|
||||
if (hiddenOtpInputRef.value) {
|
||||
hiddenOtpInputRef.value.value = ''
|
||||
}
|
||||
nextTick(() => {
|
||||
inputRefs.value[0]?.focus()
|
||||
})
|
||||
@ -126,6 +144,26 @@ const handleCodeInput = (event: Event, index: number) => {
|
||||
}
|
||||
}
|
||||
|
||||
// Handle autofill from password managers via the hidden autocomplete="one-time-code" input
|
||||
const handleHiddenOtpInput = (event: Event) => {
|
||||
const input = event.target as HTMLInputElement
|
||||
const digits = input.value.replace(/[^0-9]/g, '').slice(0, 6).split('')
|
||||
|
||||
digits.forEach((digit, i) => {
|
||||
code.value[i] = digit
|
||||
if (inputRefs.value[i]) {
|
||||
inputRefs.value[i]!.value = digit
|
||||
}
|
||||
})
|
||||
|
||||
for (let i = digits.length; i < 6; i++) {
|
||||
code.value[i] = ''
|
||||
if (inputRefs.value[i]) {
|
||||
inputRefs.value[i]!.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeydown = (event: KeyboardEvent, index: number) => {
|
||||
if (event.key === 'Backspace') {
|
||||
const input = event.target as HTMLInputElement
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user