Demos
How to import
import { Tag, TagGroup, SplitTagGroup } from '@fibrous/semi-ui-react';
Basic usage
To use this tag, just wrap the content with the <Tag> tag.
It can be turned into a closable label by adding the closable property.
At this time, clicking x to close will trigger the onClose event, and blocking the default event in onClose can make it still show and not hide after clicking
Code
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<div>
<Space>
<Tag>default tag</Tag>
<Tag closable>Closable Tag</Tag>
<Tag closable onClose={(_value, e) => e.preventDefault()}>
Closable Tag, Prevent Default
</Tag>
</Space>
</div>
);
}Size
Supports two sizes: large and small (default).
Code
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<Space>
<Tag size="small" color="light-blue">
small tag
</Tag>
<Tag size="large" color="cyan">
large tag
</Tag>
</Space>
);
}Shape
Supports two Shape: square(default)、circle。
Code
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<Space>
<Tag size="small" shape="circle" color="amber">
small circle tag
</Tag>
<Tag size="large" shape="circle" color="violet">
large circle tag
</Tag>
</Space>
);
}Icon
Use prefixIcon and suffixIcon to add icons before or after the children content.
Code
import { IconGithubLogo, IconSemiLogo } from '@fibrous/semi-icons-react';
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<Space>
<Tag color="light-blue" prefixIcon={<IconGithubLogo />} size="large" shape="circle">
Semi Design
</Tag>
<Tag color="cyan" size="large" shape="circle" suffixIcon={<IconSemiLogo />}>
D2C: figma to code in one click
</Tag>
</Space>
);
}Color
Tag supports 16 colors including whites from Semi's palette: amber, blue, cyan, green, grey, indigo, light-blue, light-green, lime, orange, pink, purple, red, teal, violet, yellow, white. You can also customize color through style.
Code
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<Space wrap>
{(['amber', 'blue', 'cyan', 'green', 'grey', 'indigo', 'light-blue', 'light-green', 'lime', 'orange', 'pink', 'purple', 'red', 'teal', 'violet', 'yellow', 'white'] as const).map((item) => (
<Tag color={item} key={item}>
{item}
</Tag>
))}
</Space>
);
}AI style - colorful labels
Set colorful to true to get colorful labels.
Code
import { IconAIFilledLevel1, IconAIFilledLevel3 } from '@fibrous/semi-icons-react';
import { Tag } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<div style={{ display: 'flex', flexDirection: 'column', rowGap: 30 }}>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gridGap: '10px', width: 'fit-content' }}>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="solid" shape="circle" gradient>
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel3 size="small" />} type="light" shape="circle" gradient>
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel3 size="small" />} type="ghost" shape="circle" gradient>
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="solid" shape="circle">
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="light" shape="circle">
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="ghost" shape="circle">
AI
</Tag>
</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(3,1fr)', gridGap: '10px', width: 'fit-content' }}>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="solid" gradient>
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel3 size="small" />} type="light" gradient>
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel3 size="small" />} type="ghost" gradient>
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="solid">
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="light">
AI
</Tag>
<Tag colorful prefixIcon={<IconAIFilledLevel1 size="small" />} type="ghost">
AI
</Tag>
</div>
</div>
);
}Type
Tag supports three different types, including: light(default), ghost, solid.
Code
import { IconGithubLogo, IconSemiLogo } from '@fibrous/semi-icons-react';
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<Space wrap>
<Tag color="light-blue" prefixIcon={<IconGithubLogo />} size="large" shape="circle" type="light">
Semi Design Light Tag
</Tag>
<Tag color="cyan" size="large" shape="circle" suffixIcon={<IconSemiLogo />} type="light">
D2C: figma to code in one click
</Tag>
<Tag color="light-blue" prefixIcon={<IconGithubLogo />} size="large" shape="circle" type="ghost">
Semi Design Ghost Tag
</Tag>
<Tag color="cyan" size="large" shape="circle" type="ghost" suffixIcon={<IconSemiLogo />}>
D2C: figma to code in one click
</Tag>
<Tag color="light-blue" prefixIcon={<IconGithubLogo />} size="large" shape="circle" type="solid">
Semi Design Solid Tag
</Tag>
<Tag color="cyan" size="large" shape="circle" type="solid" suffixIcon={<IconSemiLogo />}>
D2C: figma to code in one click
</Tag>
</Space>
);
}Avatar Tag
You can get a avatar tag with avatarSrc property. avatarShape can change the shape of avatar tag including square(default) and circle.
Code
import { Tag, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
const src = '/assets/placeholder/avatar-a.svg';
return (
<Space vertical align="start">
<Tag avatarSrc={src}>焦锐志</Tag>
<Tag avatarSrc={src} size="large">
焦锐志
</Tag>
<Tag avatarSrc={src} size="large" closable>
焦锐志
</Tag>
<Tag avatarSrc={src} avatarShape="circle">
焦锐志
</Tag>
<Tag avatarSrc={src} avatarShape="circle" size="large">
焦锐志
</Tag>
<Tag avatarSrc={src} avatarShape="circle" size="large" closable>
焦锐志
</Tag>
</Space>
);
}Invisible
You can use visible property to control whether the tag is visible.
Code
import { useState } from 'react';
import { Tag, RadioGroup, Radio } from '@fibrous/semi-ui-react';
export default function TagDemo() {
const [visible, setVisible] = useState(false);
const toggleVisible = () => {
setVisible(!visible);
};
return (
<div>
<RadioGroup type="button" defaultValue={0} onChange={toggleVisible}>
<Radio value={1}>Show</Radio>
<Radio value={0}>Hide</Radio>
</RadioGroup>
<div style={{ marginTop: 10 }}>
<Tag visible={visible} size="large" color="light-blue">
Invisible tag
</Tag>
</div>
</div>
);
}TagGroup
You can pass in configs for tags through tagList to create a TagGroup. The maxTagCount can be used to cap the number of list and will be displayed as +N when the limit is exceeded.
Set the showPopover property to control whether the remaining content is displayed by Popover when hover to + N Tag
Code
import { TagGroup, type TagProps } from '@fibrous/semi-ui-react';
export default function TagDemo() {
const tagList: TagProps[] = [
{ color: 'light-blue', children: '抖音' },
{ color: 'cyan', children: '火山' },
{ color: 'violet', children: '剪映' },
{ color: 'white', children: '醒图' },
];
const src = '/assets/placeholder/avatar-a.svg';
const tagList2: TagProps[] = [
{ color: 'white', children: 'Douyin', avatarSrc: src },
{ color: 'white', children: 'Hotsoon', avatarSrc: src },
{ color: 'white', children: 'Capcut', avatarSrc: src },
{ color: 'white', children: 'Xingtu', avatarSrc: src },
];
const divStyle = {
backgroundColor: 'var(--semi-color-fill-0)',
height: 35,
width: 300,
display: 'flex',
alignItems: 'center',
padding: '0 10px',
marginBottom: 30,
};
const tagGroupStyle = {
display: 'flex',
alignItems: 'center',
width: 350,
};
return (
<>
<div style={divStyle}>
<TagGroup maxTagCount={3} style={tagGroupStyle} tagList={tagList} size="large" />
</div>
<div style={divStyle}>
<TagGroup maxTagCount={2} style={tagGroupStyle} tagList={tagList2} size="large" avatarShape="circle" showPopover />
</div>
</>
);
}If the tags in the TagGroup can be deleted, the user needs to process the tagList passed to the TagGroup in onTagClose. Provide a tagKey for every item when tags are removed from the list; otherwise removing the earlier of two tags with the same text shifts the later one onto its instance.
Code
import { useState } from 'react';
import { TagGroup, type TagGroupProps, type TagProps } from '@fibrous/semi-ui-react';
export default function TagDemo() {
const defaultList: TagProps[] = [
{ tagKey: '1', color: 'light-blue', children: '抖音', closable: true },
{ tagKey: '3', color: 'cyan', children: '剪映', closable: true },
{ tagKey: '2', color: 'violet', children: '醒图', closable: true },
{ tagKey: '4', color: 'teal', children: '轻颜相机', closable: true },
{ tagKey: '5', color: 'white', children: '飞书', closable: true },
];
const [tagList, setTagList] = useState(defaultList);
const tagListClick: TagGroupProps['onTagClose'] = (_value, _e, tagKey) => {
const newTagList = [...tagList];
const closeTagIndex = newTagList.findIndex((t) => t.tagKey === tagKey);
newTagList.splice(closeTagIndex, 1);
setTagList(newTagList);
};
return (
<div
style={{
backgroundColor: 'var(--semi-color-fill-0)',
height: 35,
width: 300,
display: 'flex',
alignItems: 'center',
padding: '0 10px',
marginBottom: 30,
}}
>
<TagGroup
maxTagCount={3}
showPopover
style={{
display: 'flex',
alignItems: 'center',
width: 350,
}}
tagList={tagList}
size="large"
onTagClose={tagListClick}
/>
</div>
);
}SplitTagGroup
Use SplitTagGroup to combine multiple tags into a single connected group. The first and last tags keep their rounded corners while the middle tags are rendered with a square edge, producing a continuous visual unit.
Code
import { Tag, SplitTagGroup, Space } from '@fibrous/semi-ui-react';
export default function TagDemo() {
return (
<Space vertical align="start">
<SplitTagGroup>
<Tag color="blue" type="solid">
标签一
</Tag>
<Tag color="cyan" type="solid">
标签二
</Tag>
<Tag color="teal" type="solid">
标签三
</Tag>
</SplitTagGroup>
<SplitTagGroup>
<Tag color="violet" shape="circle">
组合
</Tag>
<Tag color="purple" shape="circle">
标签
</Tag>
<Tag color="pink" shape="circle">
示例
</Tag>
<Tag color="red" shape="circle">
效果
</Tag>
</SplitTagGroup>
<SplitTagGroup>
<Tag color="amber" type="light">
浅色
</Tag>
<Tag color="orange" type="light">
组合
</Tag>
<Tag color="yellow" type="light">
标签
</Tag>
</SplitTagGroup>
<SplitTagGroup>
<Tag color="green" type="ghost">
镂空
</Tag>
<Tag color="light-green" type="ghost">
样式
</Tag>
<Tag color="lime" type="ghost">
组合
</Tag>
</SplitTagGroup>
</Space>
);
}API Reference
Tag
Props
| Property | Description | Type | Default |
|---|---|---|---|
| avatarShape | Shape of the avatar in an avatar tag: square or circle. | AvatarShape | "square" |
| avatarSrc | Avatar image URL. Setting it makes an avatar tag. | string | - |
| children | Tag content. Plain text or numbers are truncated with an ellipsis; other nodes are centered. | React.ReactNode | - |
| className | Class name of the root element. | string | "" |
| closable | Whether the tag can be closed. A closable tag can also be closed with the Backspace or Delete key. | boolean | false |
| color | Tag color: one of the 16 palette colors or white. | TagColor | "grey" |
| colorful | Whether the tag is colorful. | boolean | false |
| gradient | Whether a colorful tag uses a gradient. Requires colorful to be true. | boolean | false |
| onClose | Callback when the tag is closed, with the tag content, the event and tagKey. event is the click on the close icon, or the keydown for Backspace or Delete. Call preventDefault on the event to keep the tag visible. | Type(tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, tagKey: string | number) => void | - |
| onMouseEnter | Callback when the pointer enters the tag. | Type() => void | - |
| prefixIcon | Icon before the content. | React.ReactNode | null |
| ref | Reference to the root element. | TypeReact.Ref<HTMLDivElement> | - |
| shape | Tag shape: square or circle. | TagShape | "square" |
| size | Tag size: default, small or large. | TagSize | "default" |
| style | Style of the root element. | React.CSSProperties | {} |
| suffixIcon | Icon after the content. | React.ReactNode | null |
| tabIndex | tabIndex of the root element. TagInput uses it so that arrow keys, not Tab, move focus between tags. | number | - |
| tagKey | Unique identifier of the tag, passed as the third argument of onClose. Must not repeat. | string | number | - |
| type | Style type: light, ghost or solid. | TagType | "light" |
| visible | Whether the tag is visible. When omitted, closing the tag hides it; when given, this value decides. | boolean | - |
aria-label, onClick and other native attributes are spread onto the root element (div). Declaring onClick or closable turns the root element into a focusable button (role="button").
TagGroup
Props
| Property | Description | Type | Default |
|---|---|---|---|
| avatarShape | Avatar shape of the avatar tags in the group: square or circle. | AvatarShape | "square" |
| className | Class name of the root element. | string | "" |
| maxTagCount | Maximum number of visible tags. The rest is shown as +N. | number | - |
| mode | With custom, each tagList item is rendered as given instead of being wrapped in a Tag. | 'custom' | - |
| onPlusNMouseEnter | Callback when the pointer enters the +N tag. | Type() => void | - |
| onTagClose | Callback when a tag in the group is closed, with the tag content, the event and the tagKey of the tag. Update tagList in the callback. | Type(tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, tagKey: string | number) => void | - |
| popoverProps | Props passed to the Popover, such as position and trigger. See Popover. | PopoverProps | - |
| ref | Reference to the root element. | TypeReact.Ref<HTMLDivElement> | - |
| restCount | The number shown in +N. Defaults to the number of tags beyond maxTagCount. | number | - |
| showPopover | Whether hovering +N shows the remaining tags in a Popover. | boolean | - |
| size | Size of the tags in the group: default, small or large. | TagSize | "default" |
| style | Style of the root element. | React.CSSProperties | {} |
| tagList | Tag configurations. Each item holds the props of a Tag, with children as the tag content. With mode set to custom, it is an array of ReactNode. | React.ReactNode[] | TagProps[] | - |
Other native attributes are spread onto the TagGroup root element (div).
SplitTagGroup
Props
| Property | Description | Type | Default |
|---|---|---|---|
| ref | Reference to the root element. | TypeReact.Ref<HTMLDivElement> | - |
className, style, children, aria-label and other native attributes are spread onto the root element (div). The root role is fixed to group.
Accessibility
ARIA
aria-labelis used to indicate the role ofTag, for deletable or clickableTag, we recommend using this attribute
Keyboard and Focus
- If the current
Tagis interactive, then thisTagcan be focused. Such as:- When the
onClickattribute (@clickin Vue) is used, the keyboard user can activate thisTagwith theEnterorSpacekey - When the
closableproperty istrue, keyboard users can delete thisTagby pressing theDeleteorBackspacekey, and focus moves to the adjacent focusableTag
- When the
Content Guidelines
- Due to limited space, label text should be as short as possible
- avoid line breaks
- use sentence case
Design Tokens
| Sass variable | Value | Usage |
|---|---|---|
| $color-tag_avatar-bg-default | var(--semi-color-bg-4) | 头像标签背景颜色 - 默认 |
| $color-tag_avatar-border-default | var(--semi-color-border) | 头像标签描边颜色 - 默认 |
| $color-tag_avatar-text-default | var(--semi-color-text-0) | 头像标签文字颜色 - 默认 |
| $color-tag_white-bg-default | var(--semi-color-bg-4) | 白色标签背景颜色 - 默认 |
| $color-tag_white-border-default | rgb(from var(--semi-grey-2) r g b / 0.7) | 白色标签描边颜色 - 默认 |
| $color-tag_white-text-default | var(--semi-color-text-0) | 白色标签文字颜色 - 默认 |
| $color-tag_white-icon-default | var(--semi-color-text-2) | 白色标签图标颜色 - 默认 |
| $color-tag-outline-focus | $color-focus-ring | 标签轮廓 - 聚焦 |
| $color-tag_colorful_solid-bg | var(--semi-color-ai-purple) | AI Tag深色底色类型背景色 |
| $color-tag_colorful_solid-text | var(--semi-color-white) | AI Tag 深色底色类型字体颜色 |
| $color-tag_colorful_solid_gradient-bg | var(--semi-color-ai-general) | AI Tag深色底色类型渐变背景色 |
| $color-tag_colorful_light-bg | var(--semi-ai-purple-0) | AI Tag 浅色底色类型背景色 |
| $color-tag_colorful_light-text | var(--semi-color-ai-purple) | AI Tag 浅色底色类型字体颜色 |
| $color-tag_colorful_light_gradient-bg | var(--semi-ai-general-0) | AI Tag浅色底色类型背景色-渐变 |
| $color-tag_colorful_light_gradient-text | var(--semi-color-ai-general) | AI Tag浅色底色类型字体色-渐变 |
| $color-tag_colorful_light_gradient-1 | var(--semi-ai-general-5-0) | AI Tag 浅色底色icon渐变色1 |
| $color-tag_colorful_light_gradient-2 | var(--semi-ai-general-5-1) | AI Tag 浅色底色icon渐变色2 |
| $color-tag_colorful_light_gradient-3 | var(--semi-ai-general-5-2) | AI Tag 浅色底色icon渐变色3 |
| $color-tag_colorful_light_gradient-4 | var(--semi-ai-general-5-3) | AI Tag 浅色底色icon渐变色4 |
| $color-tag_colorful_ghost-bg | var(--semi-color-white) | AI Tag 白色底色类型背景色 |
| $color-tag_colorful_ghost-text | var(--semi-color-ai-purple) | AI Tag 白色底色类型字体颜色 |
| $color-tag_colorful_ghost-border | var(--semi-color-ai-general) | AI Tag 白色底色类型描边颜色 |
| $color-tag_colorful_ghost_gradient-text | var(--semi-color-ai-general) | AI Tag 白色底色类型字体色-渐变 |
| $color-tag_colorful_ghost_gradient-1 | var(--semi-ai-general-5-0) | AI Tag 白色底色icon渐变色1 |
| $color-tag_colorful_ghost_gradient-2 | var(--semi-ai-general-5-1) | AI Tag 白色底色icon渐变色2 |
| $color-tag_colorful_ghost_gradient-3 | var(--semi-ai-general-5-2) | AI Tag 白色底色icon渐变色3 |
| $color-tag_colorful_ghost_gradient-4 | var(--semi-ai-general-5-3) | AI Tag 白色底色icon渐变色4 |
| $width-tag_avatar_circle_small | 16px | 头像标签圆角 - 小尺寸 |
| $width-tag_avatar_circle_large | 20px | 头像标签圆角 - 大尺寸 |
| $width-tag-border | 1px | 标签描边宽度 |
| $width-tag_avatar-border | $width-tag-border | 头像标签描边宽度 |
| $width-tag-outline | $width-focus-ring | 标签轮廓宽度 |
| $height-tag_small | 20px | 小尺寸标签高度 |
| $height-tag_large | 24px | 大尺寸标签高度 |
| $radius-tag | var(--semi-border-radius-small) | 标签圆角大小 |
| $radius-tag_circle | var(--semi-border-radius-full) | 胶囊标签圆角大小 |
| $spacing-tag_small-paddingY | 2px | 小尺寸标签垂直方向内边距 |
| $spacing-tag_small-paddingX | $spacing-tight | 小尺寸标签水平方向内边距 |
| $spacing-tag_prefix_icon_paddingRight | $spacing-extra-tight | 后缀图标右侧边距 |
| $spacing-tag_suffix_icon_paddingLeft | $spacing-extra-tight | 后缀图标左侧边距 |
| $spacing-tag_large-paddingY | 4px | 大尺寸标签垂直方向内边距 |
| $spacing-tag_large-paddingX | $spacing-tight | 大尺寸标签水平方向内边距 |
| $color-tag_close-icon-default | var(--semi-color-text-2) | 可删除的标签删除按钮颜色 |
| $color-tag_close-icon-hover | var(--semi-color-text-1) | 可删除的标签删除按钮颜色 - 悬浮 |
| $color-tag_close-icon-active | var(--semi-color-text-0) | 可删除的标签删除按钮颜色 - 按下 |
| $spacing-tag_close-paddingLeft | $spacing-extra-tight | 可删除的标签删除按钮左侧内边距 |
| $spacing-tag_closable-paddingTop | $spacing-extra-tight | 可删除的标签删除按钮顶部内边距 |
| $spacing-tag_closable-paddingRight | $spacing-extra-tight | 可删除的标签删除按钮右侧内边距 |
| $spacing-tag_closable-paddingBottom | $spacing-extra-tight | 可删除的标签删除按钮底部内边距 |
| $spacing-tag_closable-paddingLeft | $spacing-tight | 可删除的标签删除按钮左侧内边距 |
| $spacing-tag_avatar-marginRight | $spacing-extra-tight | 头像标签头像右侧外边距 |
| $spacing-tag_avatar_square-paddingTop | 0 | 方形头像标签头像顶部内边距 |
| $spacing-tag_avatar_square-paddingRight | $spacing-extra-tight | 方形头像标签头像右侧内边距 |
| $spacing-tag_avatar_square-paddingBottom | 0 | 方形头像标签头像底部内边距 |
| $spacing-tag_avatar_square-paddingLeft | 0 | 方形头像标签头像左侧内边距 |
| $spacing-tag_avatar_circle-paddingTop | $spacing-super-tight | 圆型头像标签头像顶部内边距 |
| $spacing-tag_avatar_circle-paddingRight | $spacing-extra-tight | 圆型头像标签头像右侧内边距 |
| $spacing-tag_avatar_circle-paddingBottom | $spacing-super-tight | 圆型头像标签头像底部内边距 |
| $spacing-tag_avatar_circle-paddingLeft | $spacing-super-tight | 圆型头像标签头像左侧内边距 |
| $color-tag_avatar_square_img-bg-default | var(--semi-color-default) | 方形头像标签头像背景色 - 默认 |
| $spacing-tag_group-marginBottom | 0 | 标签组底部外边距 |
| $spacing-tag_group-marginRight | $spacing-tight | 标签组右侧外边距 |
| $font-tag_colorful-fontWeight | $font-weight-bold | AI tag的字重 |