Mentions

Mention component.

When To Use#

When you need to mention someone or something.

Examples

Basic usage.

expand codeexpand code
import { Mentions } from 'infrad';
import type { OptionProps } from 'infrad/es/mentions';
import React from 'react';

const { Option } = Mentions;

const onChange = (value: string) => {
  console.log('Change:', value);
};

const onSelect = (option: OptionProps) => {
  console.log('select', option);
};

const App: React.FC = () => (
  <Mentions
    style={{ width: '100%' }}
    onChange={onChange}
    onSelect={onSelect}
    defaultValue="@afc163"
  >
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>
);

export default App;
   

Controlled mode, for example, to work with Form.

expand codeexpand code
import { Button, Form, Mentions } from 'infrad';
import React from 'react';

const { Option, getMentions } = Mentions;

const App: React.FC = () => {
  const [form] = Form.useForm();

  const onReset = () => {
    form.resetFields();
  };

  const onFinish = async () => {
    try {
      const values = await form.validateFields();
      console.log('Submit:', values);
    } catch (errInfo) {
      console.log('Error:', errInfo);
    }
  };

  const checkMention = async (_: any, value: string) => {
    const mentions = getMentions(value);

    if (mentions.length < 2) {
      throw new Error('More than one must be selected!');
    }
  };

  return (
    <Form form={form} layout="horizontal" onFinish={onFinish}>
      <Form.Item
        name="coders"
        label="Top coders"
        labelCol={{ span: 6 }}
        wrapperCol={{ span: 16 }}
        rules={[{ validator: checkMention }]}
      >
        <Mentions rows={1}>
          <Option value="afc163">afc163</Option>
          <Option value="zombieJ">zombieJ</Option>
          <Option value="yesmeck">yesmeck</Option>
        </Mentions>
      </Form.Item>
      <Form.Item
        name="bio"
        label="Bio"
        labelCol={{ span: 6 }}
        wrapperCol={{ span: 16 }}
        rules={[{ required: true }]}
      >
        <Mentions rows={3} placeholder="You can use @ to ref user here">
          <Option value="afc163">afc163</Option>
          <Option value="zombieJ">zombieJ</Option>
          <Option value="yesmeck">yesmeck</Option>
        </Mentions>
      </Form.Item>
      <Form.Item wrapperCol={{ span: 14, offset: 6 }}>
        <Button htmlType="submit" type="primary">
          Submit
        </Button>
        &nbsp;&nbsp;&nbsp;
        <Button htmlType="button" onClick={onReset}>
          Reset
        </Button>
      </Form.Item>
    </Form>
  );
};

export default App;

Configurate disabled and readOnly.

expand codeexpand code
import { Mentions } from 'infrad';
import React from 'react';

const { Option } = Mentions;

const getOptions = () =>
  ['afc163', 'zombiej', 'yesmeck'].map(value => (
    <Option key={value} value={value}>
      {value}
    </Option>
  ));

const App: React.FC = () => (
  <>
    <div style={{ marginBottom: 10 }}>
      <Mentions style={{ width: '100%' }} placeholder="this is disabled Mentions" disabled>
        {getOptions()}
      </Mentions>
    </div>
    <Mentions style={{ width: '100%' }} placeholder="this is readOnly Mentions" readOnly>
      {getOptions()}
    </Mentions>
  </>
);

export default App;

Height autoSize.

expand codeexpand code
import { Mentions } from 'infrad';
import React from 'react';

const { Option } = Mentions;

const App: React.FC = () => (
  <Mentions autoSize style={{ width: '100%' }}>
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>
);

export default App;

async

expand codeexpand code
import { Mentions } from 'infrad';
import debounce from 'lodash/debounce';
import React, { useCallback, useRef, useState } from 'react';

const { Option } = Mentions;
const App: React.FC = () => {
  const [loading, setLoading] = useState(false);
  const [users, setUsers] = useState<{ login: string; avatar_url: string }[]>([]);
  const ref = useRef<string>();

  const loadGithubUsers = (key: string) => {
    if (!key) {
      setUsers([]);
      return;
    }

    fetch(`https://api.github.com/search/users?q=${key}`)
      .then(res => res.json())
      .then(({ items = [] }) => {
        if (ref.current !== key) return;

        setLoading(false);
        setUsers(items.slice(0, 10));
      });
  };

  const debounceLoadGithubUsers = useCallback(debounce(loadGithubUsers, 800), []);

  const onSearch = (search: string) => {
    console.log('Search:', search);
    ref.current = search;
    setLoading(!!search);
    setUsers([]);

    debounceLoadGithubUsers(search);
  };

  return (
    <Mentions style={{ width: '100%' }} loading={loading} onSearch={onSearch}>
      {users.map(({ login, avatar_url: avatar }) => (
        <Option key={login} value={login} className="antd-demo-dynamic-option">
          <img src={avatar} alt={login} />
          <span>{login}</span>
        </Option>
      ))}
    </Mentions>
  );
};

export default App;

Customize Trigger Token by prefix props. Default to @, Array<string> also supported.

expand codeexpand code
import { Mentions } from 'infrad';
import React, { useState } from 'react';

const { Option } = Mentions;

const MOCK_DATA = {
  '@': ['afc163', 'zombiej', 'yesmeck'],
  '#': ['1.0', '2.0', '3.0'],
};

type PrefixType = keyof typeof MOCK_DATA;

const App: React.FC = () => {
  const [prefix, setPrefix] = useState<PrefixType>('@');

  const onSearch = (_: string, newPrefix: PrefixType) => {
    setPrefix(newPrefix);
  };

  return (
    <Mentions
      style={{ width: '100%' }}
      placeholder="input @ to mention people, # to mention tag"
      prefix={['@', '#']}
      onSearch={onSearch}
    >
      {(MOCK_DATA[prefix] || []).map(value => (
        <Option key={value} value={value}>
          {value}
        </Option>
      ))}
    </Mentions>
  );
};

export default App;

Change the suggestions placement.

expand codeexpand code
import { Mentions } from 'infrad';
import React from 'react';

const { Option } = Mentions;

const App: React.FC = () => (
  <Mentions style={{ width: '100%' }} placement="top">
    <Option value="afc163">afc163</Option>
    <Option value="zombieJ">zombieJ</Option>
    <Option value="yesmeck">yesmeck</Option>
  </Mentions>
);

export default App;

Add status to Mentions with status, which could be error or warning

expand codeexpand code
import { Mentions, Space } from 'infrad';
import type { OptionProps } from 'infrad/es/mentions';
import React from 'react';

const { Option } = Mentions;

const onChange = (value: string) => {
  console.log('Change:', value);
};

const onSelect = (option: OptionProps) => {
  console.log('select', option);
};

const App: React.FC = () => {
  const options = (
    <>
      <Option value="afc163">afc163</Option>
      <Option value="zombieJ">zombieJ</Option>
      <Option value="yesmeck">yesmeck</Option>
    </>
  );

  return (
    <Space direction="vertical">
      <Mentions onChange={onChange} onSelect={onSelect} defaultValue="@afc163" status="error">
        {options}
      </Mentions>
      <Mentions onChange={onChange} onSelect={onSelect} defaultValue="@afc163" status="warning">
        {options}
      </Mentions>
    </Space>
  );
};

export default App;

API#

<Mentions onChange={onChange}>
  <Mentions.Option value="sample">Sample</Mentions.Option>
</Mentions>

Mention#

PropertyDescriptionTypeDefaultVersion
autoFocusAuto get focus when component mountedbooleanfalse
autoSizeTextarea height autosize feature, can be set to true | false or an object { minRows: 2, maxRows: 6 }boolean | objectfalse
defaultValueDefault valuestring-
filterOptionCustomize filter option logicfalse | (input: string, option: OptionProps) => boolean-
getPopupContainerSet the mount HTML node for suggestions() => HTMLElement-
notFoundContentSet mentions content when not matchReactNodeNot Found
placementSet popup placementtop | bottombottom
prefixSet trigger prefix keywordstring | string[]@
splitSet split string before and after selected mentionstring
statusSet validation status'error' | 'warning' | 'success' | 'validating'-4.19.0
validateSearchCustomize trigger search logic(text: string, props: MentionsProps) => void-
valueSet value of mentionsstring-
onBlurTrigger when mentions lose focus() => void-
onChangeTrigger when value changed(text: string) => void-
onFocusTrigger when mentions get focus() => void-
onResizeThe callback function that is triggered when textarea resizefunction({ width, height })-
onSearchTrigger when prefix hit(text: string, prefix: string) => void-
onSelectTrigger when user select the option(option: OptionProps, prefix: string) => void-

Mention methods#

NameDescription
blur()Remove focus
focus()Get focus

Option#

PropertyDescriptionTypeDefault
childrenSuggestion contentReactNode-
valueThe value of suggestion, the value will insert into input filed while selectedstring-