feat: add Badge component #6573

This commit is contained in:
chenjiahan
2020-10-02 16:46:57 +08:00
parent f75c8231c6
commit 475e60b282
17 changed files with 336 additions and 46 deletions
+78
View File
@@ -0,0 +1,78 @@
# Badge
### Install
```js
import { createApp } from 'vue';
import { Badge } from 'vant';
const app = createApp();
app.use(Badge);
```
## Usage
### Basic Usage
```html
<van-badge :content="5">
<div class="child" />
</van-badge>
<van-badge dot>
<div class="child" />
</van-badge>
<style>
.child {
width: 36px;
height: 36px;
background: #f2f3f5;
border-radius: 4px;
}
</style>
```
### Max
```html
<van-badge :content="20" :max="9">
<div class="child" />
</van-badge>
<van-badge :content="200" :max="99">
<div class="child" />
</van-badge>
```
### Custom Color
```html
<van-badge :content="5" color="#1989fa">
<div class="child" />
</van-badge>
<van-badge dot color="#1989fa">
<div class="child" />
</van-badge>
```
### Standaline
```html
<van-badge :content="200" :max="99" />
```
## API
### Props
| Attribute | Description | Type | Default |
| --- | --- | --- | --- |
| content | Badge content | _string \| number_ | - |
| color | Background color | _string_ | `#ee0a24` |
| dot | Whether to show dot | _boolean_ | `false` |
| max | Max valueshow `{max}+` when exceedonly works when content is number type | _number_ | - |
### Slots
| Name | Description |
| ------- | ------------ |
| default | Default slot |
+91
View File
@@ -0,0 +1,91 @@
# Badge 徽标
### 介绍
在右上角展示徽标数字或小红点。
### 引入
```js
import { createApp } from 'vue';
import { Badge } from 'vant';
const app = createApp();
app.use(Badge);
```
## 代码演示
### 基础用法
设置 `content` 属性后,Badge 会在子元素的右上角显示对应的徽标,也可以通过 `dot` 来显示小红点。
```html
<van-badge :content="5">
<div class="child" />
</van-badge>
<van-badge dot>
<div class="child" />
</van-badge>
<style>
.child {
width: 36px;
height: 36px;
background: #f2f3f5;
border-radius: 4px;
}
</style>
```
### 最大值
设置 `max` 属性后,当 `content` 的数值超过最大值时,会自动显示为 `{max}+`
```html
<van-badge :content="20" :max="9">
<div class="child" />
</van-badge>
<van-badge :content="200" :max="99">
<div class="child" />
</van-badge>
```
### 自定义颜色
通过 `color` 属性来设置徽标的颜色。
```html
<van-badge :content="5" color="#1989fa">
<div class="child" />
</van-badge>
<van-badge dot color="#1989fa">
<div class="child" />
</van-badge>
```
### 独立展示
当 Badge 没有子元素时,会作为一个独立的元素进行展示。
```html
<van-badge :content="200" :max="99" />
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| content | 徽标内容 | _string \| number_ | - |
| color | 徽标背景颜色 | _string_ | `#ee0a24` |
| dot | 是否展示为小红点 | _boolean_ | `false` |
| max | 最大值,超过最大值会显示 `{max}+`,仅当 content 为 number 类型时有效 | _number_ | - |
### Slots
| 名称 | 说明 |
| ------- | ---------------- |
| default | 徽标包裹的子元素 |
| content | 自定义徽标内容 |
+78
View File
@@ -0,0 +1,78 @@
<template>
<demo-section>
<demo-block :title="t('basicUsage')">
<van-badge :content="5">
<div class="child" />
</van-badge>
<van-badge dot>
<div class="child" />
</van-badge>
</demo-block>
<demo-block :title="t('max')">
<van-badge :content="20" :max="9">
<div class="child" />
</van-badge>
<van-badge :content="200" :max="99">
<div class="child" />
</van-badge>
</demo-block>
<demo-block :title="t('customColor')">
<van-badge :content="5" :color="BLUE">
<div class="child" />
</van-badge>
<van-badge dot :color="BLUE">
<div class="child" />
</van-badge>
</demo-block>
<demo-block :title="t('standalone')">
<van-badge :content="200" :max="99" />
</demo-block>
</demo-section>
</template>
<script>
import { BLUE } from '../../utils/constant';
export default {
i18n: {
'zh-CN': {
max: '最大值',
standalone: '独立展示',
customColor: '自定义颜色',
},
'en-US': {
max: 'Max',
standalone: 'Standalone',
customColor: 'Custom Color',
},
},
data() {
return {
BLUE,
};
},
};
</script>
<style lang="less">
@import '../../style/var';
.demo-badge {
background-color: @white;
.van-badge__wrapper {
margin-left: @padding-md;
}
.child {
width: 36px;
height: 36px;
background: @gray-2;
border-radius: 4px;
}
}
</style>
+15 -6
View File
@@ -1,9 +1,7 @@
@import '../style/var';
.van-badge {
position: absolute;
top: 0;
right: 0;
display: inline-block;
box-sizing: border-box;
min-width: @badge-size;
padding: @badge-padding;
@@ -15,9 +13,15 @@
text-align: center;
background-color: @badge-background-color;
border: @badge-border-width solid @white;
border-radius: @badge-size;
transform: translate(50%, -50%);
transform-origin: 100%;
border-radius: @border-radius-max;
&--fixed {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
transform-origin: 100%;
}
&--dot {
width: @badge-dot-size;
@@ -26,4 +30,9 @@
background-color: @badge-dot-color;
border-radius: 100%;
}
&__wrapper {
position: relative;
display: inline-block;
}
}
+51 -7
View File
@@ -1,21 +1,65 @@
import type { PropType } from 'vue';
import { isDef, createNamespace } from '../utils';
const [createComponent, bem] = createNamespace('badge');
export default createComponent({
props: {
max: Number,
dot: Boolean,
badge: [Number, String],
color: String,
content: [Number, String],
tag: {
type: String as PropType<keyof HTMLElementTagNameMap>,
default: 'div',
},
},
setup(props) {
return () => {
const { dot, badge } = props;
const hasBadge = isDef(badge) && badge !== '';
setup(props, { slots }) {
const hasContent = () =>
!!(slots.default || (isDef(props.content) && props.content !== ''));
if (dot || hasBadge) {
return <div class={bem({ dot })}>{dot ? '' : badge}</div>;
const renderContent = () => {
const { dot, max, content } = props;
if (!dot && hasContent()) {
if (slots.content) {
return slots.content();
}
if (isDef(max) && typeof content === 'number' && content > max) {
return `${max}+`;
}
return content;
}
};
const renderBadge = () => {
if (hasContent() || props.dot) {
return (
<div
class={bem({ dot: props.dot, fixed: !!slots.default })}
style={{ background: props.color }}
>
{renderContent()}
</div>
);
}
};
return () => {
if (slots.default) {
const { tag } = props;
return (
<tag class={bem('wrapper')}>
{slots.default()}
{renderBadge()}
</tag>
);
}
return renderBadge();
};
},
});