6.7 KiB
ADR-076: Панель ввода iOS системная, строка сообщения — textarea
Пересматривает ADR-064, ADR-069 и ADR-071. Уточняет docs/ui.md, «Чат» и «Доступность».
Контекст
В v1.1 строка сообщения прошла два варианта: textarea вынесли из <form>, затем заменили на contenteditable="plaintext-only". Оба решения исходили из предположения, что системная полоса iOS со стрелками и «готово» появляется только у поля формы.
Проверка v1.1 на реальном iPhone опровергла предположение: полоса осталась и у contenteditable. Это часть клавиатурного интерфейса WebKit, а не узел страницы. Web API для её отключения нет. В нативной оболочке внешний вид клавиатуры может менять хост iOS; установленная PWA остаётся веб-страницей и такого доступа не получает.
На том же экране часть потерянного места оказалась не системной панелью: строка ввода всегда добавляла 20px + env(safe-area-inset-bottom). Safari сохраняет нижний safe-area домашнего индикатора и после появления клавиатуры, хотя её прямоугольная поверхность уже закрывает этот край. Получалась отдельная пустая полоса примерно той же высоты, что системная панель.
contenteditable при этом стоил клиенту ручной реализации подсказки, предела, вставки без разметки, переноса строки, disabled, счётчика, работы IME и запасного пути для браузеров без plaintext-only. Главное следствие ADR-069 не наступило, а цена осталась.
Решение
- Строка сообщения снова становится
textareaс нативнымиplaceholder,maxLength,disabled, выделением, вставкой и отменой. Числоrowsсчитается по фактической высоте текста от одной до семи: это сохраняет автовысоту в Safari без поддержкиfield-sizing. Доступное имя повторяет подсказку черезaria-label, кнопка>объявляется как «отправить»;autocapitalize,autocorrectиenterkeyhintостаются прежними. - Контейнер
div role="form"и кнопкаtype="button"остаются. Они не убирают системную панель, но и не создают отдельного поведения; менять их ещё раз без причины незачем. - Системная панель iOS принимается как ограничение веб-клиента.
inputmode="none"и собственная экранная клавиатура не используются: убрать вместе с панелью системную клавиатуру означает потерять обычный набор, раскладки, диктовку и доступность. - Нативная iOS-оболочка не добавляется в Bare. Если абсолютное управление панелью станет требованием, это отдельный продуктовый и архитектурный выбор.
- Тап по неинтерактивному месту истории вызывает
blur()строки сообщения и закрывает клавиатуру. Кнопки и ссылки в ленте сохраняют своё действие. - Пока поле сфокусировано и
visualViewportуменьшен как при экранной клавиатуре, весь обычный нижний отступ строки ввода (20px + safe-areaна узком экране,28px + safe-areaна широком) заменяется на 6 px. Эвристика сверяет масштаб и ширину и требует существенного уменьшения высоты; один фокус не считается клавиатурой, поэтому с физической клавиатурой обычный отступ остаётся. При закрытии размеры пересчитываются. Смена ширины после фокуса и уход приложения в фон возвращают полный безопасный отступ до следующего тапа по полю: известное старое значениеvisualViewportпосле поворота или возврата не должно прижать ввод к домашнему индикатору.
Следствия
- Строка сообщения снова опирается на браузерное текстовое поле и стала заметно проще. Лишнее не проходит через
maxLength; ручная обработкаbeforeinput, вставки, IME и текстовых узлов удалена. - Полоса со стрелками и «готово» на iPhone остаётся. Код и документация больше не обещают веб-странице контроль над системным UI.
- Пустой зазор между строкой ввода и системной панелью исчезает; место возвращается истории без вмешательства в клавиатуру.
- Тап по истории возвращает место ленте без нажатия системной кнопки «готово».
- Проверка самой панели и точного момента перестроения
visualViewportпо-прежнему требует реального iPhone в Safari и установленном PWA; поведениеtextarea, отправки, эвристики размеров и снятия фокуса проверяется в обычном браузере.