Chip
元件用於标记事物的属性、标签或用於分类、筛选。
在 MUI 当中,这样的元件叫做 Chip,而在 Antd 中,这样的元件叫做 Tag,但其实是指一样的元件。
我自己以前会喜欢把这样的元件叫做 Tag,因为最符合直觉,像我们常见的 Hashtag 大概也是长这样。但是开发经验累积一段时间之後,会发现怎麽到处都有东西叫做 Tag?真的很容易撞名,而且这样的元件他也不一定会用在 Tag 上面,可能有些资料叫做 categories 或是 filters ,但他也需要用同样的元件来展示,所以如果叫做 Tag 我自己是觉得容易撞名,有时候也容易混淆,跟别人沟通的时候可能也会不小心产生误会,特别是你的专案里面同时有资料叫做 tags 和 categories 要在同个地方展示,而且你同时又有一个元件叫做 <Tag />
,在跟别人沟通的时候真的非常怕他会听错或是自己讲错,因此我觉得 MUI 把它叫做 Chip 真的是很不错,我自己也蛮喜欢这个名字,因此这边文章统一起见,我先暂时叫这个元件为 Chip。
Chip 元件也是在 MUI 及 Antd 还蛮一致的元件,可以变化的样式和功能都很相似。
外观样式
variant 跟 button 很相似,有 default 跟 outlined 两种选项,default 是整个元件填满的样式。
颜色
颜色的部分 MUI 只提供我们使用 default, primary, secondary,而 Antd 的 color 支援填入色票之外,也支援一些保留字,例如 success, proccessing, error, warning, default。
icon
icon 可以让我们在 Chip 开头的地方放上一些图像,例如头像或是其他 icon 方便我们识别。
closeIcon
在结尾的地方放上的图像,MUI 叫做 deleteIcon ,Andtd 叫做 closeIcon,功能上看起来是大同小异。并且这个 icon 是支援点击事件的,透果 onDelete/onClose 可以 handle 对 icon 的点击动作。
我觉得 MUI 及 Antd 这边有个小细节还不错,就是 Antd 的 closeIcon 对应的事件是 onClose,而 MUI deleteIcon 对应到的事件是 onDelete,不会说 close 和 delete 混着用,如果我们没有注意到的话,我们平常专案内的元件很有可能就会设计出命名不一致的元件。
元件内容
在 MUI 里面叫做 label ,是一个可传入 ReactNode 的 props;Antd 则是让内容可以透过 children element 传进去。
// MUI
<Chip
...otherprops
label="标签内容"
/>
// Antd
<Tag
...otherprops
>
标签内容
</Tag>
之前我们有遇到类似的状况是在 button 的地方,由於 button 是 html 原生的元件,有大家既定认知的使用方式,所以我会比较希望是用 children element 的方式来实作;但 Chip 这边好像两种方式都有人喜欢,毕竟 MUI Chip 也可以让我们在 label 传入 element。
状态属性
由於 Chip 是可点击的元件,有 onDelete/onClose 事件,因此若若有需要它不可被点击的状态,这边也提供 disabled 的 boolean 属性让我们使用。
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
variant | 变化模式 | contained , outlined |
contained |
themeColor | 主题颜色 | primary, secondary, 色票 | primary |
isDisabled | 是否能进行交互 | boolean | false |
label | 内容 | ReactNode , String |
|
icon | 图示 | ReactNode | |
deleteIcon | 删除图示 | ReactNode | |
onDelete | 删除事件 | func |
一个 Chip 的 children 有可能会出现 icon
, label
, deleteIcon
,如下图:
因此我们在规划 html 结构的时候也以这样为主,其实跟我们在设计 Button 的时候蛮像的,其中 ChipWrapper 来决定其 children 的布局,而 icon & deleteIcon 会再根据各别的条件来决定是否显示:
<ChipWrapper>
<Icon />
<Label>
<DeleteIcon>
</ChipWrapper>
变化模式 variant
我们会根据 variant 来决定他是 contained
或是 outlined
的样式,跟先前的 Button 一样,我们用一个 variantMap 的 object 来取得对应的样式,若没有对应到,则预设为 contained:
const containedStyle = css`
background: ${(props) => props.$color};
color: #FFF;
`;
const outlinedStyle = css`
background: #FFF;
color: ${(props) => props.$color};
`;
const variantMap = {
contained: containedStyle,
outlined: outlinedStyle,
};
客制化颜色
颜色的部分我们一样有 primary
, secondray
以及随意传入的色票号码,这边的作法跟 Button 是一样的,附上连结,就不再详细说明。
我们已经有一个 makeColor({ themeColor })
的 function,把 themeColor 传入,就能够将 primary
, secondary
转换成对应的色票号码
https://github.com/TimingJL/13th-ithelp_custom-react-ui-components/blob/main/src/hooks/useColor.jsx
Icon & DeleteIcon
Label 左侧的 icon 是随着有没有传入 icon 这个 props 来决定是否显示,其中我们透过 React.cloneElement
加上一个 className 为 chip__start-icon
来调整他的样式:
<StyledChip
className={className}
$variant={variant}
$color={color}
>
{icon && React.cloneElement(icon, {
className: clsx(icon.props.className, 'chip__start-icon'),
})}
<Label>{label}</Label>
</StyledChip>
Label 右侧的 icon 多数为用来触发 onDelete function,因命名上也使用 deleteIcon
这个名称。
deleteIcon
这个 props 是当我们想要客制化 endIcon 时能够使用,否则,若只有给定 onDelete function 而没有给定 deleteIcon 时,则显示预设的 deleteIcon:
const endIcon = deleteIcon || <CancelIcon />;
<StyledChip
className={className}
$variant={variant}
$color={color}
>
{icon && React.cloneElement(icon, {
className: clsx(icon.props.className, 'chip__start-icon'),
})}
<Label>{label}</Label>
{(deleteIcon || onDelete) && React.cloneElement(endIcon, {
className: clsx(endIcon.props.className, 'chip__end-icon'),
onClick: onDelete,
})}
</StyledChip>
到目前为止,我们就已经完成一个相当接近 MUI 的 Chip 了,实作逻辑上其实并没有特别复杂,跟前面提到几个 数据输入元件
做法都蛮类似的,但主要是样式上会随着不同专案的需要有些调整,若把客制化样式的部分做得好用,我觉得就会是很不错的元件。
Chip 元件原始码:
Source code
Storybook:
Chip
>>: 每个人都该学的30个Python技巧|技巧 23:方便的运算函式—pow()、divmod()、round()(字幕、衬乐、练习)
今天要来谈谈如何查看 Angular 应用程序的版本及更新。 首先,我们要先知道目前本机端的 Ang...
虽然还有一天...有点怀念ESO...收拾一下东西,等会要往车站移动了。 收拾完行李check ou...
经历了一个月的洗礼,又再一次完成了铁人赛。 当然不免俗的,最後来一篇赛後检讨。 这篇分成三个大部分来...
终於结束Text的部分啦~~~ 今天要来讲Treeview,这个就是树状的意思,像树一样有层次感,可...
我认为想要做电商的新手,必须要掌握以下几点: 1. 确定产品和货源 成立电商第一步就是要确认自己所要...