prompt-mentions
v0.0.30
Published
React component library to add an AI prompt with mentions.
Readme
prompt-mentions
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-mentionsyarn add prompt-mentionspnpm add prompt-mentionsQuick 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 themeCustom 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 buildContributing
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
