Skip to content

Commit

Permalink
feat(tag): support title api (#3309)
Browse files Browse the repository at this point in the history
* feat(tag): support title api

* fix: test case

* fix: test case

* chore: fix test

* chore: update snapshot

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
2 people authored and uyarn committed Sep 24, 2024
1 parent 0dd7d07 commit 5b46b83
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 20 deletions.
99 changes: 96 additions & 3 deletions src/tag/__tests__/vitest-tag.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,56 @@ describe('Tag Component', () => {
expect(wrapper2.find('.t-tag__icon-close').exists()).toBeTruthy();
});

it('props.color is equal to #ff0000', () => {
const wrapper = mount({
render() {
return <Tag color={'#ff0000'}></Tag>;
},
});
const domWrapper = wrapper.findComponent(Tag);
expect(domWrapper.element.style.backgroundColor).toBe('rgb(255, 0, 0)');
});
it('props.color expect variant=dark', () => {
const wrapper = mount({
render() {
return <Tag color={'#ff0000'} variant={'dark'} theme={'primary'}></Tag>;
},
});
const domWrapper = wrapper.findComponent(Tag);
expect(domWrapper.element.style.backgroundColor).toBe('rgb(255, 0, 0)');
expect(domWrapper.element.style.color).toBe('white');
});
it('props.color expect variant=light', () => {
const wrapper = mount({
render() {
return <Tag color={'#ff0000'} variant={'light'}></Tag>;
},
});
const domWrapper = wrapper.findComponent(Tag);
expect(domWrapper.element.style.color).toBe('rgb(255, 0, 0)');
expect(domWrapper.element.style.backgroundColor).toBe('rgba(255, 0, 0, 0.1)');
});
it('props.color expect variant=outline', () => {
const wrapper = mount({
render() {
return <Tag color={'#ff0000'} variant={'outline'}></Tag>;
},
});
const domWrapper = wrapper.findComponent(Tag);
expect(domWrapper.element.style.borderColor).toBe('#ff0000');
expect(domWrapper.element.style.color).toBe('rgb(255, 0, 0)');
});
it('props.color expect variant=light-outline', () => {
const wrapper = mount({
render() {
return <Tag color={'#ff0000'} variant={'light-outline'}></Tag>;
},
});
const domWrapper = wrapper.findComponent(Tag);
expect(domWrapper.element.style.borderColor).toBe('#ff0000');
expect(domWrapper.element.style.color).toBe('rgb(255, 0, 0)');
});

it('props.content works fine', () => {
const wrapper = mount({
render() {
Expand Down Expand Up @@ -106,9 +156,19 @@ describe('Tag Component', () => {
return <Tag maxWidth={'150px'} content={'This is a long long long long long tag'}></Tag>;
},
});
const domWrapper1 = wrapper.find('.t-tag--text');
expect(domWrapper1.element.style.maxWidth).toBe('150px');
expect(domWrapper1.attributes('title')).toBe('This is a long long long long long tag');
const domWrapper = wrapper.find('.t-tag--text');
expect(domWrapper.attributes('title')).toBe('This is a long long long long long tag');
expect(domWrapper.element.style.maxWidth).toBe('150px');
});
it('props.maxWidth is equal to 150', () => {
const wrapper = mount({
render() {
return <Tag maxWidth={'150'} content={'This is a long long long long long tag'}></Tag>;
},
});
const domWrapper = wrapper.find('.t-tag--text');
expect(domWrapper.attributes('title')).toBe('This is a long long long long long tag');
expect(domWrapper.element.style.maxWidth).toBe('150px');
});

const shapeClassNameList = [{ 't-tag--square': false }, 't-tag--round', 't-tag--mark'];
Expand Down Expand Up @@ -156,6 +216,39 @@ describe('Tag Component', () => {
});
});

it('props.title is equal to This is a long tag', () => {
const wrapper = mount({
render() {
return (
<Tag title={'This is a long tag'} content={'This is a long long long long long tag'} maxWidth={'150px'}></Tag>
);
},
});
const domWrapper = wrapper.find('.t-tag--text');
expect(domWrapper.element.style.maxWidth).toBe('150px');
expect(domWrapper.attributes('title')).toBe('This is a long tag');
});
it('props.title is equal to ', () => {
const wrapper = mount({
render() {
return <Tag title={''} content={'This is a long long long long long tag'} maxWidth={'150px'}></Tag>;
},
});
const domWrapper = wrapper.find('.t-tag--text');
expect(domWrapper.element.style.maxWidth).toBe('150px');
expect(domWrapper.attributes('title')).toBeUndefined();
});
it('props.title is equal to undefined', () => {
const wrapper = mount({
render() {
return <Tag title={undefined} content={'This is a long long long long long tag'} maxWidth={'150px'}></Tag>;
},
});
const domWrapper = wrapper.find('.t-tag--text');
expect(domWrapper.element.style.maxWidth).toBe('150px');
expect(domWrapper.attributes('title')).toBeUndefined();
});

['dark', 'light', 'outline', 'light-outline'].forEach((item) => {
it(`props.variant is equal to ${item}`, () => {
const wrapper = mount({
Expand Down
10 changes: 9 additions & 1 deletion src/tag/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ export default {
/** 标签是否可关闭 */
closable: Boolean,
/** 自定义标签颜色 */
color: String,
color: {
type: String,
default: '',
},
/** 组件子元素 */
content: {
type: [String, Function] as PropType<TdTagProps['content']>,
Expand Down Expand Up @@ -58,6 +61,11 @@ export default {
return ['default', 'primary', 'warning', 'danger', 'success'].includes(val);
},
},
/** 标签标题,在标签hover时展示,默认为标签内容 */
title: {
type: String,
default: '',
},
/** 标签风格变体 */
variant: {
type: String as PropType<TdTagProps['variant']>,
Expand Down
6 changes: 5 additions & 1 deletion src/tag/tag.en-US.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
:: BASE_DOC ::

## API

### Tag Props

name | type | default | description | required
-- | -- | -- | -- | --
closable | Boolean | false | \- | N
color | String | '' | custom color | N
color | String | - | self-defined tag color | N
content | String / Slot / Function | - | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | Typescript:`string \| TNode`[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
disabled | Boolean | false | \- | N
Expand All @@ -15,6 +16,7 @@ maxWidth | String / Number | - | \- | N
shape | String | square | options: square/round/mark | N
size | String | medium | options: small/medium/large。Typescript:`SizeEnum`[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
theme | String | default | options: default/primary/warning/danger/success | N
title | String | - | title of tag | N
variant | String | dark | options: dark/light/outline/light-outline | N
onClick | Function | | Typescript:`(context: { e: MouseEvent }) => void`<br/> | N
onClose | Function | | Typescript:`(context: { e: MouseEvent }) => void`<br/> | N
Expand All @@ -26,6 +28,7 @@ name | params | description
click | `(context: { e: MouseEvent })` | \-
close | `(context: { e: MouseEvent })` | \-


### CheckTag Props

name | type | default | description | required
Expand All @@ -49,6 +52,7 @@ name | params | description
change | `(checked: boolean, context: CheckTagChangeContext)` | [see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/tag/type.ts)。<br/>`interface CheckTagChangeContext { e: MouseEvent \| KeyboardEvent; value: string \| number }`<br/>
click | `(context: { e: MouseEvent })` | \-


### CheckTagGroup Props

name | type | default | description | required
Expand Down
12 changes: 8 additions & 4 deletions src/tag/tag.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
{{ custom-color }}

## API

### Tag Props

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
closable | Boolean | false | 标签是否可关闭 | N
color | String | '' | 颜色 | N
color | String | - | 自定义标签颜色 | N
content | String / Slot / Function | - | 组件子元素。TS 类型:`string \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
default | String / Slot / Function | - | 组件子元素,同 `content`。TS 类型:`string \| TNode`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
disabled | Boolean | false | 标签禁用态,失效标签不能触发事件。默认风格(theme=default)才有禁用态 | N
Expand All @@ -19,6 +20,7 @@ maxWidth | String / Number | - | 标签最大宽度,宽度超出后会出现
shape | String | square | 标签类型,有三种:方形、圆角方形、标记型。可选项:square/round/mark | N
size | String | medium | 标签尺寸。可选项:small/medium/large。TS 类型:`SizeEnum`[通用类型定义](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
theme | String | default | 组件风格,用于描述组件不同的应用场景。可选项:default/primary/warning/danger/success | N
title | String | - | 标签标题,在标签hover时展示,默认为标签内容 | N
variant | String | dark | 标签风格变体。可选项:dark/light/outline/light-outline | N
onClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>点击时触发 | N
onClose | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>如果关闭按钮存在,点击关闭按钮时触发 | N
Expand All @@ -30,9 +32,10 @@ onClose | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>
click | `(context: { e: MouseEvent })` | 点击时触发
close | `(context: { e: MouseEvent })` | 如果关闭按钮存在,点击关闭按钮时触发


### CheckTag Props

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
checked | Boolean | - | 标签选中的状态,默认风格(theme=default)才有选中态。支持语法糖 `v-model` | N
defaultChecked | Boolean | - | 标签选中的状态,默认风格(theme=default)才有选中态。非受控属性 | N
Expand All @@ -53,9 +56,10 @@ onClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`<br/>
change | `(checked: boolean, context: CheckTagChangeContext)` | 状态切换时触发。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/tag/type.ts)。<br/>`interface CheckTagChangeContext { e: MouseEvent \| KeyboardEvent; value: string \| number }`<br/>
click | `(context: { e: MouseEvent })` | 点击标签时触发


### CheckTagGroup Props

名称 | 类型 | 默认值 | 说明 | 必传
名称 | 类型 | 默认值 | 描述 | 必传
-- | -- | -- | -- | --
checkedProps | Object | - | 透传标签选中态属性。TS 类型:`TdTagProps` | N
multiple | Boolean | false | 是否支持选中多个标签 | N
Expand Down
27 changes: 19 additions & 8 deletions src/tag/tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Vue from 'vue';
import { CloseIcon as TdCloseIcon } from 'tdesign-icons-vue';
import { ScopedSlotReturnValue } from 'vue/types/vnode';
import tinycolor from 'tinycolor2';
import isString from 'lodash/isString';
import props from './props';
import mixins from '../utils/mixins';
import getConfigReceiverMixins, { TagConfig, getGlobalIconMixins } from '../config-provider/config-receiver';
Expand Down Expand Up @@ -98,6 +99,22 @@ export default mixins(getConfigReceiverMixins<Vue, TagConfig>('tag'), getGlobalI
}
return style;
},
renderTitle(tagContent: string) {
if (!this.maxWidth) {
return undefined;
}

const vProps = (this.$vnode.componentOptions.propsData as TdTagProps) || {};
if (Reflect.has(vProps, 'title')) {
return vProps.title || undefined;
}

if (tagContent) {
return tagContent;
}

return undefined;
},
},

render() {
Expand All @@ -106,19 +123,13 @@ export default mixins(getConfigReceiverMixins<Vue, TagConfig>('tag'), getGlobalI
// 标签内容
const tagContent: TNodeReturnValue = renderContent(this, 'default', 'content');

const title = typeof tagContent === 'string' ? tagContent : '';
const titleAttribute = title && this.maxWidth ? { title } : undefined;
const title = this.renderTitle(isString(tagContent) ? tagContent : '');
// 图标
const icon = renderTNodeJSX(this, 'icon');
return (
<div class={this.tagClass} onClick={this.handleClick} style={this.tagStyle}>
{icon}
<span
class={this.maxWidth ? `${this.componentName}--text` : undefined}
style={this.textStyle}
// @ts-ignore
attrs={titleAttribute}
>
<span class={this.maxWidth ? `${this.componentName}--text` : undefined} style={this.textStyle} title={title}>
{tagContent}
</span>
{!this.disabled ? closeIcon : undefined}
Expand Down
8 changes: 7 additions & 1 deletion src/tag/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export interface TdTagProps {
*/
closable?: boolean;
/**
* 自定义颜色
* 自定义标签颜色
* @default ''
*/
color?: string;
/**
Expand Down Expand Up @@ -52,6 +53,11 @@ export interface TdTagProps {
* @default default
*/
theme?: 'default' | 'primary' | 'warning' | 'danger' | 'success';
/**
* 标签标题,在标签hover时展示,默认为标签内容
* @default ''
*/
title?: string;
/**
* 标签风格变体
* @default dark
Expand Down
2 changes: 1 addition & 1 deletion test/snap/__snapshots__/csr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -107193,11 +107193,11 @@ exports[`csr snapshot test > csr test ./src/tag/_example/long-text.vue 1`] = `
<div>
<div
class="t-tag t-tag--default t-tag--dark t-tag--ellipsis"
title="默认超八个字超长文本标签超长省略文本标签"
>
<span
class="t-tag--text"
style="max-width: 150px;"
title="默认超八个字超长文本标签超长省略文本标签"
>
默认超八个字超长文本标签超长省略文本标签
</span>
Expand Down
2 changes: 1 addition & 1 deletion test/snap/__snapshots__/ssr.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ exports[`ssr snapshot test > renders ./src/tag/_example/disabled.vue correctly 1

exports[`ssr snapshot test > renders ./src/tag/_example/icon.vue correctly 1`] = `"<div data-server-rendered=\\"true\\" class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\"><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--default t-tag--dark\\"><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-discount\\"><path fill=\\"currentColor\\" d=\\"M11.5 1.19l10.5.8.81 10.51-10.93 10.93L.56 12.13 11.5 1.18zm.76 2.06l-8.87 8.87 8.49 8.49 8.87-8.87-.61-7.88-7.88-.6zm3.86 4.63a1 1 0 10-1.41 1.41 1 1 0 001.41-1.41zm-2.83-1.42a3 3 0 114.24 4.25 3 3 0 01-4.24-4.25z\\"></path></svg><span>函数图标</span></div></div><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--default t-tag--dark\\"><svg fill=\\"none\\" viewBox=\\"0 0 24 24\\" width=\\"1em\\" height=\\"1em\\" class=\\"t-icon t-icon-discount\\"><path fill=\\"currentColor\\" d=\\"M11.5 1.19l10.5.8.81 10.51-10.93 10.93L.56 12.13 11.5 1.18zm.76 2.06l-8.87 8.87 8.49 8.49 8.87-8.87-.61-7.88-7.88-.6zm3.86 4.63a1 1 0 10-1.41 1.41 1 1 0 001.41-1.41zm-2.83-1.42a3 3 0 114.24 4.25 3 3 0 01-4.24-4.25z\\"></path></svg><span> 插槽图标 </span></div></div></div>"`;

exports[`ssr snapshot test > renders ./src/tag/_example/long-text.vue correctly 1`] = `"<div data-server-rendered=\\"true\\"><div title=\\"默认超八个字超长文本标签超长省略文本标签\\" class=\\"t-tag t-tag--default t-tag--dark t-tag--ellipsis\\"><span class=\\"t-tag--text\\" style=\\"max-width:150px;\\">默认超八个字超长文本标签超长省略文本标签</span></div></div>"`;
exports[`ssr snapshot test > renders ./src/tag/_example/long-text.vue correctly 1`] = `"<div data-server-rendered=\\"true\\"><div class=\\"t-tag t-tag--default t-tag--dark t-tag--ellipsis\\"><span title=\\"默认超八个字超长文本标签超长省略文本标签\\" class=\\"t-tag--text\\" style=\\"max-width:150px;\\">默认超八个字超长文本标签超长省略文本标签</span></div></div>"`;

exports[`ssr snapshot test > renders ./src/tag/_example/plain.vue correctly 1`] = `"<div data-server-rendered=\\"true\\" class=\\"t-space t-space-horizontal\\" style=\\"gap:16px;\\"><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--primary t-tag--outline\\"><span>标签一</span></div></div><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--success t-tag--outline\\"><span>标签二</span></div></div><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--default t-tag--outline\\"><span>标签三</span></div></div><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--warning t-tag--outline\\"><span>标签四</span></div></div><div class=\\"t-space-item\\"><div class=\\"t-tag t-tag--danger t-tag--outline\\"><span>标签五</span></div></div></div>"`;

Expand Down

0 comments on commit 5b46b83

Please sign in to comment.