I’m working on an input field that combines user input (userText
) and AI-generated suggestions (aiText
). The goal is to make them appear as part of the same sentence, even when the user hasn’t accepted the AI’s suggestions yet.
Currently, the input field is single-line, and when aiText
is longer, it breaks awkwardly in the middle of the input field, making it look disjointed. Ideally, if aiText
needs to wrap to a new line, it should start from the very left of the input component, not from the middle where userText
ends.
Here’s the current implementation:
<div
onClick={focusContentEditable}
className="relative flex justify-start items-start p-3 border border-border
bg-[#FFFFFF] text-[#1F1F1F] dark:bg-[#2A2A40] dark:text-[#EAEAEA]
focus-within:outline focus-within:outline-[#9462fd]
cursor-text rounded-2xl text-left w-full h-20 mx-auto
overflow-hidden"
>
{/* Placeholder */}
{userText.trim() === "" && !isFocused && (
<span className="text-gray-400 text-xs">Ask me anything...</span>
)}
<div className="inline-flex items-baseline">
<span
ref={contentEditableRef}
className="text-xs border-0 outline-none whitespace-nowrap break-words inline-flex min-h-[20px] w-full"
contentEditable={true}
suppressContentEditableWarning={true}
onInput={handleInput}
onKeyDown={handleKeyDown}
>
{/* {userText} */}
</span>
<span
className={`text-xs text-gray-400 dark:text-gray-600 transition-opacity whitespace-normal inline-flex duration-500 ${
aiText ? "opacity-100" : "opacity-0"
}`}
contentEditable={false}
>
{aiText.length > 0 && userText.trim() !== "" && <>{aiText}</>}
</span>
</div>
</div>
aiText
is present and long, it breaks mid-line, which disrupts the flow of the text.aiText
can wrap cleanly to the next line starting from the left edge.contentEditable
for dynamic text input.userText
and aiText
in a single container with inline-flex
to keep them aligned.aiText
should wrap to the next line starting from the left edge if it doesn’t fit in the current line.userText
and aiText
should appear as part of the same sentence.Any suggestions on how to achieve this? Thanks in advance!
I could definitely be missing something here, but I believe a <span contentEditable={false}>
tag inside of a <p contentEditable={true}>
tag should suffice to achieve your desired behavior.
<p className="whitespace-pre-wrap" contentEditable={true}>
This is some user input text
<span contentEditable={false} className="text-xs text-gray-400">
Here is some extremely looooooong looong looong looooong AI text
</span>
</p>
We use the Tailwind class whitespace-pre-wrap
to automatically wrap the aiText
to the next line, should it overflow.