Чат v1.1.1: убрать лишний отступ над клавиатурой
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
Уточняет [ADR-024](024-identity-and-ui.md): типографика из `docs/identity/brief.md` остаётся как записана, а страница перестаёт масштабироваться.
|
||||
|
||||
Уточнён [ADR-076](076-ios-input-accessory-is-system.md): строка сообщения снова стала `textarea`; она уже входит в перечень элементов управления, по которым второй тап не гасится.
|
||||
Уточнён [ADR-076](076-ios-input-accessory-is-system.md): строка сообщения снова стала `textarea`, входит в перечень элементов управления, по которым второй тап не гасится, и заменяет весь нижний отступ на 6 px только при открытой экранной клавиатуре.
|
||||
|
||||
## Контекст
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
- Страховка на JS — `web/js/zoom.js`: мета-строке Safari верен не всегда. Слушатели непассивные, иначе `preventDefault` не действует. `gesturestart`, `gesturechange`, `gestureend` — события щипка, они бывают только в Safari — гасятся целиком. Второй тап подряд, ближе 350 мс и 40 px к первому, гасится, если он не по элементу управления: `preventDefault` на `touchend` уносит с собой `click`, а нажать кнопку дважды подряд — обычное дело. Прокрутка, свайпы и одиночные нажатия не трогаются вовсе.
|
||||
- `overscroll-behavior: none` у страницы и `contain` у лент: резинового отскока и «потянуть для обновления» нет, прокрутка внутри лент прежняя.
|
||||
- Выделение текста снято с шапки, сайдбара, кнопок и разделителей: долгое нажатие по ним показывало лупу и «копировать», а копировать там нечего. С текста сообщений, отпечатков, полей ввода и версии в подвале сайдбара (ADR-067) не снято — их копируют; версию на iPhone взять больше неоткуда, там нет ни строки адреса, ни консоли.
|
||||
- `viewport-fit=cover` пускает страницу под вырез и системную полосу, поэтому отступы считаются с ней: подвал сайдбара и строка ввода добавляют к нижнему полю `env(safe-area-inset-bottom)`, страница — боковые и верхнюю вставки. Верхняя при `status-bar-style: default` нулевая и не делает ничего; она стоит на случай, когда браузер решит иначе, — строка кода против шапки, уехавшей под часы.
|
||||
- `viewport-fit=cover` пускает страницу под вырез и системную полосу, поэтому отступы считаются с ней: подвал сайдбара и строка ввода добавляют к нижнему полю `env(safe-area-inset-bottom)`, страница — боковые и верхнюю вставки. Когда открыта экранная клавиатура, обычные `20px + env(safe-area-inset-bottom)` строки ввода заменяются на 6 px по ADR-076: клавиатура уже закрывает домашний индикатор. Верхняя вставка при `status-bar-style: default` нулевая и не делает ничего; она стоит на случай, когда браузер решит иначе, — строка кода против шапки, уехавшей под часы.
|
||||
|
||||
## Следствия
|
||||
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
Проверка 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 не наступило, а цена осталась.
|
||||
|
||||
## Решение
|
||||
@@ -17,10 +19,12 @@
|
||||
- Системная панель iOS принимается как ограничение веб-клиента. `inputmode="none"` и собственная экранная клавиатура не используются: убрать вместе с панелью системную клавиатуру означает потерять обычный набор, раскладки, диктовку и доступность.
|
||||
- Нативная iOS-оболочка не добавляется в Bare. Если абсолютное управление панелью станет требованием, это отдельный продуктовый и архитектурный выбор.
|
||||
- Тап по неинтерактивному месту истории вызывает `blur()` строки сообщения и закрывает клавиатуру. Кнопки и ссылки в ленте сохраняют своё действие.
|
||||
- Пока поле сфокусировано и `visualViewport` уменьшен как при экранной клавиатуре, весь обычный нижний отступ строки ввода (`20px + safe-area` на узком экране, `28px + safe-area` на широком) заменяется на 6 px. Эвристика сверяет масштаб и ширину и требует существенного уменьшения высоты; один фокус не считается клавиатурой, поэтому с физической клавиатурой обычный отступ остаётся. При закрытии размеры пересчитываются. Смена ширины после фокуса и уход приложения в фон возвращают полный безопасный отступ до следующего тапа по полю: известное старое значение `visualViewport` после поворота или возврата не должно прижать ввод к домашнему индикатору.
|
||||
|
||||
## Следствия
|
||||
|
||||
- Строка сообщения снова опирается на браузерное текстовое поле и стала заметно проще. Лишнее не проходит через `maxLength`; ручная обработка `beforeinput`, вставки, IME и текстовых узлов удалена.
|
||||
- Полоса со стрелками и «готово» на iPhone остаётся. Код и документация больше не обещают веб-странице контроль над системным UI.
|
||||
- Пустой зазор между строкой ввода и системной панелью исчезает; место возвращается истории без вмешательства в клавиатуру.
|
||||
- Тап по истории возвращает место ленте без нажатия системной кнопки «готово».
|
||||
- Проверка самой панели по-прежнему требует реального iPhone; поведение `textarea`, отправки и снятия фокуса проверяется в обычном браузере.
|
||||
- Проверка самой панели и точного момента перестроения `visualViewport` по-прежнему требует реального iPhone в Safari и установленном PWA; поведение `textarea`, отправки, эвристики размеров и снятия фокуса проверяется в обычном браузере.
|
||||
|
||||
@@ -42,7 +42,7 @@ font-family: ui-monospace, "SF Mono", Menlo, Consolas, "DejaVu Sans Mono", monos
|
||||
## Компоновка
|
||||
|
||||
- Десктоп: сайдбар 224 px с правой границей `line`, шапка 64 px, отступы контента 32 px.
|
||||
- Мобильный: шапка 56 px, отступы 20 px, ввод с min-height 44 px. Нижнее поле подвала и строки ввода считается с `env(safe-area-inset-bottom)`: под системную полосу iPhone они не заходят (ADR-075).
|
||||
- Мобильный: шапка 56 px, отступы 20 px, ввод с min-height 44 px. Нижнее поле подвала и строки ввода считается с `env(safe-area-inset-bottom)`: под системную полосу iPhone они не заходят. При открытой экранной клавиатуре её прямоугольник уже защищает край, поэтому обычные `20px + safe-area` строки ввода заменяются компактными 6 px (ADR-076).
|
||||
- Сообщения — поток, автор и время над текстом; на телефоне и планшете свои — у правого края, чужие — у левого, на десктопе все — у левого; ширина блока не больше `min(640px, 85%)` (ADR-077).
|
||||
- Ввод — рамка 1 px ink, без скруглений, `>` цветом mark слева.
|
||||
- Активный элемент списка — инверсия: фон ink, текст bone.
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
|
||||
Без inline-стилей и inline-скриптов (CSP). Рендер — `document.createElement` и `textContent`; `innerHTML` не используется нигде: сообщения — пользовательские данные.
|
||||
|
||||
Страница ведёт себя как приложение, а не как документ (ADR-075): масштабирования нет, резинового отскока нет, выделение снято с шапки, сайдбара, кнопок и разделителей — но не с текста сообщений, отпечатков, полей ввода и версии в подвале сайдбара: их копируют. Установленное на «Домой» приложение объявлено мета-строками, имя на экране — `bare`, системная полоса остаётся над страницей. Подвал сайдбара и строка ввода отступают от нижней системной полосы iPhone.
|
||||
Страница ведёт себя как приложение, а не как документ (ADR-075): масштабирования нет, резинового отскока нет, выделение снято с шапки, сайдбара, кнопок и разделителей — но не с текста сообщений, отпечатков, полей ввода и версии в подвале сайдбара: их копируют. Установленное на «Домой» приложение объявлено мета-строками, имя на экране — `bare`, системная полоса остаётся над страницей. Подвал сайдбара и строка ввода отступают от нижней системной полосы iPhone; у строки весь нижний отступ становится 6 px, пока край уже закрыт экранной клавиатурой (ADR-076).
|
||||
|
||||
## Вход и регистрация
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
Лента открывается последними 50 сообщениями и стоит в конце. Прокрутка к верхнему краю подгружает следующие 50; то, что человек читает, при этом не двигается. Загруженное остаётся в разметке целиком — виртуализации нет (ADR-053).
|
||||
|
||||
Ввод: рамка 1 px ink, слева `>` цветом `mark`, подсказка «сообщение в #general» / «сообщение»; имя комнаты в подсказке обрезается до 12 символов многоточием — «сообщение в #длинноеимя…» (ADR-061), в шапке оно остаётся полным. Enter — отправить, Shift+Enter — перенос; на мобильном Enter — перенос, отправка — кнопка `>` справа. Подсказка «enter — отправить» только на десктопе. Лимит 4000 — счётчик появляется после 3500; нативный `maxLength` не пускает лишнее. Тап по неинтерактивному месту истории снимает фокус со строки и закрывает клавиатуру (ADR-076).
|
||||
Ввод: рамка 1 px ink, слева `>` цветом `mark`, подсказка «сообщение в #general» / «сообщение»; имя комнаты в подсказке обрезается до 12 символов многоточием — «сообщение в #длинноеимя…» (ADR-061), в шапке оно остаётся полным. Enter — отправить, Shift+Enter — перенос; на мобильном Enter — перенос, отправка — кнопка `>` справа. Подсказка «enter — отправить» только на десктопе. Лимит 4000 — счётчик появляется после 3500; нативный `maxLength` не пускает лишнее. Тап по неинтерактивному месту истории снимает фокус со строки и закрывает клавиатуру. Пока открыта экранная клавиатура, весь нижний отступ строки заменяется 6 px; при физической клавиатуре и после закрытия обычный отступ сохраняется (ADR-076).
|
||||
|
||||
Строка сообщения — `textarea` (ADR-076): она принимает только текст, сама держит вставку, выделение, отмену, подсказку, предел и состояние `disabled`. Растёт под содержимое, дальше семи строк — прокрутка. Системную панель со стрелками и «готово» iOS рисует поверх клавиатуры и для `textarea`, и для `contenteditable`; у веб-страницы нет поддерживаемого API, чтобы её скрыть. Полное управление этой панелью потребовало бы отдельной нативной iOS-оболочки; собственная экранная клавиатура в веб-клиенте не делается.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user