diff --git a/src/tag/__tests__/vitest-tag.test.jsx b/src/tag/__tests__/vitest-tag.test.jsx index 3d5c7a5c6..13b56f9c7 100644 --- a/src/tag/__tests__/vitest-tag.test.jsx +++ b/src/tag/__tests__/vitest-tag.test.jsx @@ -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 ; + }, + }); + 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 ; + }, + }); + 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 ; + }, + }); + 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 ; + }, + }); + 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 ; + }, + }); + 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() { @@ -106,9 +156,19 @@ describe('Tag Component', () => { return ; }, }); - 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 ; + }, + }); + 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']; @@ -156,6 +216,39 @@ describe('Tag Component', () => { }); }); + it('props.title is equal to This is a long tag', () => { + const wrapper = mount({ + render() { + return ( + + ); + }, + }); + 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 ; + }, + }); + 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 ; + }, + }); + 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({ diff --git a/src/tag/props.ts b/src/tag/props.ts index 68922af95..56508b65b 100644 --- a/src/tag/props.ts +++ b/src/tag/props.ts @@ -11,7 +11,10 @@ export default { /** 标签是否可关闭 */ closable: Boolean, /** 自定义标签颜色 */ - color: String, + color: { + type: String, + default: '', + }, /** 组件子元素 */ content: { type: [String, Function] as PropType, @@ -58,6 +61,11 @@ export default { return ['default', 'primary', 'warning', 'danger', 'success'].includes(val); }, }, + /** 标签标题,在标签hover时展示,默认为标签内容 */ + title: { + type: String, + default: '', + }, /** 标签风格变体 */ variant: { type: String as PropType, diff --git a/src/tag/tag.en-US.md b/src/tag/tag.en-US.md index fdeded2c8..f7aed69bc 100644 --- a/src/tag/tag.en-US.md +++ b/src/tag/tag.en-US.md @@ -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 @@ -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`
| N onClose | Function | | Typescript:`(context: { e: MouseEvent }) => void`
| N @@ -26,6 +28,7 @@ name | params | description click | `(context: { e: MouseEvent })` | \- close | `(context: { e: MouseEvent })` | \- + ### CheckTag Props name | type | default | description | required @@ -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)。
`interface CheckTagChangeContext { e: MouseEvent \| KeyboardEvent; value: string \| number }`
click | `(context: { e: MouseEvent })` | \- + ### CheckTagGroup Props name | type | default | description | required diff --git a/src/tag/tag.md b/src/tag/tag.md index f16c47e9c..6f3fa7b31 100644 --- a/src/tag/tag.md +++ b/src/tag/tag.md @@ -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 @@ -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`
点击时触发 | N onClose | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
如果关闭按钮存在,点击关闭按钮时触发 | N @@ -30,9 +32,10 @@ onClose | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
click | `(context: { e: MouseEvent })` | 点击时触发 close | `(context: { e: MouseEvent })` | 如果关闭按钮存在,点击关闭按钮时触发 + ### CheckTag Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- checked | Boolean | - | 标签选中的状态,默认风格(theme=default)才有选中态。支持语法糖 `v-model` | N defaultChecked | Boolean | - | 标签选中的状态,默认风格(theme=default)才有选中态。非受控属性 | N @@ -53,9 +56,10 @@ onClick | Function | | TS 类型:`(context: { e: MouseEvent }) => void`
change | `(checked: boolean, context: CheckTagChangeContext)` | 状态切换时触发。[详细类型定义](https://github.com/Tencent/tdesign-vue/tree/develop/src/tag/type.ts)。
`interface CheckTagChangeContext { e: MouseEvent \| KeyboardEvent; value: string \| number }`
click | `(context: { e: MouseEvent })` | 点击标签时触发 + ### CheckTagGroup Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- checkedProps | Object | - | 透传标签选中态属性。TS 类型:`TdTagProps` | N multiple | Boolean | false | 是否支持选中多个标签 | N diff --git a/src/tag/tag.tsx b/src/tag/tag.tsx index 63bb983be..9d2a3a5c8 100644 --- a/src/tag/tag.tsx +++ b/src/tag/tag.tsx @@ -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'; @@ -98,6 +99,22 @@ export default mixins(getConfigReceiverMixins('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() { @@ -106,18 +123,13 @@ export default mixins(getConfigReceiverMixins('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 (
{icon} - + {tagContent} {!this.disabled ? closeIcon : undefined} diff --git a/src/tag/type.ts b/src/tag/type.ts index fd2fe32bb..f0b0481e7 100644 --- a/src/tag/type.ts +++ b/src/tag/type.ts @@ -13,7 +13,8 @@ export interface TdTagProps { */ closable?: boolean; /** - * 自定义颜色 + * 自定义标签颜色 + * @default '' */ color?: string; /** @@ -52,6 +53,11 @@ export interface TdTagProps { * @default default */ theme?: 'default' | 'primary' | 'warning' | 'danger' | 'success'; + /** + * 标签标题,在标签hover时展示,默认为标签内容 + * @default '' + */ + title?: string; /** * 标签风格变体 * @default dark diff --git a/test/snap/__snapshots__/csr.test.js.snap b/test/snap/__snapshots__/csr.test.js.snap index 39e0621d9..b35c8618e 100644 --- a/test/snap/__snapshots__/csr.test.js.snap +++ b/test/snap/__snapshots__/csr.test.js.snap @@ -107195,11 +107195,11 @@ exports[`csr snapshot test > csr test ./src/tag/_example/long-text.vue 1`] = `
默认超八个字超长文本标签超长省略文本标签 diff --git a/test/snap/__snapshots__/ssr.test.js.snap b/test/snap/__snapshots__/ssr.test.js.snap index 502701b4e..c6ba054c7 100644 --- a/test/snap/__snapshots__/ssr.test.js.snap +++ b/test/snap/__snapshots__/ssr.test.js.snap @@ -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`] = `"
函数图标
插槽图标
"`; -exports[`ssr snapshot test > renders ./src/tag/_example/long-text.vue correctly 1`] = `"
默认超八个字超长文本标签超长省略文本标签
"`; +exports[`ssr snapshot test > renders ./src/tag/_example/long-text.vue correctly 1`] = `"
默认超八个字超长文本标签超长省略文本标签
"`; exports[`ssr snapshot test > renders ./src/tag/_example/plain.vue correctly 1`] = `"
标签一
标签二
标签三
标签四
标签五
"`;