Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(tabbar): add prop before-switch #3060

Merged
merged 2 commits into from
Jul 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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 @@
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 @@
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 @@
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 @@
})
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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) => {

Check warning on line 196 in src/packages/__VUE/tabbar/__tests__/index.spec.tsx

View check run for this annotation

codefactor.io / CodeFactor

src/packages/__VUE/tabbar/__tests__/index.spec.tsx#L196

Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any)
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)
})
Comment on lines +194 to +217
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

避免使用 any 类型,建议指定一个更具体的类型。

- const beforeSwitch = (_: any, index: string | number) => {
+ const beforeSwitch = (_: unknown, index: string | number) => {

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
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)
})
test('Tabbar: props.beforeSwitch', async () => {
const val = ref(0)
const beforeSwitch = (_: unknown, 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