輸入元件

提及輸入框

輸入 @ 觸發人員選單,插入高亮提及籤條的文字區。

這是 WebberUI Pro 元件

下方的安裝指令需要授權才能執行,未授權時會回 401。

怎麼安裝 Pro 元件 →查看方案 →

輸入 @ 即時開啟可鍵盤操作的成員浮動選單,選中後插入彩色高亮的 @名稱 籤條,並透過 onChange 回傳目前文中所有被提及的成員,適合留言、評論與協作工具的輸入場景。

把這個效果裝進你的專案

在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。

npx webberui@latest add "https://webberui.com/r/mention-textarea.json?t=<安裝 token>"

還沒有專案,或安裝遇到問題?看快速開始 →

Mention Textarea 是用 React、Tailwind CSS 與 Motion 做的 @ 提及輸入框(mention input)元件:以原生 textarea 搭配一層同步捲動的高亮鏡像,輸入 @ 時開啟可用鍵盤操作的成員選單,選中後在文字中插入帶色的 @名稱。

Playground

即時調整 props、程式碼片段同步更新——直接試出你要的樣子再複製。

4
6
編輯中的呼叫預設屬性
<MentionTextarea/>

完整範例包含預覽的排版與資料。先安裝元件,再把範例檔貼入你的專案。

適用情境

  • 專案管理或協作工具的留言、任務評論欄,用 @ 通知相關成員。
  • 客服或工單系統的內部備註,標記需要接手的同事。
  • 設計稿、文件審閱的回饋輸入框。
  • 團隊內部的公告或聊天訊息輸入區。
  • 不適合:只需要從清單挑選多位成員、不需要寫在文字裡時,改用 Tag Input。

安裝

npx webberui@latest add "https://webberui.com/r/mention-textarea.json?t=<安裝 token>"

或在 components.json 設定 registries 後,改用 @webberui/mention-textarea 安裝。

使用

import {
  MentionTextarea,
  type MentionUser,
} from "@/components/ui/mention-textarea";

const users: MentionUser[] = [
  { id: "u1", name: "林小美", hue: 340, title: "產品設計師" },
  { id: "u2", name: "陳大文", hue: 210, title: "前端工程師" },
];

<MentionTextarea
  users={users}
  placeholder="輸入訊息,使用 @ 提及成員…"
  onChange={(value, mentions) => console.log(value, mentions)}
/>

範例

受控模式與送出留言

用 value 與 onChange 管理內容;onChange 的第二個參數是目前文中提及的成員(已去重),送出時可以把成員 id 一併傳給後端發送通知。

"use client";

import * as React from "react";
import {
  MentionTextarea,
  type MentionUser,
} from "@/components/ui/mention-textarea";

export function CommentBox({ users, taskId }: { users: MentionUser[]; taskId: string }) {
  const [text, setText] = React.useState("");
  const [mentions, setMentions] = React.useState<MentionUser[]>([]);

  async function submit() {
    await fetch(`/api/tasks/${taskId}/comments`, {
      method: "POST",
      body: JSON.stringify({ text, mentionIds: mentions.map((u) => u.id) }),
    });
    setText("");
    setMentions([]);
  }

  return (
    <div className="space-y-2">
      <MentionTextarea
        users={users}
        value={text}
        onChange={(value, list) => {
          setText(value);
          setMentions(list);
        }}
        placeholder="留下評論,使用 @ 通知成員…"
      />
      <button onClick={submit} disabled={!text.trim()}>
        送出
      </button>
    </div>
  );
}

從團隊資料產生成員清單

hue(0–360)決定頭像漸層與提及籤條的顏色。成員資料沒有顏色欄位時,可以依 id 算出一個固定色相,同一位成員每次都會是同一種顏色。

import { MentionTextarea, type MentionUser } from "@/components/ui/mention-textarea";

function hueFromId(id: string) {
  let h = 0;
  for (const ch of id) h = (h * 31 + ch.charCodeAt(0)) % 360;
  return h;
}

const members = [
  { id: "m_102", name: "林小美", role: "產品設計師" },
  { id: "m_215", name: "陳大文", role: "前端工程師" },
  { id: "m_318", name: "張雅婷", role: "專案經理" },
];

const users: MentionUser[] = members.map((m) => ({
  id: m.id,
  name: m.name,
  title: m.role,
  hue: hueFromId(m.id),
}));

<MentionTextarea users={users} />;

預填內容與調整尺寸

defaultValue 中符合成員名稱的 @名稱 會直接顯示為高亮籤條;rows 調整輸入框行數,maxMenuItems 限制選單一次顯示的人數。

<MentionTextarea
  users={users}
  defaultValue="@張雅婷 這個需求下週一前可以確認嗎?"
  rows={6}
  maxMenuItems={4}
  className="max-w-xl"
/>

Props

Prop型別預設值說明
usersMentionUser[]—可被提及的成員清單({ id, name, hue, title? }),輸入 @ 時據此過濾選單
valuestring—受控模式的文字值,與 onChange 搭配使用
defaultValuestring""非受控模式的初始文字值
onChange(value: string, mentions: MentionUser[]) => void—內容變更回呼,第二參數為目前文中所有被提及的成員
placeholderstring"輸入訊息,使用 @ 提及成員…"輸入框佔位提示文字
rowsnumber4textarea 顯示行數
maxMenuItemsnumber6選單一次最多顯示的成員數
classNamestring—透傳到最外層容器並以 cn() 合併

可及性

  • 輸入框標註 role="combobox"、aria-expanded、aria-autocomplete="list",選單為 role="listbox",項目為 role="option" 並以 aria-activedescendant 指向當前選項
  • 完整鍵盤支援:↑ / ↓ 移動選項、Enter 或 Tab 插入、Escape 關閉選單
  • 選單項目以 onMouseDown 攔截點擊,選取過程中焦點始終留在輸入框內
  • 使用者系統開啟「減少動態效果」時,選單改為純淡入淡出、取消選中底塊的 spring 位移動畫
  • 高亮層為 aria-hidden 的純視覺鏡像,輔助科技仍朗讀 textarea 的原始純文字內容

常見問題

可以在 Next.js App Router 使用嗎?

可以。元件檔案開頭已有 "use client",在 Server Component 頁面直接 import,並把伺服器端取得的成員清單傳給 users 即可(MentionUser 只包含字串與數字)。

用注音或其他中文輸入法打字會誤觸選單嗎?

不會。按鍵處理會先檢查 isComposing,輸入法組字期間按 Enter 只會確認選字,不會插入選單中的成員。

送出後拿到的內容是什麼格式?

value 是純文字,提及以 @名稱 的形式存在文中;onChange 的第二個參數提供對應的 MentionUser 物件陣列。元件依名稱比對提及,所以成員名稱最好不要重複。

名稱有空格的成員可以被搜尋到嗎?

@ 後面的查詢字串遇到空白就會結束,最多 20 個字元,所以只能用空格前的部分搜尋,例如輸入 @Mary 找到「Mary Lin」。選中後仍會插入完整名稱並正確高亮。

有支援鍵盤與螢幕報讀器嗎?

輸入框是 role="combobox",選單為 role="listbox",以 aria-activedescendant 指向目前選項;↑/↓ 移動、Enter 或 Tab 插入、Escape 關閉。系統開啟「減少動態效果」時選單只做淡入淡出。依賴為 motion、clsx 與 tailwind-merge。