Skip to content

Commit

Permalink
feat(tabbar): add prop before-switch (#3060)
Browse files Browse the repository at this point in the history
  • Loading branch information
eiinu authored Jul 2, 2024
1 parent 22fc347 commit a0135e8
Show file tree
Hide file tree
Showing 14 changed files with 236 additions and 84 deletions.
3 changes: 3 additions & 0 deletions packages/nutui-eslint-config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export default [
...pluginVue.configs['flat/recommended'],
{
rules: {
'no-empty': ['error', {
allowEmptyCatch: true
}],
// typescript-eslint
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-types': 'off',
Expand Down
41 changes: 41 additions & 0 deletions packages/nutui-taro-demo/src/nav/pages/tabbar/before-switch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<nut-tabbar v-model="active" :before-switch="beforeSwitch">
<nut-tabbar-item tab-title="Home">
<template #icon>
<Home></Home>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="Category">
<template #icon>
<Category></Category>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="Find">
<template #icon>
<Find></Find>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="Cart">
<template #icon>
<Cart></Cart>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="My">
<template #icon>
<My></My>
</template>
</nut-tabbar-item>
</nut-tabbar>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { Home, Category, Find, Cart, My } from '@nutui/icons-vue-taro'
const active = ref(0)
const beforeSwitch = (_: any, index: string | number) => {
console.log(index)
return Number(index) % 2 === 0
}
</script>
10 changes: 8 additions & 2 deletions packages/nutui-taro-demo/src/nav/pages/tabbar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<h2>{{ t('quantity') }}</h2>
<Quantity />

<h2>{{ t('beforeSwitch') }}</h2>
<BeforeSwitch />

<h2>{{ t('fixed') }}</h2>
<Fixed />
</Demo>
Expand All @@ -36,6 +39,7 @@ import Badge from './badge.vue'
import Color from './color.vue'
import Quantity from './quantity.vue'
import Fixed from './fixed.vue'
import BeforeSwitch from './before-switch.vue'
const t = useTranslate({
'zh-CN': {
basic: '基础用法',
Expand All @@ -45,7 +49,8 @@ const t = useTranslate({
badge: '徽标提示',
color: '自定义颜色',
quantity: '自定义数量',
fixed: '固定底部'
fixed: '固定底部',
beforeSwitch: '切换前的回调'
},
'en-US': {
basic: 'Basic Usage',
Expand All @@ -55,7 +60,8 @@ const t = useTranslate({
badge: 'Show Badge',
color: 'Custom Color',
quantity: 'Custom Quantity',
fixed: 'Fixed Bottom'
fixed: 'Fixed Bottom',
beforeSwitch: 'Before Switch'
}
})
</script>
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`should render fixed element when using bottom prop 1`] = `
exports[`Tabbar: should render fixed element when using bottom prop 1`] = `
"<div class="" style="">
<view class="nut-tabbar nut-tabbar-bottom nut-tabbar-safebottom"></view>
</div>"
`;

exports[`should render placeholder when using placeholder and bottom prop 1`] = `
exports[`Tabbar: should render placeholder when using placeholder and bottom prop 1`] = `
"<div class="nut-tabbar__placeholder" style="height: 40px;">
<view class="nut-tabbar nut-tabbar-bottom"></view>
</div>"
`;

exports[`should render tabbar when default 1`] = `
exports[`Tabbar: should render tabbar when default 1`] = `
"<div class="" style="">
<view class="nut-tabbar">
<div class="nut-tabbar-item">
Expand Down
45 changes: 35 additions & 10 deletions src/packages/__VUE/tabbar/__tests__/index.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ vi.mock('@/packages/utils/useRoute')
push: vi.fn()
})

test('should render tabbar when default', async () => {
test('Tabbar: should render tabbar when default', async () => {
const wrapper = mount(() => {
return (
<Tabbar>
Expand All @@ -26,7 +26,7 @@ test('should render tabbar when default', async () => {
expect(wrapper.html()).toMatchSnapshot()
})

test('should render custom img when using img prop', async () => {
test('Tabbar: should render custom img when using img prop', async () => {
const wrapper = mount(() => {
return (
<Tabbar>
Expand Down Expand Up @@ -63,7 +63,7 @@ test('should render custom img when using img prop', async () => {
expect(tabbarItemIcon[1].element.src).toContain('c98ad61124172e93')
})

test('should render custom color and bage when using prop', async () => {
test('Tabbar: should render custom color and bage when using prop', async () => {
const wrapper = mount(() => {
return (
<Tabbar unactive-color="grey" active-color="blue">
Expand All @@ -81,7 +81,7 @@ test('should render custom color and bage when using prop', async () => {
expect(wrapper.find<HTMLElement>('.nut-badge').exists()).toBe(true)
})

test('should render fixed element when using bottom prop', async () => {
test('Tabbar: should render fixed element when using bottom prop', async () => {
const wrapper = mount(Tabbar, {
props: {
bottom: true,
Expand All @@ -90,7 +90,7 @@ test('should render fixed element when using bottom prop', async () => {
})
expect(wrapper.html()).toMatchSnapshot()
})
test('should match active tabbar by clcik', async () => {
test('Tabbar: should match active tabbar by clcik', async () => {
const wrapper = mount({
setup() {
const active = ref(0)
Expand All @@ -113,7 +113,7 @@ test('should match active tabbar by clcik', async () => {
expect(tabbarItem[2].element.style.color).toEqual('blue')
})

test('should show sure emitted when click', async () => {
test('Tabbar: should show sure emitted when click', async () => {
const tabSwitch = vi.fn()
const wrapper = mount(() => {
return (
Expand All @@ -130,7 +130,7 @@ test('should show sure emitted when click', async () => {
expect(tabSwitch).toBeCalled()
})

test('should render placeholder when using placeholder and bottom prop', async () => {
test('Tabbar: should render placeholder when using placeholder and bottom prop', async () => {
const wrapper = mount(Tabbar, {
props: {
bottom: true,
Expand All @@ -142,7 +142,7 @@ test('should render placeholder when using placeholder and bottom prop', async (
expect(wrapper.html()).toMatchSnapshot()
})

test('should redirect when exist router and using to prop', async () => {
test('Tabbar: should redirect when exist router and using to prop', async () => {
const wrapper = mount(() => {
return (
<Tabbar>
Expand All @@ -158,7 +158,7 @@ test('should redirect when exist router and using to prop', async () => {
expect(useRouter().push).toHaveBeenCalledWith('/category')
})

test('should call replace when no router exist and using to prop', async () => {
test('Tabbar: should call replace when no router exist and using to prop', async () => {
(useRouter as any).mockReturnValue(undefined)

const wrapper = mount(() => {
Expand All @@ -176,7 +176,7 @@ test('should call replace when no router exist and using to prop', async () => {
expect(location.replace).toHaveBeenCalledWith('/category')
})

test('should set window.location.href when using href prop', async () => {
test('Tabbar: should set window.location.href when using href prop', async () => {
const wrapper = mount(() => {
return (
<Tabbar>
Expand All @@ -190,3 +190,28 @@ test('should set window.location.href when using href prop', async () => {
await tabbarItem[1].trigger('click')
expect(window.location.href).toMatch('/category')
})

test('Tabbar: props.beforeSwitch', async () => {
const val = ref(0)
const beforeSwitch = (_: any, index: string | number) => {
return Number(index) % 2 === 0
}
const wrapper = mount(() => {
return (
<Tabbar v-model={val.value} beforeSwitch={beforeSwitch}>
<TabbarItem tab-title="首页" icon={h(Home)}></TabbarItem>
<TabbarItem tab-title="分类" icon={h(Category)}></TabbarItem>
<TabbarItem tab-title="发现" icon={h(Find)}></TabbarItem>
</Tabbar>
)
})
const items = wrapper.findAll('.nut-tabbar-item')
expect(items.length).toBe(3)
items[2].trigger('click')
await nextTick()
expect(val.value).toBe(2)

items[1].trigger('click')
await nextTick()
expect(val.value).toBe(2)
})
41 changes: 41 additions & 0 deletions src/packages/__VUE/tabbar/demo/before-switch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<nut-tabbar v-model="active" :before-switch="beforeSwitch">
<nut-tabbar-item tab-title="Home">
<template #icon>
<Home></Home>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="Category">
<template #icon>
<Category></Category>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="Find">
<template #icon>
<Find></Find>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="Cart">
<template #icon>
<Cart></Cart>
</template>
</nut-tabbar-item>
<nut-tabbar-item tab-title="My">
<template #icon>
<My></My>
</template>
</nut-tabbar-item>
</nut-tabbar>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { Home, Category, Find, Cart, My } from '@nutui/icons-vue'
const active = ref(0)
const beforeSwitch = (_: any, index: string | number) => {
console.log(index)
return Number(index) % 2 === 0
}
</script>
10 changes: 8 additions & 2 deletions src/packages/__VUE/tabbar/demo/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<h2>{{ t('quantity') }}</h2>
<Quantity />

<h2>{{ t('beforeSwitch') }}</h2>
<BeforeSwitch />

<h2>{{ t('fixed') }}</h2>
<Fixed />
</Demo>
Expand All @@ -36,6 +39,7 @@ import Badge from './badge.vue'
import Color from './color.vue'
import Quantity from './quantity.vue'
import Fixed from './fixed.vue'
import BeforeSwitch from './before-switch.vue'
const t = useTranslate({
'zh-CN': {
basic: '基础用法',
Expand All @@ -45,7 +49,8 @@ const t = useTranslate({
badge: '徽标提示',
color: '自定义颜色',
quantity: '自定义数量',
fixed: '固定底部'
fixed: '固定底部',
beforeSwitch: '切换前的回调'
},
'en-US': {
basic: 'Basic Usage',
Expand All @@ -55,7 +60,8 @@ const t = useTranslate({
badge: 'Show Badge',
color: 'Custom Color',
quantity: 'Custom Quantity',
fixed: 'Fixed Bottom'
fixed: 'Fixed Bottom',
beforeSwitch: 'Before Switch'
}
})
</script>
14 changes: 12 additions & 2 deletions src/packages/__VUE/tabbar/doc.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ The bardge logo component is used internally and its properties can be applied d

> demo: tabbar quantity
### Before Switch version

> demo: tabbar before-switch
### Fixed Bottom

> demo: tabbar fixed
Expand All @@ -59,12 +63,13 @@ The bardge logo component is used internally and its properties can be applied d

| Attribute | Description | Type | Default |
| --- | --- | --- | --- |
| v-model:visible | The index value of the selected label | number | `0` |
| v-model:visible | The index value of the selected label | string \| number | `0` |
| bottom | Whether to fix the bottom | boolean | `false` |
| unactive-color | Color of unactive tab item | string | `#7d7e80` |
| active-color | Color of active tab item | string | `#1989fa` |
| safe-area-inset-bottom | Whether to enable bottom safe area adaptation | boolean | `false` |
| placeholder | Whether to generate a placeholder element when fixed | boolean | `false` |
| before-switch `version` | hook before switch event | `(data, value) => boolean \| Promise<boolean>` | `() => true` |

### TabbarItem Props

Expand Down Expand Up @@ -93,7 +98,12 @@ The bardge logo component is used internally and its properties can be applied d
The component exports the following type definitions:

```js
import type { TabbarProps, TabbarInstance, TabbarItemProps, TabbarItemInstance } from '@nutui/nutui';
import type {
TabbarProps,
TabbarInstance,
TabbarItemProps,
TabbarItemInstance
} from '@nutui/nutui';
```

## Theming
Expand Down
16 changes: 13 additions & 3 deletions src/packages/__VUE/tabbar/doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ app.use(TabbarItem)

> demo: tabbar quantity
### 固定底部,可自由跳转
### 切换前的回调 version

> demo: tabbar before-switch
### 固定底部

> demo: tabbar fixed
Expand All @@ -59,12 +63,13 @@ app.use(TabbarItem)

| 参数 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| v-model | 选中标签的索引值或者名称 | number | `0` |
| v-model | 选中标签的索引值或者名称 | string \| number | `0` |
| bottom | 是否固定在页面底部 | boolean | `false` |
| unactive-color | icon 未激活的颜色 | string | `#7d7e80` |
| active-color | icon 激活的颜色 | string | `#1989fa` |
| safe-area-inset-bottom | 是否开启 iphone 系列全面屏底部安全区适配 | boolean | `false` |
| placeholder | 固定在底部时,是否在标签位置生成一个等高的占位元素 | boolean | `false` |
| before-switch `version` | 切换前的回调函数,返回 false 时拦截切换操作 | `(data, value) => boolean \| Promise<boolean>` | `() => true` |

### TabbarItem Props

Expand Down Expand Up @@ -93,7 +98,12 @@ app.use(TabbarItem)
组件导出以下类型定义:

```js
import type { TabbarProps, TabbarInstance, TabbarItemProps, TabbarItemInstance } from '@nutui/nutui';
import type {
TabbarProps,
TabbarInstance,
TabbarItemProps,
TabbarItemInstance
} from '@nutui/nutui';
```

## 主题定制
Expand Down
Loading

0 comments on commit a0135e8

Please sign in to comment.