feat(button-group): [button-group] add default empty text (#1155)

* feat(button-group): [button-group] add default empty text

* feat(button-group): [button-group] add default empty text
This commit is contained in:
gimmyhehe 2023-12-17 16:06:27 +08:00 committed by GitHub
parent 85a8d798b2
commit c84ab66471
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 170 additions and 84 deletions

View File

@ -10,6 +10,7 @@ test('按钮组基本示例', async ({ page }) => {
const button3 = demo.getByRole('button', { name: 'Button3' }) const button3 = demo.getByRole('button', { name: 'Button3' })
await button3.click() await button3.click()
await demo.getByRole('button', { name: 'Button2' }).hover()
await expect(buttonGroup.locator('li').nth(2)).toHaveClass('active') await expect(buttonGroup.locator('li').nth(2)).toHaveClass('active')
await expect(button3).toHaveCSS('background-color', 'rgb(94, 124, 224)') await expect(button3).toHaveCSS('background-color', 'rgb(94, 124, 224)')
await expect(button3).toHaveCSS('border-bottom-color', 'rgb(94, 124, 224)') await expect(button3).toHaveCSS('border-bottom-color', 'rgb(94, 124, 224)')

View File

@ -0,0 +1,25 @@
<template>
<div>
<tiny-button-group :data="groupData" v-model="checkedVal"></tiny-button-group>
<tiny-button-group :data="groupData" v-model="checkedVal">
<span class="custom-empty">自定义空数据</span>
</tiny-button-group>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { ButtonGroup as TinyButtonGroup } from '@opentiny/vue'
const checkedVal = ref('')
const groupData = ref([])
</script>
<style scoped>
.custom-empty {
color: #fac20a;
}
.tiny-button-group + .tiny-button-group {
margin-left: 20px;
}
</style>

View File

@ -0,0 +1,11 @@
import { test, expect } from '@playwright/test'
test('空数据插槽', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('button-group#slot-empty')
const demo = page.locator('#slot-empty')
const emptySlot = demo.locator('.tiny-button-group .tiny-button-group--empty')
await expect(emptySlot.first()).toHaveCSS('color', 'rgb(173, 176, 184)')
await expect(demo.locator('.tiny-button-group .custom-empty')).toHaveCSS('color', 'rgb(250, 194, 10)')
})

View File

@ -0,0 +1,33 @@
<template>
<div>
<tiny-button-group :data="groupData" v-model="checkedVal"></tiny-button-group>
<tiny-button-group :data="groupData" v-model="checkedVal">
<span class="custom-empty">自定义空数据</span>
</tiny-button-group>
</div>
</template>
<script>
import { ButtonGroup } from '@opentiny/vue'
export default {
components: {
TinyButtonGroup: ButtonGroup
},
data() {
return {
checkedVal: '',
groupData: []
}
}
}
</script>
<style scoped>
.custom-empty {
color: #fac20a;
}
.tiny-button-group + .tiny-button-group {
margin-left: 20px;
}
</style>

View File

@ -86,6 +86,15 @@ export default {
}, },
'codeFiles': ['slot-default.vue'] 'codeFiles': ['slot-default.vue']
}, },
{
'demoId': 'slot-empty',
'name': { 'zh-CN': '空数据插槽', 'en-US': 'Empty slot' },
'desc': {
'zh-CN': '<p>当数据为空时,默认会显示暂无数据,通过默认插槽自定义内容。</p>',
'en-US': '<p>When the data is empty, customize the content via the <code>empty</code> slot.</p>'
},
'codeFiles': ['slot-empty.vue']
},
{ {
'demoId': 'button-group-multiple', 'demoId': 'button-group-multiple',
'name': { 'zh-CN': '多行按钮组', 'en-US': 'Button Group Multiple' }, 'name': { 'zh-CN': '多行按钮组', 'en-US': 'Button Group Multiple' },

View File

@ -28,6 +28,10 @@
margin-top: var(--ti-button-group-margin-top); margin-top: var(--ti-button-group-margin-top);
.clearfix(); .clearfix();
&--empty {
color: var(--ti-common-color-placeholder);
}
.@{group-item-prefix-cls} { .@{group-item-prefix-cls} {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;

View File

@ -15,93 +15,96 @@
:class="[size ? 'tiny-button-group--' + size : '', border ? '' : 'tiny-button-group--borderless']" :class="[size ? 'tiny-button-group--' + size : '', border ? '' : 'tiny-button-group--borderless']"
> >
<slot> <slot>
<ul v-if="!(showMore && showMore > 0)" class="tiny-group-item"> <template v-if="data.length > 0">
<li v-for="(node, index) in data" :key="index" :class="{ active: state.value === node[valueField] }"> <ul v-if="!(showMore && showMore > 0)" class="tiny-group-item">
<button <li v-for="(node, index) in data" :key="index" :class="{ active: state.value === node[valueField] }">
:class="getItemClass(node)" <button
:style="{ :class="getItemClass(node)"
height: size === 'medium' ? '42px' : size === 'small' ? '32px' : size === 'mini' ? '24px' : '', :style="{
'line-height': size === 'medium' ? '40px' : size === 'small' ? '30px' : size === 'mini' ? '22px' : '' height: size === 'medium' ? '42px' : size === 'small' ? '32px' : size === 'mini' ? '24px' : '',
}" 'line-height': size === 'medium' ? '40px' : size === 'small' ? '30px' : size === 'mini' ? '22px' : ''
type="button" }"
@click="handleClick(node)" type="button"
> @click="handleClick(node)"
{{ node[textField] }} >
</button> {{ node[textField] }}
</button>
<span <span
v-if="node.sup" v-if="node.sup"
:class="[ :class="[
'tiny-group-item__sup', 'tiny-group-item__sup',
{ {
'tiny-group-item__sup-text': !node.sup.slot && !node.sup.icon && node.sup.text, 'tiny-group-item__sup-text': !node.sup.slot && !node.sup.icon && node.sup.text,
'tiny-group-item__sup-icon': !node.sup.slot && node.sup.icon 'tiny-group-item__sup-icon': !node.sup.slot && node.sup.icon
}, },
typeof node.sup.class === 'string' ? node.sup.class : '', typeof node.sup.class === 'string' ? node.sup.class : '',
...(Array.isArray(node.sup.class) ? node.sup.class : []) ...(Array.isArray(node.sup.class) ? node.sup.class : [])
]" ]"
>
<slot v-if="node.sup.slot" :name="node.sup.slot" :sup="node.sup" />
<component v-else-if="node.sup.icon" :is="node.sup.icon"></component>
<span v-else-if="node.sup.text">{{ node.sup.text }}</span>
</span>
</li>
</ul>
<ul v-else class="tiny-group-item show-more">
<li
v-for="(node, index) in state.buttonData"
:key="index"
:class="{ active: state.value === node[valueField] }"
> >
<slot v-if="node.sup.slot" :name="node.sup.slot" :sup="node.sup" /> <tiny-button :class="getItemClass(node)" @click="handleClick(node)">
<component v-else-if="node.sup.icon" :is="node.sup.icon"></component> {{ node[textField] }}
<span v-else-if="node.sup.text">{{ node.sup.text }}</span> </tiny-button>
</span>
</li>
</ul>
<ul v-else class="tiny-group-item show-more">
<li
v-for="(node, index) in state.buttonData"
:key="index"
:class="{ active: state.value === node[valueField] }"
>
<tiny-button :class="getItemClass(node)" @click="handleClick(node)">
{{ node[textField] }}
</tiny-button>
<span <span
v-if="node.sup" v-if="node.sup"
:class="[ :class="[
'tiny-group-item__sup', 'tiny-group-item__sup',
{ {
'tiny-group-item__sup-text': !node.sup.slot && !node.sup.icon && node.sup.text, 'tiny-group-item__sup-text': !node.sup.slot && !node.sup.icon && node.sup.text,
'tiny-group-item__sup-icon': !node.sup.slot && node.sup.icon 'tiny-group-item__sup-icon': !node.sup.slot && node.sup.icon
}, },
typeof node.sup.class === 'string' ? node.sup.class : '', typeof node.sup.class === 'string' ? node.sup.class : '',
...(Array.isArray(node.sup.class) ? node.sup.class : []) ...(Array.isArray(node.sup.class) ? node.sup.class : [])
]" ]"
> >
<slot v-if="node.sup.slot" :name="node.sup.slot" :sup="node.sup" /> <slot v-if="node.sup.slot" :name="node.sup.slot" :sup="node.sup" />
<component v-else-if="node.sup.icon" :is="node.sup.icon"></component> <component v-else-if="node.sup.icon" :is="node.sup.icon"></component>
<span v-else-if="node.sup.text">{{ node.sup.text }}</span> <span v-else-if="node.sup.text">{{ node.sup.text }}</span>
</span> </span>
</li> </li>
<li v-if="data.length > showMore" class="tiny-group-item__more"> <li v-if="data.length > showMore" class="tiny-group-item__more">
<tiny-popover :visible-arrow="false" width="200" popper-class="tiny-group-item__more-popover"> <tiny-popover :visible-arrow="false" width="200" popper-class="tiny-group-item__more-popover">
<template #reference> <template #reference>
<tiny-button class="more-button"> <tiny-button class="more-button">
<icon-popup></icon-popup> <icon-popup></icon-popup>
</tiny-button> </tiny-button>
</template> </template>
<ul class="more-list"> <ul class="more-list">
<li <li
v-for="(moreNode, index) in state.moreData" v-for="(moreNode, index) in state.moreData"
:key="index" :key="index"
:class="{ :class="{
active: state.value === moreNode[valueField], active: state.value === moreNode[valueField],
'more-item': true 'more-item': true
}" }"
@click="moreNodeClick(moreNode)" @click="moreNodeClick(moreNode)"
> >
{{ moreNode[textField] }} {{ moreNode[textField] }}
</li> </li>
</ul> </ul>
</tiny-popover> </tiny-popover>
</li> </li>
<li v-if="showEdit" class="tiny-group-item__edit"> <li v-if="showEdit" class="tiny-group-item__edit">
<tiny-button @click="$emit('edit')" class="edit-button"> <tiny-button @click="$emit('edit')" class="edit-button">
<icon-writing></icon-writing> <icon-writing></icon-writing>
</tiny-button> </tiny-button>
</li> </li>
</ul> </ul>
</template>
<span v-else class="tiny-button-group--empty"> 暂无数据 </span>
</slot> </slot>
</div> </div>
</template> </template>