Fix iOS Safari auto-zoom on input fields

- Changed all input/textarea/select font-size from text-sm to text-base (16px minimum)
- Added blur handler to reset viewport zoom on InlineItemCreate
- Prevents iOS Safari from auto-zooming when focusing on form fields
- Ensures zoom resets properly when closing forms
This commit is contained in:
2025-12-03 21:01:17 +00:00
parent 1e7aa6ae5d
commit 2f2cc309a3
2 changed files with 17 additions and 7 deletions

View File

@@ -63,6 +63,10 @@ export default function InlineItemCreate({ listId }: InlineItemCreateProps) {
const handleCancel = () => { const handleCancel = () => {
setTitle('') setTitle('')
setIsCreating(false) setIsCreating(false)
// Reset zoom on iOS Safari
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur()
}
} }
const handleKeyDown = (e: React.KeyboardEvent) => { const handleKeyDown = (e: React.KeyboardEvent) => {
@@ -71,6 +75,11 @@ export default function InlineItemCreate({ listId }: InlineItemCreateProps) {
} }
} }
const handleBlur = () => {
// Force viewport reset on iOS Safari
window.scrollTo(0, 0)
}
if (!isCreating) { if (!isCreating) {
return ( return (
<button <button
@@ -94,10 +103,11 @@ export default function InlineItemCreate({ listId }: InlineItemCreateProps) {
setError('') setError('')
}} }}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
onBlur={handleBlur}
placeholder="Enter task title..." placeholder="Enter task title..."
autoFocus autoFocus
maxLength={200} maxLength={200}
className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base ${ className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-base ${
error ? 'border-red-500 focus:ring-red-500' : 'border-gray-300 focus:ring-blue-500' error ? 'border-red-500 focus:ring-red-500' : 'border-gray-300 focus:ring-blue-500'
}`} }`}
aria-invalid={error ? 'true' : 'false'} aria-invalid={error ? 'true' : 'false'}

View File

@@ -264,7 +264,7 @@ export default function ItemForm({ listId, item, mode = 'edit', canEdit = true }
onChange={(e) => setTitle(e.target.value)} onChange={(e) => setTitle(e.target.value)}
onBlur={() => handleBlur('title')} onBlur={() => handleBlur('title')}
disabled={!canEdit} disabled={!canEdit}
className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base ${ className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-base ${
errors.title && touched.title errors.title && touched.title
? 'border-red-500 focus:ring-red-500' ? 'border-red-500 focus:ring-red-500'
: 'border-gray-300 focus:ring-blue-500' : 'border-gray-300 focus:ring-blue-500'
@@ -293,7 +293,7 @@ export default function ItemForm({ listId, item, mode = 'edit', canEdit = true }
onBlur={() => handleBlur('description')} onBlur={() => handleBlur('description')}
disabled={!canEdit} disabled={!canEdit}
rows={3} rows={3}
className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base resize-y ${ className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-base resize-y ${
errors.description && touched.description errors.description && touched.description
? 'border-red-500 focus:ring-red-500' ? 'border-red-500 focus:ring-red-500'
: 'border-gray-300 focus:ring-blue-500' : 'border-gray-300 focus:ring-blue-500'
@@ -320,7 +320,7 @@ export default function ItemForm({ listId, item, mode = 'edit', canEdit = true }
value={priority} value={priority}
onChange={(e) => setPriority(e.target.value as 'low' | 'medium' | 'high')} onChange={(e) => setPriority(e.target.value as 'low' | 'medium' | 'high')}
disabled={!canEdit} disabled={!canEdit}
className={`w-full px-3 sm:px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm sm:text-base tap-target ${!canEdit ? 'bg-gray-100 cursor-not-allowed' : ''}`} className={`w-full px-3 sm:px-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 text-base tap-target ${!canEdit ? 'bg-gray-100 cursor-not-allowed' : ''}`}
> >
<option value="low">Low</option> <option value="low">Low</option>
<option value="medium">Medium</option> <option value="medium">Medium</option>
@@ -340,7 +340,7 @@ export default function ItemForm({ listId, item, mode = 'edit', canEdit = true }
onChange={(e) => setDueDate(e.target.value)} onChange={(e) => setDueDate(e.target.value)}
onBlur={() => handleBlur('dueDate')} onBlur={() => handleBlur('dueDate')}
disabled={!canEdit} disabled={!canEdit}
className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base tap-target ${ className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-base tap-target ${
errors.dueDate && touched.dueDate errors.dueDate && touched.dueDate
? 'border-red-500 focus:ring-red-500' ? 'border-red-500 focus:ring-red-500'
: 'border-gray-300 focus:ring-blue-500' : 'border-gray-300 focus:ring-blue-500'
@@ -370,7 +370,7 @@ export default function ItemForm({ listId, item, mode = 'edit', canEdit = true }
onChange={(e) => setTagInput(e.target.value)} onChange={(e) => setTagInput(e.target.value)}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
disabled={!canEdit} disabled={!canEdit}
className={`flex-1 px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base ${ className={`flex-1 px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-base ${
errors.tagInput errors.tagInput
? 'border-red-500 focus:ring-red-500' ? 'border-red-500 focus:ring-red-500'
: 'border-gray-300 focus:ring-blue-500' : 'border-gray-300 focus:ring-blue-500'
@@ -432,7 +432,7 @@ export default function ItemForm({ listId, item, mode = 'edit', canEdit = true }
onBlur={() => handleBlur('notes')} onBlur={() => handleBlur('notes')}
disabled={!canEdit} disabled={!canEdit}
rows={5} rows={5}
className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-sm sm:text-base resize-y ${ className={`w-full px-3 sm:px-4 py-3 border rounded-lg focus:outline-none focus:ring-2 text-base resize-y ${
errors.notes && touched.notes errors.notes && touched.notes
? 'border-red-500 focus:ring-red-500' ? 'border-red-500 focus:ring-red-500'
: 'border-gray-300 focus:ring-blue-500' : 'border-gray-300 focus:ring-blue-500'