Как лучше реализовать форму ввода как в веб-версии chatGPT?

Ссылка скопирована
0 ответов

Сейчас ситуация такая: делаю проект в связке next.js 16 + tailwind v4. Это просто обертка над llm под капотом (если не углубляться). На днях пытался сделать форму ввода как в веб-версии chatGPT. Изображения прикрепил ниже, вживуюТут.

6915cea4893c8285522825.png
6915ceab9c9f3894766437.png
6915ceb358b25502435903.png

По вводным: в какой-то момент пришел к выводу, что наилучшим решением будет делать гридами. Ещё понял, что нужно заводить два как бы кадра, между которыми будет происходить анимация, пускай называются до/после. Для флага, который переключает эти кадры заведем состояние isExpanded. Теперь получается вот такая разметка, если рассмотреть ее по грид-ареа:

  1. По вводным: первый кадр (isExpanded === false) --> у нас в грид сетке 1 ряд, 3 колонки, выглядит вот так:

    По вводным: | button | textarea | button button |

    По вводным: это повторяет разметку обычной формы ввода, которую сейчас пихают в ai приложения. Внутри формы слева-направо: кнопка с иконкой, поле ввода (textarea, contenteditable элемент), контейнер, внутри которого еще две кнопки с иконкой.

  2. По вводным: второй кадр (isExpanded === true) --> в грид сетке становится 2 ряда и 3 колонки, выглядит вот так:

    По вводным: | textarea | textarea | textarea |
    По вводным: | button | тут пусто| button button |

    По вводным: это уже разложенное состояние. В целом все понятно - сверху широкое поле ввода, а снизу остается ряд с кнопками для взаимодействия.

По вводным: все хорошо, но что должно триггерить изменение значения у isExpanded? Кажется, что все просто, нам ведь известна ширина элемента, она стабильна, потому что грид-ареа textarea стоит статично между двумя блоками, а родитель ограничен по ширине. То есть когда контент в textarea достигает границы ширины, то происходит перенос строки, далее textarea вырастет в высоту в два раза, потому что начнется вторая строка. Будто можно брать этот момент за флаг, который будет переключать isExpanded в состояние true.

Тут не знаю, стоит ли пояснять, но по начальной задумке одна строка в текстаре равна по высоте всем остальным элементам формы (как в chatGPT), все стоит ровно, горизонтально и классно.

Сейчас ситуация такая: тут случится проблема - isExpanded переключилось и, соответственно, вся форма поменяла грид-сетку на состояние второго кадра и ширина грид-ареа textarea увеличилась, потому что элемент теперь в верхнем ряду, а значит к нему добавилась ширина других двух колонок грида. Вот тут самый прикол - при вводе следующего символа состояние isExpanded снова изменится, потому что теперь первая строка символов норм помещается в этот ряд, а потом еще раз так, и еще раз. И с каждым таким переключение isExpanded будет переключаться, форму будет переключать между первым и вторым кадром туда-сюда. В какой-то момент предел будет достигнут и форма статично встанет во второй кадр. Такое не пойдет.

По вводным: вот тут кажется логичным и простым решением зафиксировать флаг isExpanded в состояние true в самый первый момент изменения высоты textarea, чтобы форма зафиксировалась во втором кадре и дальше такой и оставалась, а при удалении символов можно просто сбрасывать обратно первый кадр, когда удалены все до последнего символы в поле ввода.

Сейчас ситуация такая: вроде бы схема рабочая, подумал я и пошел делать. Далее встал вопрос анимации, потому что до текущего момента это было просто слайд-шоу из двух кадров. А анимировать я не сумел, только очень коряво. Я проверял анимировать гриды, потому что знал, что вроде как их можно анимировать нативным css, но выходило очень некрасиво, кнопки могли терять форму (сжаться/развернуться) в процессе, текст перескакивал невнятно и очень неуверенно. Я далее попроверял поиграться с паддингами у textarea, вроде выровнял таким образом, что сдвига текста сильно не видно и при этом сама форма выглядит органично.

По вводным: в целом результат получился на 5/10. Очень странные и смешаные чувства испытал я в этот момент и пошел искать другие решения. Вспомнил про библиотеку framer, которая умеет анимировать изменения лейаута. Зашел в документацию, прочитал, подумал, начал делать. В результате пришлось все равно долго разбираться в настройке анимации, хотя сперва думал, что минут 30 это максимум займет. Настроил изменение лейаута через этот же пропс layout на каждом элементе и вроде как сработало. Выглядело лучше, чем анимация на чистом css, но все равно очень тупо и неказисто.

По вводным: вот тут и встает вопрос, а как можно реализовать форму ввода, которая будет повторять поведение формы ввода как в веб-версии chatGPT? Если у кого-то есть хорошие идеи, предложения, рекомендации, примеры кода, какие-то пояснения, хоть что-то -Дайте знать,.

Сейчас ситуация такая: ещё важный момент - поле ввода, именно куда вводится текст будущего промпта, может быть реализовано по сути либо элементом textarea, либо же contenteditable div, потому что оба имеют возможность расти в высоту. Я и попроверял, но результат был плюс-минус таким же. Большую часть времени я все-таки тестил это дело с textarea внутри, потому что в chatGPT используется именно contenteditable компонент, потому что есть возможность вставлять туда изображения и прикреплять вложения. В мои задачи это не входило, потому что я не планирую добавлять этот функционал, хоты бы пока. Поэтому самым простым решением и было вставить textarea. Тут ещё просто для справки стоит сказать, что в gpt все-таки учтена адаптивность, поэтому не помню на каком разрешении contenteditable элемент меняется на обычный textarea.

Нужно решить такую задачу?

Опишите проблему, и специалист поможет с настройкой, исправлением ошибки или доработкой сайта. Подберём понятный план работ без лишней переписки.

Заказать помощь
Другие ответы (0)

Пока нет других ответов. Будьте первым, кто поможет автору.

Ответить на вопрос

комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Вам также может быть интересно