fix(регистрация/моб): поля ввода 16px на мобильной ширине (iOS Safari без зума)
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker Public / Build + push Public (test + latest) (push) Waiting to run
Docker Public / Deploy :test → test.food-market.kz (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
Some checks are pending
Auto-tag / Create date-tag (push) Waiting to run
CI / Backend (.NET 8) (push) Waiting to run
CI / Web (React + Vite) (push) Waiting to run
CI / POS (WPF, Windows) (push) Waiting to run
Docker Public / Build + push Public (test + latest) (push) Waiting to run
Docker Public / Deploy :test → test.food-market.kz (push) Blocked by required conditions
Docker Web / Build + push Web (push) Waiting to run
Docker Web / Deploy Web on stage (push) Blocked by required conditions
iOS Safari зумит страницу при фокусе на поле с font-size < 16px и оставляет её увеличенной/сдвинутой. Делаем у текстовых полей text-base (16px) на мобильной ширине и sm:text-sm (14px) на планшете+. Запрет масштабирования (user-scalable=no) НЕ вводим — viewport-меты не трогаем. Затронуто: - public: SignupForm.inputCls (email/пароль/название + PhoneInput сайта); - кабинет: общий inputClass в Field.tsx (TextInput/Textarea/Select/Money/Percent) + поиск внутри выпадашек, PhoneInput кабинета, инлайн-поля LoginPage. Диапазон-слайдер конструктора тарифов не трогаем (type=range не зумится). Проверено в браузере (Playwright): на ширине 390 все поля формы регистрации 16px, на 900 — 14px. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
043d5c0417
commit
164ad57ed7
|
|
@ -154,8 +154,10 @@ export default function SignupForm({ defaultPlan = 'start' }: Props) {
|
|||
} finally { setBusy(false) }
|
||||
}
|
||||
|
||||
// text-base на мобильной ширине (16px) → iOS Safari не зумит страницу при
|
||||
// фокусе на поле; на sm и выше — привычные 14px. user-scalable=no НЕ ставим.
|
||||
const inputCls = (hasError: boolean) =>
|
||||
`w-full h-10 rounded-md border px-3 text-sm focus:outline-none focus:ring-2 ${
|
||||
`w-full h-10 rounded-md border px-3 text-base sm:text-sm focus:outline-none focus:ring-2 ${
|
||||
hasError ? 'border-red-400 focus:ring-red-300' : 'border-slate-300 focus:ring-brand'
|
||||
}`
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ export function Field({ label, error, children, className }: FieldProps) {
|
|||
)
|
||||
}
|
||||
|
||||
const inputClass = 'w-full h-10 rounded-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 px-3 text-sm leading-none focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] disabled:opacity-60 disabled:bg-slate-50 dark:disabled:bg-slate-800/60'
|
||||
// text-base на мобильной ширине (16px) → iOS Safari не зумит при фокусе; с sm —
|
||||
// привычные 14px. Запрет масштабирования (user-scalable=no) НЕ используем.
|
||||
const inputClass = 'w-full h-10 rounded-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 px-3 text-base sm:text-sm leading-none focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] disabled:opacity-60 disabled:bg-slate-50 dark:disabled:bg-slate-800/60'
|
||||
|
||||
export function TextInput(props: InputHTMLAttributes<HTMLInputElement>) {
|
||||
// Подключаем локализацию нативных подсказок валидации (required, type=email,
|
||||
|
|
@ -227,7 +229,7 @@ export function Select({
|
|||
value={query}
|
||||
onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="Поиск…"
|
||||
className="w-full h-8 rounded border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-2 text-sm focus:outline-none focus:ring-1 focus:ring-[var(--color-brand)]"
|
||||
className="w-full h-8 rounded border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-2 text-base sm:text-sm focus:outline-none focus:ring-1 focus:ring-[var(--color-brand)]"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') { e.preventDefault(); setOpen(false); setQuery('') }
|
||||
else if (e.key === 'ArrowDown') {
|
||||
|
|
@ -412,7 +414,7 @@ export function AsyncSelect({
|
|||
<div className="p-2 border-b border-slate-100 dark:border-slate-800">
|
||||
<input ref={searchRef} value={query} onChange={(e) => setQuery(e.target.value)}
|
||||
placeholder="Поиск…"
|
||||
className="w-full h-8 rounded border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-2 text-sm focus:outline-none focus:ring-1 focus:ring-[var(--color-brand)]"
|
||||
className="w-full h-8 rounded border border-slate-200 dark:border-slate-700 bg-white dark:bg-slate-900 px-2 text-base sm:text-sm focus:outline-none focus:ring-1 focus:ring-[var(--color-brand)]"
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') { e.preventDefault(); setOpen(false); setQuery('') }
|
||||
else if (e.key === 'ArrowDown') { e.preventDefault(); setHighlight((h) => Math.min(h + 1, Math.max(0, options.length - 1))) }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { useMemo, useRef, useLayoutEffect, type InputHTMLAttributes, type FormEvent } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const inputClass = 'w-full h-10 rounded-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 px-3 text-sm leading-none focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] disabled:opacity-60 disabled:bg-slate-50 dark:disabled:bg-slate-800/60 tabular-nums'
|
||||
// text-base на мобильной (16px) → iOS Safari не зумит при фокусе; sm → 14px.
|
||||
const inputClass = 'w-full h-10 rounded-md border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-900 px-3 text-base sm:text-sm leading-none focus:outline-none focus:ring-2 focus:ring-[var(--color-brand)] disabled:opacity-60 disabled:bg-slate-50 dark:disabled:bg-slate-800/60 tabular-nums'
|
||||
|
||||
// Код страны (+7) живёт в префиксе; оператор НЕ подставляем заранее, иначе
|
||||
// при вводе полного номера «7XX…» его первая цифра налезает на префиксную «7».
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ export function LoginPage() {
|
|||
onBlur={() => setEmailErr(validateEmail(email))}
|
||||
aria-invalid={emailErr ? true : undefined}
|
||||
aria-describedby={emailErr ? 'login-email-err' : undefined}
|
||||
className={`w-full rounded-md border bg-white dark:bg-slate-900 px-3 py-2 text-sm focus:outline-none focus:ring-2 ${emailErr ? 'border-red-400 focus:ring-red-300' : 'border-slate-300 dark:border-slate-600 focus:ring-[var(--color-brand)]'}`}
|
||||
className={`w-full rounded-md border bg-white dark:bg-slate-900 px-3 py-2 text-base sm:text-sm focus:outline-none focus:ring-2 ${emailErr ? 'border-red-400 focus:ring-red-300' : 'border-slate-300 dark:border-slate-600 focus:ring-[var(--color-brand)]'}`}
|
||||
/>
|
||||
{emailErr && <span id="login-email-err" role="alert" className="text-xs text-red-600 block mt-1">{emailErr}</span>}
|
||||
</label>
|
||||
|
|
@ -125,7 +125,7 @@ export function LoginPage() {
|
|||
onBlur={() => setPasswordErr(password ? null : messages.required)}
|
||||
aria-invalid={passwordErr ? true : undefined}
|
||||
aria-describedby={passwordErr ? 'login-password-err' : undefined}
|
||||
className={`w-full rounded-md border bg-white dark:bg-slate-900 px-3 py-2 text-sm focus:outline-none focus:ring-2 ${passwordErr ? 'border-red-400 focus:ring-red-300' : 'border-slate-300 dark:border-slate-600 focus:ring-[var(--color-brand)]'}`}
|
||||
className={`w-full rounded-md border bg-white dark:bg-slate-900 px-3 py-2 text-base sm:text-sm focus:outline-none focus:ring-2 ${passwordErr ? 'border-red-400 focus:ring-red-300' : 'border-slate-300 dark:border-slate-600 focus:ring-[var(--color-brand)]'}`}
|
||||
/>
|
||||
{passwordErr && <span id="login-password-err" role="alert" className="text-xs text-red-600 block mt-1">{passwordErr}</span>}
|
||||
</label>
|
||||
|
|
|
|||
Loading…
Reference in a new issue