UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

455 lines (371 loc) 17.6 kB
--- localeCode: en-US order: 49 category: Input title: TagInput subTitle: TagInput icon: doc-tagInput brief: Taginput is a input component that can add content as a tag. --- ## Demos ### How to import ```jsx import import { TagInput } from '@douyinfe/semi-ui'; ``` ### Basic Usage After pressing the Enter key, the input will add value as a tag. If the tag content is an empty string or pure space, it will be filtered. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput defaultValue={['Semi', 'Design', 'Design2Code']} placeholder='Please enter...' onChange={v => console.log(v)} /> ); ``` ### Batch Add You can use `separator` to set the separator to achieve batch input, and its default value is a comma. Multiple separators are supported in string[] format. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <> <TagInput separator='-' placeholder='Use `-` for batch input' onChange={v => console.log(v)} /> <br/><br/> <TagInput separator={['-', '/', '|', '++']} placeholder='Support multiple separators for batch input' onChange={v => console.log(v)} /> </> ); ``` ### Batch Remove You can also use `showClear` to set whether to support one-click deletion of all tags and input. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput showClear defaultValue={['Semi', 'Design2Code']} placeholder='Please enter...' onChange={v => console.log(v)} /> ); ``` ### Disabled ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput disabled showClear defaultValue={['Semi', 'Design2Code']} placeholder='Please enter...' /> ); ``` ### Size Use `size` to set the size of the TagInput, optional: `small`, `default`, `large`. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <> <TagInput size='small' placeholder='small'/> <br/><br/> <TagInput placeholder='default'/> <br/><br/> <TagInput size='large' placeholder='large'/> </> ); ``` ### Different validate status validateStatus: `default`, `warning`, `error`. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <> <TagInput placeholder='default'/> <br/><br/> <TagInput placeholder='warning' validateStatus='warning'/> <br/><br/> <TagInput placeholder='error' validateStatus='error'/> </> ); ``` ### Prefix / Suffix You can pass the input box prefix through `prefix`, the input box suffix through `suffix`, for text or React Node. The left and right padding is automatically brought when the content passed in by prefix and reactix is text or Icon. If it is a custom ReactNode, the left and right padding is 0.If necessary, you can set it in the ReactNode you passed in. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; import { IconVigoLogo, IconGift } from '@douyinfe/semi-icons'; () => ( <> <TagInput prefix={<IconVigoLogo />} showClear/> <br/><br/> <TagInput prefix="Prefix" showClear/> <br/><br/> <TagInput suffix={<IconGift />}/> <br/><br/> <TagInput suffix="Suffix" showClear/> </> ); ``` ### Allow Duplicates You can use `allowDuplicates` to set whether to allow the creation of the same tag. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput allowDuplicates={false} defaultValue={['Semi', 'Design', 'Design2Code']} placeholder='Please enter...' onChange={v => console.log(v)} /> ); ``` ### Autocomplete You can use `addOnBlur` to set whether the current input value is automatically created as a tag when the blur event is triggered. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput addOnBlur={true} defaultValue={['Semi', 'Design', 'Design2Code']} placeholder='Please enter...' onChange={v => console.log(v)} /> ); ``` ### Limits You can use `max` to limit the number of tags. The `onExceed()` callback will be invoked when the limit is exceeded. You can use `maxLength` to limit the maximum length of a single tag, and the `onInputExceed()` callback will be invoked when this value is exceeded. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <> <TagInput max={3} placeholder='max = 3' onChange={v => console.log(v)} onExceed={v => { Toast.warning('Exceeds max'); console.log(v); }} /> <TagInput maxLength={5} placeholder='maxLength = 5' style={{ marginTop: 12 }} onChange={v => console.log(v)} onInputExceed={v => { Toast.warning('Exceeds maxLength'); console.log(v); }} /> </> ); ``` ### Limit the number of tags displayed You can use `maxTagCount` to limit the number of tags displayed, and the excess will be displayed as +N. You can use `showRestTagsPopover` to set whether hover +N displays Popover after `maxTagCount` is exceeded, and you can configure Popover in the `restTagsPopoverProps` property. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput maxTagCount={2} showRestTagsPopover={true} restTagsPopoverProps={{ position: 'top' }} defaultValue={['Semi', 'Design', 'Design2Code']} /> ); ``` ### Controlled Tag You can use `value` to set tags, and use `onChange` to achieve control of the tags. ```jsx live=true import React, { useCallback, useState } from 'react'; import { TagInput } from '@douyinfe/semi-ui'; function TagInputDemo() { const [value, setValue] = useState(['semi']); const handleChange = useCallback(v => setValue(v), []); return <TagInput value={value} onChange={handleChange} />; } ``` ### Controlled Input You can use `inputValue` to set input box, and use `onInputChange` to control the input content. ```jsx live=true import React, { useCallback, useState } from 'react'; import { TagInput } from '@douyinfe/semi-ui'; function TagInputDemo() { const [value, setValue] = useState('semi'); const handleInputChange = useCallback((v, e) => setValue(v), []); return <TagInput inputValue={value} onInputChange={handleInputChange} />; } ``` ### Callback ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput defaultValue={['Semi', 'Design2Code']} showClear onFocus={e =>{console.log(`onFocus`);}} onBlur={e=>{console.log(`onBlur`);}} onChange={tag=>{console.log(`onChange :${tag}`);}} onAdd={tag=>{console.log(`onAdd :${tag}`);}} onRemove={(v, i)=>{console.log(`onRemove :${v}, index:${i}`);}} onInputChange={(input, e)=>{console.log(`onInputChange :${input}`);}} /> ); ``` ### Focus Management You can use the `blur()` and `focus()` methods to manage the focus. ```jsx live=true import React, { useCallback, useRef } from 'react'; import { TagInput, Button } from '@douyinfe/semi-ui'; function TagInputDemo() { const ref = useRef(); const handleTagInputFocus = useCallback(() => { ref.current && ref.current.focus(); }, []); return ( <> <TagInput defaultValue={['Semi', 'Design2Code']} ref={ref} /> <Button style={{ marginTop: 10 }} onClick={handleTagInputFocus}> focus </Button> </> ); } ``` ### Custom TagInput rendering You can use `renderTagItem` to customize tag rendering. `renderTagItem(value: string, index: number, onClose: function ) => React.ReactNode` The third parameter `onClose` is available since version 2.23.0. ```jsx live=true import React, { useCallback, useMemo, useState } from 'react'; import { TagInput, Avatar } from '@douyinfe/semi-ui'; import { IconClose } from '@douyinfe/semi-ui-icons'; function CustomRender() { const [value, setValue] = useState(['xiakeman']); const list = useMemo(() => ([ { "name": "xiakeman", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/avatarDemo.jpeg" }, { "name": "shenyue", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/bf8647bffab13c38772c9ff94bf91a9d.jpg" }, { "name": "quchenyi", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dbf7351bb779433d17c4f50478cf42f7.jpg" }, { "name": "wenjiamao", "avatar": "https://sf6-cdn-tos.douyinstatic.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/7abf810ff060ac3387bd027ead92c4e0.jpg" }, ]), []); const mapList = useMemo(() => new Map(list.map(item => [item.name, item])), [list]); const renderTagItem = useCallback((value, index, onClose) => { const data = mapList.get(value); return ( <div key={index} style={{ display: 'flex', alignItems: 'center', fontSize: 14, marginRight: 10 }} > <Avatar alt='avatar' src={data ? data.avatar : 'https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/dy.png'} size="extra-small" /> <span style={{ marginLeft: 8 }}> {`${value}@semi.com`} </span> <IconClose onClick={onClose} /> </div> ); }, [mapList]); return ( <TagInput value={value} onChange={setValue} renderTagItem={renderTagItem} /> ); } ``` ### Drag to sort Set `draggable` to true to enable drag and drop sorting. Supported since v2.17.0. Adding the same Tag is not allowed under drag and drop sorting, so you need to set `allowDuplicates` to false. After the drag function is enabled, click TagInput, and the Tag can be dragged. Click anywhere outside the TagInput, the Tag cannot be dragged. ```jsx live=true import React from 'react'; import { TagInput } from '@douyinfe/semi-ui'; () => ( <TagInput draggable allowDuplicates={false} defaultValue={['Semi', 'Design', 'Design2Code']} placeholder='please enter...' onChange={v => console.log(v)} /> ); ``` ## API Reference |Properties |Instructions |Type |Default |Version | |--------------|-------------------------------------------------|----------------------------------------------------------------|----------|--------| |addOnBlur |Whether to automatically create the current input value into a tag when the blur event is triggered |boolean | false |-| |allowDuplicates|Allows adding the same tag multiple times |boolean | true |-| |autoFocus |Set whether to automatically focus during initial rendering |boolean | false |-| |className |Class name |string | - |-| |defaultValue |Default tag value |string[] | - |-| |disabled |Read-only, disable interaction |boolean |false |-| |inputValue |Controlled input value |string | - |-| |maxLength |Maximum length of a tag |number | - |-| |max |Maximum number of tags allowed |number | - |-| |maxTagCount |The maximum number of tags to be displayed, if exceeded, they will be displayed in the form of +N |number | - |-| |showRestTagsPopover |When maxTagCount is exceeded and hover reaches +N, whether to display the remaining content through Popover |boolean | true |-| |restTagsPopoverProps |The configuration properties of the popover |PopoverProps | {} |-| |showContentTooltip |When the tag is too long and truncated, when hovering the tag, whether to display all contents through Tooltip.If passed in as object: type,type of component to show tooltip, one of Tooltip, Popover; opts, properties that will be passed directly to the component |boolean\|{type: 'tooltip'\|'popover', opts: object} | true |-| |placeholder |Content to be appear by default |string | - |-| |prefix |Prefix |ReactNode |- |-| | preventScroll | Indicates whether the browser should scroll the document to display the newly focused element, acting on the focus method inside the component, excluding the component passed in by the user | boolean | | | |renderTagItem |Customize the rendering of items, The parameter onClose is available in version 2.23.0 |<ApiType detail='(value: string, index: number, onClose: function) => React.ReactNode'>(params) => React.ReactNode</ApiType> | - |-| |separator |Customize the separator |string\|string[] |, |-| |showClear |Whether to show the clear button |boolean |false |-| |size |Size, one of `small`、`large`、`default` |string |`default` |-| |split |Customize the separator processing function |(value: string, separator: string) => string[] | - |2.90.0| |style |Inline style |React.CSSProperties | - |-| |suffix |Suffix |ReactNode |- |-| |validateStatus|Validate status for styling only, one of `default`、`warning`、`error`|string |`default` |-| |value |Controlled tag value |string[] \| undefined | - |-| |draggable |Set whether to drag and drop |boolean |false |2.17.0| |expandRestTagsOnClick| Without dragging,whether to expand redundant tags after TagInput is clicked |boolean |true |2.17.0| |onAdd |Callback invoked when tags are added |(addedValue: string[]) => void | - |-| |onBlur |Callback invoked when input loses focus |(e:React.MouseEvent) => void | - |-| |onChange |Callback invoked when tags changes |(value:string[]) => void | - |-| |onExceed |Callback invoked when max is exceeded |(value:string[]) => void | - |-| |onFocus |Callback invoked when input gets focus |(e:React.MouseEvent) => void | - |-| |onInputChange |Callback invoked when input changes |(value:string,e: React.KeyboardEvent) => void)| - |-| |onInputExceed |Callback invoked when maxLength is exceeded |(value:string) => void | - |-| |onKeyDown |Callback invoked when keydown |(e: React.KeyboardEvent) => void | - |2.1.0| |onRemove |Callback invoked when tags are removed |(removedValue: string, idx: number) => void | - |-| ## Methods Some internal methods provided by TagInput can be accessed through ref: |Name |Description |Version | |-------|------------|--------| |blur() |Remove focus|-| |focus()|Get focus |-| ## Accessibility ### ARIA - TagInput supports the input of `aria-label` to indicate the function of the TagInput; - TagInput will set `aria-disabled` and `aria-invalid` according to disabled and validateStatus props; - Both the input box and the clear button of TagInput have `aria-label` to indicate the function of the element. ## Design Tokens <DesignToken/> <!-- ## Related Material ```material 192,176 ``` -->