feat(tabs): [tabs] Add panel configuration function to adapt to the new SMB specifications (#1547)

This commit is contained in:
chenxi-20 2024-04-18 18:28:09 -07:00 committed by GitHub
parent e7ab21759b
commit 147de7fdde
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 235 additions and 104 deletions

View File

@ -7,7 +7,7 @@ export default {
props: [
{
name: 'active-color',
type: 'String',
type: 'string',
defaultValue: '',
desc: {
'zh-CN': '当前页签的字体颜色',
@ -237,7 +237,7 @@ export default {
},
{
name: 'v-model',
type: 'String',
type: 'string',
defaultValue: '',
desc: {
'zh-CN': '绑定值,选中选项卡的 name',
@ -248,7 +248,7 @@ export default {
},
{
name: 'v-model / modelValue',
type: 'String',
type: 'string',
defaultValue: '',
desc: {
'zh-CN': '选中选项卡的 name',
@ -284,8 +284,8 @@ export default {
mfDemo: ''
},
{
name: 'beforeClose',
type: 'Function',
name: 'before-close',
type: '(name: string)=> boolean | Promise<boolean>',
defaultValue: '',
desc: {
'zh-CN': '关闭页签前的回调函数入参为页签名。如果函数返回false 或 拒绝的Promise则不关闭页签',
@ -296,6 +296,18 @@ export default {
pcDemo: 'tabs-events-close',
mfDemo: ''
},
{
name: 'more-show-all',
type: 'boolean',
defaultValue: 'false',
desc: {
'zh-CN': `'更多'按钮触发的下拉面板是否展示全部页签项,适用于超大数据量的情况`,
'en-US':
'Indicates whether to display all tab items in the drop-down panel triggered by the More button. This parameter applies to the scenario where the data volume is large.'
},
mode: ['pc'],
pcDemo: 'more-show-all'
},
{
name: 'overflow-title',
type: 'boolean',
@ -309,9 +321,32 @@ export default {
pcDemo: 'overflow-title',
mfDemo: ''
},
{
name: 'panel-max-height',
type: 'string',
defaultValue: '',
desc: {
'zh-CN': `'更多'按钮触发的下拉面板最大高度,超出则显示滚动条,适用于超大数据量的情况`,
'en-US':
'Maximum height of the drop-down panel triggered by the More button. If the height is exceeded, a scroll bar is displayed. This applies to the scenario where the data volume is large'
},
mode: ['pc'],
pcDemo: 'more-show-all'
},
{
name: 'panel-width',
type: 'string',
defaultValue: '',
desc: {
'zh-CN': `'更多'按钮触发的下拉面板的宽度`,
'en-US': 'Width of the drop-down panel triggered by the More button'
},
mode: ['pc'],
pcDemo: 'more-show-all'
},
{
name: 'title-width',
type: 'String',
type: 'string',
defaultValue: '256px',
desc: {
'zh-CN': '当 overflow-title 为 true 时,指定页签标题的最大宽度',

View File

@ -10,52 +10,20 @@
</template>
<script setup lang="jsx">
import { ref } from 'vue'
import { reactive } from 'vue'
import { Tabs as TinyTabs, TabItem as TinyTabItem } from '@opentiny/vue'
import { iconPopup } from '@opentiny/vue-icon'
const Tabs = ref([
{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content '
},
{
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
},
{
title: 'Tab 3',
name: '3',
content: 'Tab 3 content'
},
{
title: 'Tab 4',
name: '4',
content: 'Tab 4 content'
},
{
title: 'Tab 5',
name: '5',
content: 'Tab 5 content'
},
{
title: 'Tab 6',
name: '6',
content: 'Tab 6 content'
},
{
title: 'Tab 7',
name: '7',
content: 'Tab 7 content'
},
{
title: 'Tab 8',
name: '8',
content: 'Tab 8 content'
}
])
const Tabs = reactive([])
const TinyIconPopup = iconPopup()
// tabs
for (let i = 1; i < 9; i++) {
const title = `Tab ${i}`
Tabs.push({
title,
name: i + '',
content: `${title} content `
})
}
</script>

View File

@ -1,7 +1,7 @@
<template>
<tiny-tabs style="width: 400px" show-more-tabs popper-class="custom-class">
<template #moreIcon>
<icon-popup />
<tiny-icon-popup />
</template>
<tiny-tab-item :key="item.name" v-for="item in Tabs" :title="item.title" :name="item.name">
{{ item.content }}
@ -17,52 +17,22 @@ export default {
components: {
TinyTabs: Tabs,
TinyTabItem: TabItem,
IconPopup: iconPopup()
TinyIconPopup: iconPopup()
},
data() {
return {
Tabs: [
{
title: 'Tab 1',
name: '1',
content: 'Tab 1 content '
},
{
title: 'Tab 2',
name: '2',
content: 'Tab 2 content'
},
{
title: 'Tab 3',
name: '3',
content: 'Tab 3 content'
},
{
title: 'Tab 4',
name: '4',
content: 'Tab 4 content'
},
{
title: 'Tab 5',
name: '5',
content: 'Tab 5 content'
},
{
title: 'Tab 6',
name: '6',
content: 'Tab 6 content'
},
{
title: 'Tab 7',
name: '7',
content: 'Tab 7 content'
},
{
title: 'Tab 8',
name: '8',
content: 'Tab 8 content'
}
]
Tabs: []
}
},
created() {
// tabs
for (let i = 1; i < 9; i++) {
const title = `Tab ${i}`
this.Tabs.push({
title,
name: i + '',
content: `${title} content `
})
}
}
}

View File

@ -0,0 +1,29 @@
<template>
<tiny-tabs style="width: 400px" show-more-tabs more-show-all panel-max-height="300px" panel-width="150px">
<template #moreIcon>
<tiny-icon-popup />
</template>
<tiny-tab-item :key="item.name" v-for="item in Tabs" :title="item.title" :name="item.name">
{{ item.content }}
</tiny-tab-item>
</tiny-tabs>
</template>
<script setup lang="jsx">
import { reactive } from 'vue'
import { Tabs as TinyTabs, TabItem as TinyTabItem } from '@opentiny/vue'
import { iconPopup } from '@opentiny/vue-icon'
const Tabs = reactive([])
const TinyIconPopup = iconPopup()
// tabs
for (let i = 1; i < 101; i++) {
const title = `Tab ${i}`
Tabs.push({
title,
name: i + '',
content: `${title} content `
})
}
</script>

View File

@ -0,0 +1,53 @@
import { test, expect } from '@playwright/test'
test('超长数据下拉展示全部,面板长宽可控', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
await page.goto('tabs#more-show-all')
const tabNav = page.locator('.tiny-tabs__nav.is-top.is-show-active-bar')
const showMoreBtn = page.locator('#more-show-all').getByRole('button')
const triggerBtn = page.locator('.tiny-tabs__more-container .tiny-dropdown__trigger.tiny-dropdown-trigger')
const panel = page.locator('.tiny-tabs__more-dropdown')
await showMoreBtn.hover()
await showMoreBtn.click()
await triggerBtn.click()
await page.waitForTimeout(200)
await panel.isVisible()
await expect(panel).toHaveCSS('width', '150px')
await expect(panel).toHaveCSS('max-height', '300px')
await showMoreBtn.click()
await triggerBtn.click()
await page
.locator('div')
.filter({ hasText: /^Tab 100$/ })
.nth(1)
.scrollIntoViewIfNeeded()
await page.waitForTimeout(200)
await page
.locator('div')
.filter({ hasText: /^Tab 100$/ })
.nth(1)
.click()
const tab100 = page.getByRole('tab', { name: 'Tab 100' })
await tab100.isVisible()
await expect(tab100).toHaveClass(/is-active/)
await showMoreBtn.click()
await triggerBtn.click()
await page
.locator('div')
.filter({ hasText: /^Tab 1$/ })
.nth(1)
.scrollIntoViewIfNeeded()
await page.waitForTimeout(200)
await page
.locator('div')
.filter({ hasText: /^Tab 1$/ })
.nth(1)
.click()
const tab1 = page.getByRole('tab', { name: 'Tab 1', exact: true })
await tab1.isVisible()
await expect(tab1).toHaveClass(/is-active/)
})

View File

@ -0,0 +1,39 @@
<template>
<tiny-tabs style="width: 400px" show-more-tabs more-show-all panel-max-height="300px" panel-width="150px">
<template #moreIcon>
<tiny-icon-popup />
</template>
<tiny-tab-item :key="item.name" v-for="item in Tabs" :title="item.title" :name="item.name">
{{ item.content }}
</tiny-tab-item>
</tiny-tabs>
</template>
<script lang="jsx">
import { Tabs, TabItem } from '@opentiny/vue'
import { iconPopup } from '@opentiny/vue-icon'
export default {
components: {
TinyTabs: Tabs,
TinyTabItem: TabItem,
TinyIconPopup: iconPopup()
},
data() {
return {
Tabs: []
}
},
created() {
// tabs
for (let i = 1; i < 101; i++) {
const title = `Tab ${i}`
this.Tabs.push({
title,
name: i + '',
content: `${title} content `
})
}
}
}
</script>

View File

@ -91,9 +91,9 @@ export default {
},
desc: {
'zh-CN': `通过 <code>with-close</code> 打开关闭按钮,并监听 <code>close</code> 事件自定义实现删除页签项的逻辑。
通过 <code>beforeClose</code> <code>(name: string)=> boolean | Promise&lt;boolean&gt;</code>`,
'en-US': `Use <code>with-close</code> to enable the close button and listen to the <code>close</code> event to customize the logic for deleting tab items.
The <code>beforeClose</code> function attribute is used to call back the function before the function is closed. The type of the function is declared as <code>(name: string)=> boolean | Promise<boolean></code>.`
<code>beforeClose</code> false`,
'en-US': `Use <code>with-close</code> to open the close button and listen to the <code>close</code> event to customize the logic for deleting tab items.
<code>beforeClose</code> sets the operation before the deletion. If the return value is false, the deletion is canceled. Otherwise, the deletion is performed.`
},
codeFiles: ['tabs-events-close.vue']
},
@ -150,6 +150,20 @@ export default {
},
codeFiles: ['stretch-wh.vue']
},
{
demoId: 'more-show-all',
name: {
'zh-CN': '超长数据下拉展示',
'en-US': 'Drop-down display of ultra-long data'
},
desc: {
'zh-CN':
'通过 <code>more-show-all</code> 设置下拉面板展示全部页签项,<code>panel-max-height</code> 设置面板最大高度; <code>panel-width</code> 设置面板宽度。',
'en-US':
'Use <code>more-show-all</code> to set the drop-down panel to display all tab items and <code>panel-max-height</code> to set the maximum height of the panel. <code>panel-width</code> sets the width of the panel.'
},
codeFiles: ['more-show-all.vue']
},
{
demoId: 'custom-tab-title',
name: {

View File

@ -88,6 +88,12 @@ export const calcMorePanes =
const tabs = el.querySelectorAll('.tiny-tabs__item')
const tabNavRefs = refs.nav.$refs
// 此处不同步aui。新规范适配
if (props.moreShowAll) {
state.showPanesCount = 0
return
}
if (tabs && tabs.length) {
let tabsAllWidth = 0
for (let i = 0; i < tabs.length; i++) {

View File

@ -398,6 +398,7 @@
&__more-dropdown.@{dropdown-menu-prefix-cls}.@{popper-prefix-cls} {
margin-top: var(--ti-tabs-dropdown-more-margin-top); // smb新增
overflow: auto; // smb新增
}
&__more-dropdown &__more-item {

View File

@ -65,7 +65,11 @@ export const tabsProps = {
},
beforeClose: Function,
overflowTitle: Boolean,
titleWidth: String
titleWidth: String,
// tiny 新增
moreShowAll: Boolean,
panelMaxHeight: String,
panelWidth: String
}
export default defineComponent({

View File

@ -49,7 +49,10 @@ export default defineComponent({
'separator',
'beforeClose',
'overflowTitle',
'titleWidth'
'titleWidth',
'moreShowAll',
'panelMaxHeight',
'panelWidth'
],
components: {
TabNav,
@ -84,7 +87,9 @@ export default defineComponent({
dropConfig,
tooltipConfig,
overflowTitle,
titleWidth
titleWidth,
panelMaxHeight,
panelWidth
} = this
const newButton =
@ -120,7 +125,9 @@ export default defineComponent({
tooltipConfig,
overflowTitle,
titleWidth,
separator: state.separator
separator: state.separator,
panelMaxHeight,
panelWidth
},
on: {
'tab-drag-start': handleTabDragStart,

View File

@ -35,7 +35,9 @@ export const tabNavPcProps = {
default: '256px'
},
// tiny 新增
tooltipConfig: [String, Object]
tooltipConfig: [String, Object],
panelMaxHeight: String,
panelWidth: String
}
export const tabNavMobileProps = {

View File

@ -111,7 +111,9 @@ export default defineComponent({
handleTitleMouseleave,
// tiny
moreIcon,
tooltipConfig
tooltipConfig,
panelMaxHeight,
panelWidth
} = this
let { panes } = this
@ -174,7 +176,8 @@ export default defineComponent({
? h(DropdownMenu, {
attrs: {
popperClass: 'tiny-tabs-dropdown tiny-tabs__more-dropdown' + (popperClass ? ' ' + popperClass : ''),
placement: 'bottom-start'
placement: 'bottom-start',
style: { maxHeight: panelMaxHeight, width: panelWidth }
},
scopedSlots: { default: menuSlot }
})