最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Struggling with Multi-Line Input Field for Combined User and AI Text - Stack Overflow

programmeradmin0浏览0评论

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>

Problem:

  1. The input field is single-line, and I’m not enforcing line breaks.
  2. When aiText is present and long, it breaks mid-line, which disrupts the flow of the text.
  3. I want the input field to expand in height to accommodate a second line if needed, so aiText can wrap cleanly to the next line starting from the left edge.

What I’ve Tried:

  • Using contentEditable for dynamic text input.
  • Combining userText and aiText in a single container with inline-flex to keep them aligned.

Desired Behavior:

  • The input field should expand in height to allow multi-line text.
  • 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’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>

Problem:

  1. The input field is single-line, and I’m not enforcing line breaks.
  2. When aiText is present and long, it breaks mid-line, which disrupts the flow of the text.
  3. I want the input field to expand in height to accommodate a second line if needed, so aiText can wrap cleanly to the next line starting from the left edge.

What I’ve Tried:

  • Using contentEditable for dynamic text input.
  • Combining userText and aiText in a single container with inline-flex to keep them aligned.

Desired Behavior:

  • The input field should expand in height to allow multi-line text.
  • 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!

Share Improve this question edited Feb 5 at 22:21 isherwood 61.1k16 gold badges120 silver badges168 bronze badges asked Feb 5 at 17:47 ZethystZethyst 1531 silver badge8 bronze badges 1
  • 1 This is really an HTML/CSS question. I suggest extracting that from the React code and presenting it here as a demo snippet. Once you have a solution you can migrated it into your app. – isherwood Commented Feb 5 at 22:22
Add a comment  | 

1 Answer 1

Reset to default 2

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.

发布评论

评论列表(0)

  1. 暂无评论