mobile: textarea text-base on mobile to suppress iOS Safari zoom-on-focus

Five textareas in the app (Coach composer, bug-report description,
admin feedback note, medication-side-effects notes, medication-intake
JSON import) shipped `text-sm` (14 px) on every viewport. iOS Safari
triggers a viewport zoom-on-focus whenever an input renders text
below 16 px — so every tap on these surfaces yanked the page scale
and rebounded on blur. Switched each className to `text-base sm:text-sm`
so the mobile baseline clears 16 px while desktop keeps the compact
look the rest of the form chrome converged on.

No shared <Textarea> primitive exists yet — F-5's deferred work — so
the fix is per-call-site. Five files, one className change each, no
component re-shape.
This commit is contained in:
Marc-André Bombeck committed 2026-05-17 00:51:47 +02:00
1 parent 02003428df
commit 03e8627765
5 files changed
+19 -5

No files matched your search

+3 -1
View File
@@ -207,7 +207,9 @@ export default function BugReportPage() {
minLength={10}
maxLength={5000}
rows={8}
className="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none"
// text-base on mobile so iOS Safari doesn't zoom on
// focus; text-sm on sm+ keeps the compact desktop look.
className="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-base focus-visible:ring-2 focus-visible:outline-none sm:text-sm"
/>
</div>
+3 -1
View File
@@ -466,7 +466,9 @@ function IntakeImportDialog({
onChange={(e) => setJsonText(e.target.value)}
placeholder={t("medications.importPaste")}
rows={8}
className="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 font-mono text-sm focus-visible:ring-2 focus-visible:outline-none"
// text-base on mobile so iOS Safari doesn't zoom on
// focus; text-sm on sm+ for the compact import textarea.
className="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 font-mono text-base focus-visible:ring-2 focus-visible:outline-none sm:text-sm"
/>
{result && (
<p
@@ -501,7 +501,9 @@ function FeedbackDetailDialog({
rows={3}
maxLength={5000}
placeholder={t("admin.feedback.adminNotePlaceholder")}
className="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:outline-none"
// text-base on mobile so iOS Safari doesn't zoom on
// focus; text-sm on sm+ keeps the compact admin look.
className="border-input bg-background text-foreground placeholder:text-muted-foreground focus-visible:ring-ring w-full rounded-md border px-3 py-2 text-base focus-visible:ring-2 focus-visible:outline-none sm:text-sm"
/>
<div className="flex justify-end">
<Button
@@ -208,7 +208,12 @@ export function CoachInput({
// `max-h-[9.5rem]`, ≈6 lines at the current line-height).
rows={1}
className={cn(
"w-full resize-none bg-transparent text-sm leading-relaxed outline-none",
// `text-base` (16 px) on mobile so iOS Safari does not
// zoom-on-focus — the kerned `text-sm` (14 px) trips the
// 16 px floor and yanks the viewport on every Coach tap.
// Desktop shrinks back to `text-sm` for the compact
// composer.
"w-full resize-none bg-transparent text-base leading-relaxed outline-none sm:text-sm",
"max-h-[9.5rem] overflow-auto",
"placeholder:text-muted-foreground disabled:opacity-60",
)}
@@ -474,7 +474,10 @@ export function SideEffectsSection({ medicationId }: SideEffectsSectionProps) {
enterKeyHint="done"
autoCapitalize="sentences"
autoComplete="off"
className="border-input bg-background text-foreground w-full rounded-md border px-2 py-1.5 text-sm"
// text-base on mobile so iOS Safari doesn't
// zoom-on-focus; text-sm on sm+ keeps the compact
// notes-row visual.
className="border-input bg-background text-foreground w-full rounded-md border px-2 py-1.5 text-base sm:text-sm"
/>
<p className="text-muted-foreground text-right text-[10px]">
{notes.length} / {NOTES_MAX}