From 9036ec91f9cef0a57ef2217273b533e32013d480 Mon Sep 17 00:00:00 2001 From: Dylan-duqingyu <63580483+Dylan-duqingyu@users.noreply.github.com> Date: Fri, 13 Aug 2021 16:45:47 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=BE=BD?= =?UTF-8?q?=E6=A0=87=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/badge/__tests__/badge.spec.ts | 50 ++++++++ devui/badge/index.ts | 16 +++ devui/badge/src/badge-types.ts | 41 +++++++ devui/badge/src/badge.scss | 76 ++++++++++++ devui/badge/src/badge.tsx | 65 ++++++++++ sites/components/badge/index.md | 178 ++++++++++++++++++++++++++++ 6 files changed, 426 insertions(+) create mode 100644 devui/badge/__tests__/badge.spec.ts create mode 100644 devui/badge/index.ts create mode 100644 devui/badge/src/badge-types.ts create mode 100644 devui/badge/src/badge.scss create mode 100644 devui/badge/src/badge.tsx create mode 100644 sites/components/badge/index.md diff --git a/devui/badge/__tests__/badge.spec.ts b/devui/badge/__tests__/badge.spec.ts new file mode 100644 index 00000000..90b9643a --- /dev/null +++ b/devui/badge/__tests__/badge.spec.ts @@ -0,0 +1,50 @@ +import { mount } from '@vue/test-utils' +import DBadge from '../src/badge' + +const SLOT = 'This is a slot test' + +describe('badge', () => { + it('badge base', () => { + const wrapper = mount(DBadge, { + props: { count: 80 }, + slots: { default: SLOT } + }) + expect(wrapper.vm.count).toEqual(80) + }) + + it('badge dot', () => { + const wrapper = mount(DBadge, { + props: { showDot: true }, + slots: { default: SLOT } + }) + expect(wrapper.find('.d-badge-content.d-badge-content-dot').exists()).toBe(true) + }) + + it('badge max', () => { + const wrapper = mount(DBadge, { + props: { count: 100 } + }) + expect(wrapper.find('.d-badge-content').text()).toBe('99+') + + const wrapper2 = mount(DBadge, { + props: { count: 100, maxCount: 1000 } + }) + expect(wrapper2.find('.d-badge-content').text()).toBe('100') + }) + + it('badge bgColor', () => { + const wrapper = mount(DBadge, { + props: { bgColor: 'red' }, + slots: { default: SLOT } + }) + expect(wrapper.find('.d-badge-content').attributes().style).toBe('background: red;') + }) + + it('badge offsetXY', () => { + const wrapper = mount(DBadge, { + props: { offsetXY: [-10, 10], badgePos: 'top-right' }, + slots: { default: SLOT } + }) + expect(wrapper.find('.d-badge-content').attributes().style).toBe('top: 10px; right: -10px;') + }) +}) diff --git a/devui/badge/index.ts b/devui/badge/index.ts new file mode 100644 index 00000000..12340737 --- /dev/null +++ b/devui/badge/index.ts @@ -0,0 +1,16 @@ +import type { App } from 'vue' +import Badge from './src/badge' + +Badge.install = function(app: App) { + app.component(Badge.name, Badge) +} + +export { Badge } + +export default { + title: 'Badge 徽标', + category: '数据展示', + install(app: App) { + app.use(Badge as any) + } +} diff --git a/devui/badge/src/badge-types.ts b/devui/badge/src/badge-types.ts new file mode 100644 index 00000000..b0a5ba2f --- /dev/null +++ b/devui/badge/src/badge-types.ts @@ -0,0 +1,41 @@ +import type { PropType, ExtractPropTypes } from 'vue' + +type BadgeStatusType = PropType<'danger' | 'warning' | 'waiting' | 'success' | 'info'> +type BadgePositionType = PropType<'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'> + +const badgeStatusType = ['danger', 'warning', 'waiting', 'success', 'info'] +const badgePositionType = ['top-left', 'top-right', 'bottom-left', 'bottom-right'] + +export const badgeProps = { + count: { + type: [Number, String] + }, + maxCount: { + type: Number, + default: 99 + }, + showDot: { + type: Boolean, + default: false + }, + status: { + type: String as BadgeStatusType, + validator: (val: string) => badgeStatusType.includes(val) + }, + badgePos: { + type: String as BadgePositionType, + default: 'top-right', + validator: (val: string) => badgePositionType.includes(val) + }, + offsetXY: { + type: Array + }, + bgColor: { + type: String + }, + textColor: { + type: String + } +} + +export type BadgeProps = ExtractPropTypes diff --git a/devui/badge/src/badge.scss b/devui/badge/src/badge.scss new file mode 100644 index 00000000..ffadd3cd --- /dev/null +++ b/devui/badge/src/badge.scss @@ -0,0 +1,76 @@ +@import '../../style/theme/color'; +@import '../../style/theme/font'; + +.d-badge { + position: relative; + display: inline-block; + + .d-badge-content { + font-size: $devui-font-size; + color: $devui-light-text; + + &-count { + padding: 0 4px; + min-width: 16px; + height: 16px; + line-height: 16px; + border-radius: 8px; + background: $devui-brand; + text-align: center; + } + + &-danger { + background: $devui-danger; + } + + &-warning { + background: $devui-warning; + } + + &-waiting { + background: $devui-waiting; + } + + &-success { + background: $devui-success; + } + + &-info { + background: $devui-info; + } + + &-top-left { + left: 0; + top: 0; + transform: translate(-50%, -50%); + } + + &-top-right { + right: 0; + top: 0; + transform: translate(50%, -50%); + } + + &-bottom-left { + left: 0; + bottom: 0; + transform: translate(-50%, 50%); + } + + &-bottom-right { + right: 0; + bottom: 0; + transform: translate(50%, 50%); + } + + &-fixed { + position: absolute; + } + + &-dot { + width: 6px; + height: 6px; + border-radius: 50%; + } + } +} diff --git a/devui/badge/src/badge.tsx b/devui/badge/src/badge.tsx new file mode 100644 index 00000000..3c0a5269 --- /dev/null +++ b/devui/badge/src/badge.tsx @@ -0,0 +1,65 @@ +import './badge.scss' + +import { defineComponent, computed } from 'vue' +import { badgeProps, BadgeProps } from './badge-types' + +export default defineComponent({ + name: 'DBadge', + props: badgeProps, + emits: [], + setup(props: BadgeProps, ctx) { + const className = computed(() => { + const base = 'd-badge-content' + return [ + base, + props.showDot ? `${base}-dot` : `${base}-count`, + props.status && `${base}-${props.status}`, + ctx.slots.default && props.badgePos && `${base}-${props.badgePos}`, + ctx.slots.default && `${base}-fixed` + ].join(' ') + }) + + const style = computed(() => { + const styleMap = { + bgColor: 'background', + textColor: 'color' + } + const ret = Object.keys(styleMap).reduce((ret, key) => { + if (props[key]) { + ret[styleMap[key]] = props[key] + } + return ret + }, {}) + // 偏移量 + if (ctx.slots.default && props.offsetXY) { + const [x, y]: Array = props.offsetXY as Array + const [yName, xName] = (props.badgePos as string).split('-') + ret[yName] = y + 'px' + ret[xName] = x + 'px' + } + + return ret + }) + + const text = computed(() => { + if (props.showDot) { + return + } + if (typeof props.count === 'number' && typeof props.maxCount === 'number') { + return props.count > props.maxCount ? `${props.maxCount}+` : props.count + } + return props.count + }) + + return () => { + return ( +
+ {ctx.slots.default?.()} +
+ {text.value} +
+
+ ) + } + } +}) diff --git a/sites/components/badge/index.md b/sites/components/badge/index.md new file mode 100644 index 00000000..129609df --- /dev/null +++ b/sites/components/badge/index.md @@ -0,0 +1,178 @@ +# Badge 徽标 + +图标右上角的圆形徽标数字。 + +### 何时使用 + +出现在图标右上角或列表项右方,通过不同的状态色加数字提示用户有消息需要处理时。 + +### 基本徽章 + +基本徽章类型,当有包裹元素时在右上角显示徽章和数目。 + +未读消息 +未读消息 +未读消息 +未读消息 + +```html +未读消息 +未读消息 +未读消息 +未读消息 +``` + +### 点状徽章 + +点状徽章类型,当有包裹元素且 showDot 参数为 true 时为点状徽章,默认在右上角展示小点不显示数目。 + +未读消息 +未读消息 + + + + + + + +```html +未读消息 +未读消息 + + + + + + +``` + +### 计数徽章 + +当徽章独立使用且不包裹任何元素时,只展示徽章状态色和数目。 + +
    +
  • + 系统消息 + +
  • +
  • + 个人消息 + +
  • +
+ +```html +
    +
  • + 系统消息 + +
  • +
  • + 个人消息 + +
  • +
+``` + +### 状态徽章 + +当徽章独立使用、不包裹任何元素且 showDot 参数为 true 时为状态徽章,不同状态展示不同色点。 + +  danger
+  warning
+  waiting
+  info
+  success
+ +```html +  danger
+  warning
+  waiting
+  info
+  success
+``` + +### 徽章位置 + +通过 badgePos 参数设置徽章位置。 + +未读消息 +未读消息 + + + + + + +```html +未读消息 +未读消息 + + + + + + +``` + +### 自定义 + +通过 bgColor 参数设置徽章展示状态色(此时 status 参数设置的徽章状态色失效),通过 offsetXY 参数可设置相对于 badgePos 的徽章偏移量。通过 textColor、bgColor 自定义文字、背景颜色。 + + + + + + + +未读消息 +未读消息 + + +```html + + + + + + +未读消息 +未读消息 + +``` + +### API + +| 参数 | 类型 | 默认 | 说明 | +| :-------: | :-----------------: | :---------: | :--------------------------------------------------------------------------------------------------------------------------- | +| count | `Number` | -- | 可选,设置基本徽章和计数徽章中显示的数目 | +| maxCount | `Number` | 99 | 可选,设置基本徽章和计数徽章最大可显示数目,当 count > maxCount 时显示 maxCount+ | +| showDot | `Boolean` | false | 可选,true 时为点状徽章(有包裹)或状态徽章(无包裹),false 时为基本徽章(有包裹)或计数徽章(无包裹) | +| status | `BadgeStatusType` | -- | 可选,状态色 danger\| warning \| waiting \| success \| info | +| badgePos | `BadgePositionType` | 'top-right' | 可选,徽标位置 top-left\| top-right \| bottom-left \| bottom-right | +| bgColor | `String` | -- | 可选,自定义徽标色,此时 status 参数设置的徽章状态色失效 | +| textColor | `String` | -- | 可选, 可自定义徽标文字颜色 | +| offsetXY | `[number, number] ` | -- | 可选,可选,有包裹时徽标位置偏移量,格式为[x,y],单位为 px。x 为相对 right 或 left 的偏移量,y 为相对 top 或 bottom 的偏移量 | + + -- Gitee From 8f714197ca6d501c807fbbbeecc6fbe0b3787fb0 Mon Sep 17 00:00:00 2001 From: Dylan-duqingyu <63580483+Dylan-duqingyu@users.noreply.github.com> Date: Sun, 15 Aug 2021 11:51:05 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9class=E5=89=8D?= =?UTF-8?q?=E7=BC=80=E6=A0=BC=E5=BC=8F=E4=B8=BAdevui-=EF=BC=8C=E7=94=A8dev?= =?UTF-8?q?-cli=E5=88=9B=E5=BB=BA=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devui/badge/__tests__/badge.spec.ts | 10 +++---- devui/badge/index.ts | 6 ++--- devui/badge/src/badge.scss | 4 +-- devui/badge/src/badge.tsx | 4 +-- sites/components/badge/index.md | 42 ++++++++++++++--------------- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/devui/badge/__tests__/badge.spec.ts b/devui/badge/__tests__/badge.spec.ts index 90b9643a..f18aa0e2 100644 --- a/devui/badge/__tests__/badge.spec.ts +++ b/devui/badge/__tests__/badge.spec.ts @@ -17,19 +17,19 @@ describe('badge', () => { props: { showDot: true }, slots: { default: SLOT } }) - expect(wrapper.find('.d-badge-content.d-badge-content-dot').exists()).toBe(true) + expect(wrapper.find('.devui-badge-content.devui-badge-content-dot').exists()).toBe(true) }) it('badge max', () => { const wrapper = mount(DBadge, { props: { count: 100 } }) - expect(wrapper.find('.d-badge-content').text()).toBe('99+') + expect(wrapper.find('.devui-badge-content').text()).toBe('99+') const wrapper2 = mount(DBadge, { props: { count: 100, maxCount: 1000 } }) - expect(wrapper2.find('.d-badge-content').text()).toBe('100') + expect(wrapper2.find('.devui-badge-content').text()).toBe('100') }) it('badge bgColor', () => { @@ -37,7 +37,7 @@ describe('badge', () => { props: { bgColor: 'red' }, slots: { default: SLOT } }) - expect(wrapper.find('.d-badge-content').attributes().style).toBe('background: red;') + expect(wrapper.find('.devui-badge-content').attributes().style).toBe('background: red;') }) it('badge offsetXY', () => { @@ -45,6 +45,6 @@ describe('badge', () => { props: { offsetXY: [-10, 10], badgePos: 'top-right' }, slots: { default: SLOT } }) - expect(wrapper.find('.d-badge-content').attributes().style).toBe('top: 10px; right: -10px;') + expect(wrapper.find('.devui-badge-content').attributes().style).toBe('top: 10px; right: -10px;') }) }) diff --git a/devui/badge/index.ts b/devui/badge/index.ts index 12340737..65f1391a 100644 --- a/devui/badge/index.ts +++ b/devui/badge/index.ts @@ -1,7 +1,7 @@ import type { App } from 'vue' import Badge from './src/badge' -Badge.install = function(app: App) { +Badge.install = function (app: App) { app.component(Badge.name, Badge) } @@ -10,7 +10,7 @@ export { Badge } export default { title: 'Badge 徽标', category: '数据展示', - install(app: App) { - app.use(Badge as any) + install(app: App): void { + app.use(Badge as any) } } diff --git a/devui/badge/src/badge.scss b/devui/badge/src/badge.scss index ffadd3cd..9f72576e 100644 --- a/devui/badge/src/badge.scss +++ b/devui/badge/src/badge.scss @@ -1,11 +1,11 @@ @import '../../style/theme/color'; @import '../../style/theme/font'; -.d-badge { +.devui-badge { position: relative; display: inline-block; - .d-badge-content { + .devui-badge-content { font-size: $devui-font-size; color: $devui-light-text; diff --git a/devui/badge/src/badge.tsx b/devui/badge/src/badge.tsx index 3c0a5269..ad6024bd 100644 --- a/devui/badge/src/badge.tsx +++ b/devui/badge/src/badge.tsx @@ -9,7 +9,7 @@ export default defineComponent({ emits: [], setup(props: BadgeProps, ctx) { const className = computed(() => { - const base = 'd-badge-content' + const base = 'devui-badge-content' return [ base, props.showDot ? `${base}-dot` : `${base}-count`, @@ -53,7 +53,7 @@ export default defineComponent({ return () => { return ( -
+
{ctx.slots.default?.()}
{text.value} diff --git a/sites/components/badge/index.md b/sites/components/badge/index.md index 129609df..f903556b 100644 --- a/sites/components/badge/index.md +++ b/sites/components/badge/index.md @@ -10,10 +10,10 @@ 基本徽章类型,当有包裹元素时在右上角显示徽章和数目。 -未读消息 -未读消息 -未读消息 -未读消息 +未读消息 +未读消息 +未读消息 +未读消息 ```html 未读消息 @@ -26,12 +26,12 @@ 点状徽章类型,当有包裹元素且 showDot 参数为 true 时为点状徽章,默认在右上角展示小点不显示数目。 -未读消息 -未读消息 - +未读消息 +未读消息 + - + @@ -50,24 +50,24 @@ 当徽章独立使用且不包裹任何元素时,只展示徽章状态色和数目。 -
    -
  • +
      +
    • 系统消息
    • -
    • +
    • 个人消息
    ```html -
      -
    • +
        +
      • 系统消息
      • -
      • +
      • 个人消息
      • @@ -96,11 +96,11 @@ 通过 badgePos 参数设置徽章位置。 -未读消息 -未读消息 - +未读消息 +未读消息 + - + @@ -156,20 +156,20 @@