Files
bare/docs/decisions/064-composer-not-form.md
T
mayatnikovandClaude Opus 5 547637067d Слить main: стороны сообщений поверх строки ввода iOS
Обе ветки правили строку ввода чата ради одной и той же полосы
помощника форм над клавиатурой iOS. ADR-064 из main считал триггером
элемент form и вынес поле наружу; на устройстве не помогло — полоса
бывает у input и textarea всегда. ADR-069 отсюда заменяет поле
редактируемым блоком, это и есть «следующий шаг» из следствий ADR-064.

Что взято:
- строка ввода — редактируемый блок (ADR-069/071), контейнер div
  с role="form" и кнопка type="button" (ADR-064);
- лента — поток со сторонами, feed-list (ADR-065), не сетка;
- brief.md: safe-area из ADR-075 и стороны из ADR-065 вместе;
- app.css: правило 44 px для блока ввода; .author:empty из медиазапроса
  убран — main вынес его на верхний уровень, сетки больше нет.

Убран слушатель submit: контейнер стал div, событие не случается.
ADR-064 и ADR-069 связаны ссылками в обе стороны.

sw.js VERSION → v6: клиент отличается от обеих версий, где стоял v5.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QR8uS3zGkybzWRW4GEY1oz
2026-08-24 11:26:09 +03:00

4.0 KiB
Raw Blame History

ADR-064: строка ввода — div, а не form

Уточняет docs/ui.md, «Доступность»: form в списке семантики держит role="form", а не элемент <form>, — для строки ввода чата.

Пересмотрен ADR-069. Диагноз здесь неверен: полосу помощника форм iOS рисует не из-за <form>, а для любых input и textarea, — вынос поля из формы её не убрал. Контейнер div с role="form" и кнопка type="button" остаются, textarea заменён редактируемым блоком — тем самым «следующим шагом», который записан ниже в «Следствиях».

Контекст

Тест с реальными пользователями (iPhone, Safari и Chrome): над клавиатурой при фокусе в строке ввода всплывает системная панель навигации между полями — «‹ ›» и «готово», около 50 px. Полю переходить некуда — оно на экране одно, — а место съедено.

Панель — не наша вёрстка, это поведение WebKit для полей, лежащих внутри <form>. Строка ввода была оформлена именно так: <form class="compose"> с <textarea> и кнопкой type="submit".

Дорогой вариант — contenteditable вместо textarea — снял бы панель гарантированно, но потребовал бы вручную переписать то, что сейчас даёт браузер бесплатно: placeholder, обрезку на 4000 символов, автовысоту, и обязательно — очистку paste до текста, потому что contenteditable иначе вставляет форматированный HTML, а innerHTML в клиенте запрещён (CLAUDE.md).

Дешёвый вариант — вынести поле из <form> — не трогает ничего из этого: textarea остаётся textarea.

Решение

  • <form class="compose"><div class="compose" role="form">. role="form" — тот же ориентир для скринридера, что и элемент <form>, без вызывающих панель heuristics WebKit.
  • Кнопка отправки — type="button" с явным click, вместо type="submit" и события submit на форме.
  • autocomplete="off" на самом поле — на случай, если панель зависит ещё и от него, а не только от <form>.
  • textarea, maxLength, field-sizing: content, placeholder — без изменений.

Остальные формы (вход, #/new, участники, настройки) не тронуты: там несколько полей в форме, панель навигации между ними — по крайней мере, не чистый минус, и незачем менять то, что не жаловались.

Следствия

  • Проверить можно только на реальном устройстве — эмуляции панели WebKit нет; headless-Chromium её и не показывал никогда, так что автотест здесь не поставить.
  • Если панель не уйдёт (вдруг триггер — не <form>, а что-то ещё в эвристике Safari), следующий шаг — contenteditable, со всей его ценой из «Контекста».
  • Enter на десктопе и кнопка «>» на мобильном по-прежнему отправляют — обработчики keydown и click делают то же, что раньше submit.