A beautiful React component library for building AI prompts with @mentions. Features a sleek mention menu, nested submenus, keyboard navigation, custom theming, and file extension icons.
Features
- π¨ Multiple preset themes β Light, Cursor Dark, GitHub Dark, Minimal
- π― Multiple trigger characters β Use
@,#,/, or any character - π Nested menus β Navigate hierarchical options with Tab/Escape
- β¨οΈ Full keyboard navigation β Arrow keys, Enter, Tab, Escape
- π·οΈ Mention pills β Beautiful styled tags for selected mentions
- πΌοΈ Icons custom and auto β Add icons to menu items, mentions. File extension icons are supported.
- ποΈ Imperative API β Programmatically append mentions via ref
- π± Message component β Render sent messages with formatted mentions
- π¨ Fully CSS customizable β CSS variables and theme objects
Installation
npm install prompt-mentions
Quick Start
import { Prompt } from "prompt-mentions"; import "prompt-mentions/style.css"; const options = [ { id: "alice", label: "Alice Johnson" }, { id: "bob", label: "Bob Smith" }, { id: "main-ts", label: "main.ts" }, ]; function App() { return ( <Prompt placeholder="Type @ to mention..." mentionConfigs={[{ trigger: "@", options }]} onChange={(value, mentions) => { console.log("Value:", value); console.log("Mentions:", mentions); }} /> ); }
Components
<Prompt />
The main input component with mention support.
import { Prompt } from "prompt-mentions";
Props
| Prop | Type | Default | Description |
|---|---|---|---|
initialValue |
string |
"" |
Initial text content with optional mentions in @[id] format |
placeholder |
string |
"" |
Placeholder text when input is empty |
mentionConfigs |
MentionConfig[] |
[{ trigger: '@', options: [] }] |
Array of mention trigger configurations |
theme |
PresetThemeName | PromptTheme |
β | Theme preset name or custom theme object |
className |
string |
"" |
Additional CSS class name |
style |
CSSProperties |
β | Inline styles |
extensionIcons |
boolean |
false |
Auto-add file icons based on extension |
onChange |
(value: string, mentions: SelectedMention[]) => void |
β | Called on every text change |
onEnter |
(value: string, mentions: SelectedMention[]) => void |
β | Called when Enter is pressed |
onMentionAdded |
(mention: SelectedMention) => void |
β | Called when a mention is selected |
onMentionDeleted |
(mention: SelectedMention) => void |
β | Called when a mention is removed |
onMentionClick |
(mention: SelectedMention) => void |
β | Called when a mention pill is clicked |
MentionConfig
interface MentionConfig { trigger: string; // Character that triggers the menu (e.g., '@', '#', '/') options: MentionOption[]; // Array of mention options menuPosition?: "above" | "below"; // Menu position relative to cursor showTrigger?: boolean; // Show trigger character in pill (default: false) }
MentionOption
interface MentionOption { id: string; // Unique identifier label: string; // Display text icon?: ReactNode; // Optional icon component type?: "item" | "divider" | "title"; // Item type children?: MentionOption[]; // Nested submenu items labelRight?: string; // Secondary label (e.g., file path) indent?: number; // Visual indent level }
<Message />
Display sent messages with formatted mention pills.
import { Message } from "prompt-mentions"; <Message value="Hello @[alice]! Please review @[main-ts]" mentionConfigs={[{ trigger: "@", options }]} onMentionClick={(mention) => console.log("Clicked:", mention)} />;
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value |
string |
β | Message text with mentions in trigger[id] format |
mentionConfigs |
MessageMentionConfig[] |
[{ trigger: '@' }] |
Mention configurations for label/icon lookup |
theme |
PresetThemeName | PromptTheme |
β | Theme preset or custom theme |
className |
string |
"" |
Additional CSS class name |
style |
CSSProperties |
β | Inline styles |
extensionIcons |
boolean |
false |
Auto-add file icons based on extension |
onMentionClick |
(mention) => void |
β | Called when a mention pill is clicked |
Theming
Preset Themes
<Prompt theme="light" /> // Default light theme <Prompt theme="cursorDark" /> // Cursor IDE dark theme <Prompt theme="githubDark" /> // GitHub dark theme <Prompt theme="minimal" /> // Clean minimal theme
Custom Theme
Pass a PromptTheme object for full control:
const customTheme: PromptTheme = { backgroundColor: "#1a1625", color: "#e0d4f7", placeholderColor: "#6b5b8c", fontSize: "14px", borderRadius: "12px", borderColor: "#2d2640", focusBorderColor: "#9c6ade", menu: { backgroundColor: "#1a1625", borderColor: "#2d2640", color: "#c4b5dc", itemHoverColor: "#2d2640", }, pill: { backgroundColor: "linear-gradient(135deg, #7c3aed, #c026d3)", borderRadius: "8px", color: "white", }, }; <Prompt theme={customTheme} />;
Partial Overrides
Override only specific properties:
<Prompt theme={{ focusBorderColor: "#f43f5e", pill: { backgroundColor: "#16a34a", }, }} />
CSS Variables
All styling is controlled via CSS variables. Override them in your CSS:
.prompt-container { --prompt-background-color: white; --prompt-color: black; --prompt-placeholder-color: #9ca3af; --prompt-border-radius: 0.375rem; --prompt-border-color: #d1d5db; --prompt-focus-border-color: #6366f1; --prompt-mention-pill-background-color: linear-gradient( 135deg, #6366f1, #8b5cf6 ); --prompt-mention-pill-color: white; --prompt-mention-pill-border-radius: 9999px; --prompt-mention-menu-background-color: white; --prompt-mention-menu-border-color: #e5e7eb; --prompt-mention-menu-item-hover-color: #f3f4f6; }
Advanced Usage
Multiple Triggers
Configure different triggers for different types of mentions:
<Prompt placeholder="Type @, #, or / ..." mentionConfigs={[ { trigger: "@", options: peopleOptions }, { trigger: "#", options: tagOptions }, { trigger: "/", options: commandOptions, menuPosition: "above" }, ]} />
Nested Menus
Create hierarchical option structures:
const options = [ { id: "team", label: "Team Members", icon: <UsersIcon />, children: [ { id: "alice", label: "Alice Johnson" }, { id: "bob", label: "Bob Smith" }, ], }, { id: "projects", label: "Projects", icon: <FolderIcon />, children: [ { id: "alpha", label: "Project Alpha" }, { id: "beta", label: "Project Beta" }, ], }, ];
Navigate with:
- Tab or β β Enter submenu
- Escape or β β Exit submenu
Icons and Labels
Add icons and secondary labels to options:
const fileOptions = [ { id: "prompt-tsx", label: "Prompt.tsx", labelRight: "src/components/", icon: <TypeScriptIcon />, indent: 1, }, ];
Auto File Extension Icons
Automatically add file type icons based on file extensions:
<Prompt extensionIcons={true} mentionConfigs={[{ trigger: "@", options: fileOptions }]} />
Supports: .ts, .tsx, .js, .jsx, .css, .html, .json, .md, .py, .go, .rs, .sql, and many more.
Dividers and Titles
Organize options with visual separators:
const options = [ { id: "title-people", label: "People", type: "title" }, { id: "alice", label: "Alice" }, { id: "bob", label: "Bob" }, { id: "divider-1", label: "", type: "divider" }, { id: "title-files", label: "Files", type: "title" }, { id: "readme", label: "README.md" }, ];
Programmatic Control (Ref)
Use the imperative handle to control the prompt externally:
import { useRef } from "react"; import { Prompt, PromptHandle, MentionOption } from "prompt-mentions"; function MyComponent() { const promptRef = useRef<PromptHandle>(null); const handleAddMention = (option: MentionOption) => { // Append mention with default trigger (@) promptRef.current?.appendMention(option); // Or with a specific trigger promptRef.current?.appendMention(option, "#"); // Focus the input promptRef.current?.focus(); }; const handleInsertText = () => { // Insert text at current cursor position (or at end if not focused) // Behaves like typing - triggers mention menu when a trigger character is inserted promptRef.current?.insertText("Hello "); // Insert a trigger to open the mention menu promptRef.current?.insertText("@"); }; return ( <> <Prompt ref={promptRef} mentionConfigs={[ { trigger: "@", options: userOptions }, { trigger: "#", options: tagOptions }, ]} /> <button onClick={() => handleAddMention({ id: "alice", label: "Alice" })}> Add @Alice </button> <button onClick={handleInsertText}>Insert Text</button> </> ); }
PromptHandle Methods
| Method | Signature | Description |
|---|---|---|
appendMention |
(option: MentionOption, trigger?: string) => void |
Appends a mention pill to the end of the input |
focus |
() => void |
Focuses the prompt input |
insertText |
(text: string) => void |
Inserts text at cursor position. Behaves like typingβtriggers mention menu when a trigger character is inserted |
Initial Value with Mentions
Pre-populate the input with existing mentions:
<Prompt initialValue="Hello @[alice]! Please check @[main-ts]" mentionConfigs={[{ trigger: "@", options }]} />
The format is trigger[id] where id matches an option's id field.
Exports
// Components export { Prompt, Message } from "prompt-mentions"; // Types export type { MentionOption, MentionItemType, SelectedMention, PromptTheme, PresetThemeName, } from "prompt-mentions"; // Theme utilities export { themeToStyles, presetThemes, defaultTheme } from "prompt-mentions"; // Extension icon utilities export { getExtensionIcon, extensionIconMap, filenameIconMap, DefaultFileIcon, DefaultFolderIcon, } from "prompt-mentions";
Keyboard Shortcuts
| Key | Action |
|---|---|
β / β |
Navigate menu options |
Enter |
Select highlighted option |
Tab / β |
Enter submenu (if available) |
Escape / β |
Exit submenu or close menu |
Backspace |
Delete mention (when cursor is adjacent) |
Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Development
# Install dependencies npm install # Run Storybook for development npm run storybook # Run tests npm run test # Build the library npm run build
Contributing
Contributions are welcome! Please read our contributing guidelines and submit pull requests to the main repository.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
MIT Β© (https://github.com/getnao/prompt-mentions/blob/main/LICENSE)
Made with β€οΈ by nao Labs