diff --git a/components/index.tsx b/components/index.tsx
index 6ad621be9f..5723cca7f7 100644
--- a/components/index.tsx
+++ b/components/index.tsx
@@ -48,3 +48,6 @@ export { Timeline }
import Tooltip from './tooltip';
export { Tooltip }
+
+import Mention from './mention';
+export { Mention };
diff --git a/components/mention/demo/async.md b/components/mention/demo/async.md
new file mode 100644
index 0000000000..533be939ee
--- /dev/null
+++ b/components/mention/demo/async.md
@@ -0,0 +1,56 @@
+---
+order: 1
+title: 异步加载
+---
+
+## zh-CN
+
+匹配内容列表为异步返回时。
+
+## en-US
+
+asnyc
+
+````jsx
+
+import { Mention } from 'antd';
+
+const users = ['afc163', 'benjycui', 'yiminghe', 'jljsj33', 'dqaria', 'RaoHai'];
+const AsyncMention = React.createClass({
+ getInitialState() {
+ return {
+ suggestions: [],
+ loading: false,
+ };
+ },
+ fetchSuggestions(value, callback) {
+ setTimeout(() => {
+ callback(users.filter(item => item.indexOf(value) !== -1));
+ }, 500);
+ },
+ onSearchChange(value) {
+ this.fetchSuggestions(value, (suggestions) => {
+ this.setState({
+ suggestions,
+ loading: false,
+ });
+ });
+ this.setState({
+ loading: true,
+ });
+ },
+ render() {
+ const { suggestions, loading } = this.state;
+ return ();
+ },
+});
+
+ReactDOM.render(
+ ,
+ mountNode
+);
+````
diff --git a/components/mention/demo/avatar.md b/components/mention/demo/avatar.md
new file mode 100644
index 0000000000..63160d21fb
--- /dev/null
+++ b/components/mention/demo/avatar.md
@@ -0,0 +1,66 @@
+---
+order: 3
+title: 头像
+---
+
+## zh-CN
+
+自定义建议(含头像)
+
+注意,自定义建议时,onSearchChange 必须不能为空。
+
+## en-US
+
+Customize suggestions
+
+````jsx
+
+import { Mention } from 'antd';
+const Nav = Mention.Nav;
+
+const webFrameworks = [
+ { name: 'React', type: 'JavaScript', icon: 'https://zos.alipayobjects.com/rmsportal/LFIeMPzdLcLnEUe.svg' },
+ { name: 'Angular', type: 'JavaScript', icon: 'https://zos.alipayobjects.com/rmsportal/PJTbxSvzYWjDZnJ.png' },
+ { name: 'Laravel', type: 'PHP', icon: 'http://laravel-china.org/assets/img/laravel-logo.png' },
+ { name: 'Flask', type: 'Python', icon: 'https://zos.alipayobjects.com/rmsportal/xaypBUijfnpAlXE.png' },
+];
+
+const CustomNavMention = React.createClass({
+ getInitialState() {
+ return {
+ suggestions: [],
+ loading: false,
+ };
+ },
+ onSearchChange(value) {
+ const searchValue = value.toLowerCase();
+ const filtered = webFrameworks.filter(item =>
+ item.name.toLowerCase().indexOf(searchValue) !== -1
+ );
+
+ const suggestions = filtered.map(suggestion =>
+ );
+ this.setState({
+ suggestions,
+ });
+ },
+ render() {
+ const { suggestions, loading } = this.state;
+ return ();
+ },
+});
+
+ReactDOM.render(
+ ,
+ mountNode
+);
+````
diff --git a/components/mention/demo/basic.md b/components/mention/demo/basic.md
new file mode 100644
index 0000000000..ae48cec6ea
--- /dev/null
+++ b/components/mention/demo/basic.md
@@ -0,0 +1,30 @@
+---
+order: 0
+title: 基本使用
+---
+
+## zh-CN
+
+基本使用
+
+## en-US
+
+Basic usage.
+
+````jsx
+
+import { Mention } from 'antd';
+
+function onChange(value) {
+ console.log(value);
+}
+
+ReactDOM.render(
+ ,
+ mountNode
+);
+````
diff --git a/components/mention/demo/customTag.md b/components/mention/demo/customTag.md
new file mode 100644
index 0000000000..de9efd0a48
--- /dev/null
+++ b/components/mention/demo/customTag.md
@@ -0,0 +1,64 @@
+---
+order: 2
+title: 自定义建议
+---
+
+## zh-CN
+
+自定义建议
+
+注意,自定义建议时,onSearchChange 必须不能为空。
+
+## en-US
+
+Customize suggestions
+
+````jsx
+
+import { Mention } from 'antd';
+const Nav = Mention.Nav;
+
+const webFrameworks = [
+ { name: 'React', type: 'JavaScript' },
+ { name: 'Angular', type: 'JavaScript' },
+ { name: 'Laravel', type: 'PHP', disabled: true },
+ { name: 'Flask', type: 'Python' },
+ { name: 'Django', type: 'Python' },
+];
+
+const CustomNavMention = React.createClass({
+ getInitialState() {
+ return {
+ suggestions: [],
+ loading: false,
+ };
+ },
+ onSearchChange(value) {
+ const searchValue = value.toLowerCase();
+ const filtered = webFrameworks.filter(item =>
+ item.name.toLowerCase().indexOf(searchValue) !== -1
+ );
+
+ const suggestions = filtered.map(suggestion =>
+ );
+ this.setState({
+ suggestions,
+ });
+ },
+ render() {
+ const { suggestions, loading } = this.state;
+ return ();
+ },
+});
+
+ReactDOM.render(
+ ,
+ mountNode
+);
+````
diff --git a/components/mention/demo/multilines.md b/components/mention/demo/multilines.md
new file mode 100644
index 0000000000..7d82a2262f
--- /dev/null
+++ b/components/mention/demo/multilines.md
@@ -0,0 +1,31 @@
+---
+order: 4
+title: 多行
+---
+
+## zh-CN
+
+多行模式,多行模式必须指定高度。
+
+## en-US
+
+Multi lines mode.
+
+````jsx
+
+import { Mention } from 'antd';
+
+function onChange(value) {
+ console.log(value);
+}
+
+ReactDOM.render(
+ ,
+ mountNode
+);
+````
diff --git a/components/mention/index.en-US.md b/components/mention/index.en-US.md
new file mode 100644
index 0000000000..ddc397806f
--- /dev/null
+++ b/components/mention/index.en-US.md
@@ -0,0 +1,42 @@
+---
+category: Components
+chinese: 提及
+cols: 1
+type: Views
+english: Mention
+---
+
+Mention component。
+
+## When To Use
+
+When need to mention someone or something.
+
+```html
+ ,
+```
+
+## API
+
+### Mention props
+
+| Property | Description | Type | Default |
+|----------|---------------|----------|--------------|
+| suggestions | suggestion content | Array or Array | [] |
+| suggestionStyle | style of suggestion container | Objet | {} |
+| onSearchChange | Callback function called when search content changes | function(value:String) | [] |
+| onChange | Callback function called when content of input changes | function(value:String) | null |
+| notFoundContent| suggestion when suggestions empty | string | '无匹配结果,轻敲空格完成输入' |
+| loading | loading mode | boolean | false |
+| multiLines | multilines mode | boolean | false |
+| defaultValue | default value | string | null |
+
+### Nav props
+
+| Property | Description | Type | Default |
+|----------|---------------|----------|--------------|
+| value | value of suggestion,the value will insert into input filed while selected | string | "" |
+| children | suggestion content | Objet | {} |
diff --git a/components/mention/index.tsx b/components/mention/index.tsx
new file mode 100644
index 0000000000..369f180b92
--- /dev/null
+++ b/components/mention/index.tsx
@@ -0,0 +1,97 @@
+import * as React from 'react';
+import RcMention, { Nav } from 'rc-editor-mention';
+import classnames from 'classnames';
+
+export interface MentionProps {
+ prefixCls: string;
+ suggestionStyle?: Object;
+ suggestions?: Array;
+ onSearchChange?: Function;
+ onChange?: Function;
+ notFoundContent?: any;
+ loading?: Boolean;
+ multiLines?: Boolean;
+}
+
+export interface MentionState {
+ suggestions?: Array;
+ focus?: Boolean;
+}
+
+export default class Mention extends React.Component {
+ static Nav = Nav;
+ static defaultProps = {
+ prefixCls: 'ant-mention',
+ suggestions: [],
+ notFoundContent: '无匹配结果,轻敲空格完成输入',
+ loading: false,
+ multiLines: false,
+ };
+ constructor(props) {
+ super(props);
+ this.state = {
+ suggestions: props.suggestions,
+ focus: false,
+ };
+ }
+
+ componentWillReceiveProps(nextProps) {
+ this.setState({
+ suggestions: nextProps.suggestions,
+ });
+ }
+
+ onSearchChange(value) {
+ console.log('onSearchChange', this.props.onSearchChange);
+ if (this.props.onSearchChange) {
+ return this.props.onSearchChange(value);
+ }
+ return this.defaultSearchChange(value);
+ }
+
+ onChange(editorState, textValue) {
+ if (this.props.onChange) {
+ this.props.onChange(textValue);
+ }
+ }
+
+ defaultSearchChange(value: String): void {
+ const searchValue = value.toLowerCase();
+ const filteredSuggestions = this.props.suggestions.filter(
+ suggestion => suggestion.toLowerCase().indexOf(searchValue) !== -1
+ );
+ this.setState({
+ suggestions: filteredSuggestions,
+ });
+ }
+
+ render() {
+ const { className, prefixCls, style, multiLines, defaultValue} = this.props;
+ let { notFoundContent } = this.props;
+
+ const { suggestions, focus } = this.state;
+ const cls = classnames({
+ [className]: !!className,
+ ['active']: focus,
+ });
+
+ if (this.props.loading) {
+ notFoundContent = ;
+ }
+
+ return this.setState({focus: true})}
+ onBlur={() => this.setState({focus: false})}
+ suggestions={suggestions}
+ notFoundContent={notFoundContent}
+ />;
+ }
+}
diff --git a/components/mention/index.zh-CN.md b/components/mention/index.zh-CN.md
new file mode 100644
index 0000000000..b42d6ac860
--- /dev/null
+++ b/components/mention/index.zh-CN.md
@@ -0,0 +1,43 @@
+---
+category: Components
+chinese: 提及
+cols: 1
+type: Views
+english: Mention
+---
+
+提及组件。(圈人组件)
+
+## 何时使用
+
+用于在输入中提及某人或某事。
+
+```html
+ ,
+```
+
+## API
+
+### Mention props
+
+| 参数 | 说明 | 类型 | 默认值 |
+|----------|---------------|----------|--------------|
+| suggestions | 建议内容 | Array or Array | [] |
+| suggestionStyle | 弹出下拉框样式 | Objet | {} |
+| onSearchChange | 输入框中 @ 变化时回调 | function(value:String) | [] |
+| onChange | 输入框内容变化时回调 | function(value:String) | null |
+| notFoundContent| 未找到时的内容 | string | '无匹配结果,轻敲空格完成输入' |
+| loading | 加载中 | boolean | false |
+| multiLines | 多行模式 | boolean | false |
+| defaultValue | 默认值 | string | null |
+
+
+### Nav props
+
+| 参数 | 说明 | 类型 | 默认值 |
+|----------|---------------|----------|--------------|
+| value | 建议值,选择建议时,用此值插入到输入框中 | string | "" |
+| children | 建议内容 | Objet | {} |
diff --git a/components/mention/style/index.less b/components/mention/style/index.less
new file mode 100644
index 0000000000..7f40f38ac3
--- /dev/null
+++ b/components/mention/style/index.less
@@ -0,0 +1,99 @@
+@import "../../style/themes/default";
+@import "../../style/mixins/index";
+@import '../../input/style/mixin.less';
+
+.ant-mention-wrapper {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ &.active {
+ .ant-mention-editor {
+ .active;
+ }
+ }
+ .ant-mention-editor {
+ .input;
+ padding: 0;
+ }
+ .ant-mention-editor-wrapper {
+ overflow-y: auto;
+ height: auto;
+ }
+ .DraftEditor-editorContainer .public-DraftEditor-content{
+ height: auto;
+ padding: 4px 7px;
+ }
+
+ .ant-mention-dropdown {
+ margin-top: 1.5em;
+ max-height: 250px;
+ min-width: 120px;
+ background-color: white;
+ border: 1px solid @border-color-base;
+ box-shadow: @box-shadow-base;
+ border-radius: @border-radius-base;
+ box-sizing: border-box;
+ z-index: @zindex-dropdown;
+ left: -9999px;
+ top: -9999px;
+ position: absolute;
+ outline: none;
+ overflow-x: hidden;
+ overflow-y: auto;
+ font-size: @font-size-base;
+ &-notfound.ant-mention-dropdown-item {
+ color: #ccc;
+
+ .anticon-loading {
+ color: @primary-color;
+ }
+ }
+ &-item {
+ position: relative;
+ display: block;
+ padding: 7px 15px;
+ font-weight: normal;
+ color: #666;
+ white-space: nowrap;
+ cursor: pointer;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ transition: background 0.3s ease;
+
+ &:hover,
+ &.focus,
+ &-active {
+ background-color: tint(@primary-color, 90%);
+ }
+
+ &-disabled {
+ color: #ccc;
+ cursor: not-allowed;
+
+ &:hover {
+ color: #ccc;
+ background-color: #fff;
+ cursor: not-allowed;
+ }
+ }
+
+ &-selected {
+ &,
+ &:hover {
+ background-color: #f7f7f7;
+ font-weight: bold;
+ color: #666;
+ }
+ }
+
+ &-divider {
+ height: 1px;
+ margin: 1px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+ line-height: 0;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/components/mention/style/index.tsx b/components/mention/style/index.tsx
new file mode 100644
index 0000000000..d74e52ee9f
--- /dev/null
+++ b/components/mention/style/index.tsx
@@ -0,0 +1 @@
+import './index.less';
diff --git a/package.json b/package.json
index 90e69dc9b7..aeb75af105 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,7 @@
"rc-collapse": "~1.6.3",
"rc-dialog": "~6.1.1",
"rc-dropdown": "~1.4.8",
+ "rc-editor-mention": "0.0.27",
"rc-form": "~0.17.1",
"rc-input-number": "~2.5.12",
"rc-menu": "~4.12.4",