From 86a315f24cddfa863b42c890dd1a9eaf73f99aa6 Mon Sep 17 00:00:00 2001 From: Matt Date: Sat, 9 Aug 2025 20:08:51 +0200 Subject: [PATCH] Fix mobile password input issues and prevent iOS auto-zoom - Add togglePasswordVisibility function with mobile-specific handling - Set font-size to 16px on password inputs to prevent iOS zoom - Add autocomplete="new-password" attribute to password fields - Increase tap target size for password visibility toggle on mobile - Configure viewport meta tag to disable zoom on iOS devices - Disable transitions on mobile for better performance --- pages/auth/setup-password.vue | 80 +++++++++++++++++++++++++++++++++-- 1 file changed, 76 insertions(+), 4 deletions(-) diff --git a/pages/auth/setup-password.vue b/pages/auth/setup-password.vue index b893145..fbe616e 100644 --- a/pages/auth/setup-password.vue +++ b/pages/auth/setup-password.vue @@ -38,8 +38,10 @@ :rules="passwordRules" :error="!!errorMessage" :append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'" - @click:append-inner="showPassword = !showPassword" - class="mb-3" + @click:append-inner="togglePasswordVisibility('password')" + class="mb-3 password-field" + autocomplete="new-password" + :autofocus="false" /> @@ -248,6 +252,28 @@ useHead({ ] }); +// Toggle password visibility with debouncing on mobile +const togglePasswordVisibility = (field: 'password' | 'confirm') => { + // Prevent rapid toggling which can cause issues on mobile + if (mobileDetection.isMobile) { + // Use nextTick to defer the update + nextTick(() => { + if (field === 'password') { + showPassword.value = !showPassword.value; + } else { + showConfirmPassword.value = !showConfirmPassword.value; + } + }); + } else { + // Immediate toggle on desktop + if (field === 'password') { + showPassword.value = !showPassword.value; + } else { + showConfirmPassword.value = !showConfirmPassword.value; + } + } +}; + // Setup password function const setupPassword = async () => { if (!formValid.value) return; @@ -311,6 +337,14 @@ onMounted(() => { if (!email.value) { errorMessage.value = 'No email address provided. Please use the link from your verification email.'; } + + // Prevent auto-zoom on iOS when focusing input fields + if (mobileDetection.isIOS) { + const metaViewport = document.querySelector('meta[name="viewport"]'); + if (metaViewport) { + metaViewport.setAttribute('content', 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no'); + } + } }); @@ -405,4 +439,42 @@ onMounted(() => { .v-progress-linear { border-radius: 3px; } + +/* Password field specific optimizations for mobile */ +.password-field :deep(.v-field__input) { + font-size: 16px !important; /* Prevent zoom on iOS */ + -webkit-text-fill-color: currentColor !important; +} + +/* Prevent auto-zoom on focus for mobile Safari */ +@media screen and (max-width: 768px) { + .password-field :deep(input) { + font-size: 16px !important; + } + + .password-field :deep(.v-field__append-inner) { + /* Make eye icon easier to tap on mobile */ + min-width: 44px; + min-height: 44px; + display: flex; + align-items: center; + justify-content: center; + } +} + +/* iOS specific fixes to prevent zoom */ +@supports (-webkit-touch-callout: none) { + .password-field :deep(input) { + font-size: 16px !important; + } +} + +/* Disable transitions on mobile for better performance */ +.is-mobile .password-field :deep(.v-field__append-inner) { + transition: none !important; +} + +.is-mobile .password-field :deep(.v-icon) { + transition: none !important; +}