提及輸入框
輸入 @ 觸發人員選單,插入高亮提及籤條的文字區。
輸入 @ 即時開啟可鍵盤操作的成員浮動選單,選中後插入彩色高亮的 @名稱 籤條,並透過 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、程式碼片段同步更新——直接試出你要的樣子再複製。
<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 | 型別 | 預設值 | 說明 |
|---|---|---|---|
users | MentionUser[] | — | 可被提及的成員清單({ id, name, hue, title? }),輸入 @ 時據此過濾選單 |
value | string | — | 受控模式的文字值,與 onChange 搭配使用 |
defaultValue | string | "" | 非受控模式的初始文字值 |
onChange | (value: string, mentions: MentionUser[]) => void | — | 內容變更回呼,第二參數為目前文中所有被提及的成員 |
placeholder | string | "輸入訊息,使用 @ 提及成員…" | 輸入框佔位提示文字 |
rows | number | 4 | textarea 顯示行數 |
maxMenuItems | number | 6 | 選單一次最多顯示的成員數 |
className | string | — | 透傳到最外層容器並以 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。