Skip to content
Draft
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
10 changes: 9 additions & 1 deletion packages/vant/src/tab/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { useId } from '../composables/use-id';
import { useExpose } from '../composables/use-expose';
import { routeProps } from '../composables/use-route';
import { TAB_STATUS_KEY } from '../composables/use-tab-status';
import type { Badge, BadgeProps } from '../badge';

// Components
import { TabTitle } from './TabTitle';
Expand All @@ -42,7 +43,14 @@ const [name, bem] = createNamespace('tab');
export const tabProps = extend({}, routeProps, {
dot: Boolean,
name: numericProp,
badge: numericProp,
badge: [...numericProp, Object] as PropType<
| Omit<
Pick<InstanceType<typeof Badge>['$props'], keyof BadgeProps>,
'dot' | 'showZero'
>
| string
| number
>,
title: String,
disabled: Boolean,
titleClass: unknownProp,
Expand Down
43 changes: 33 additions & 10 deletions packages/vant/src/tab/TabTitle.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
import { computed, defineComponent, type CSSProperties } from 'vue';
import { isDef, truthProp, numericProp, createNamespace } from '../utils';
import { Badge } from '../badge';
import {
computed,
defineComponent,
type CSSProperties,
type PropType,
} from 'vue';
import {
isDef,
truthProp,
numericProp,
createNamespace,
isObject,
} from '../utils';
import { Badge, type BadgeProps } from '../badge';

const [name, bem] = createNamespace('tab');

Expand All @@ -13,7 +24,14 @@ export const TabTitle = defineComponent({
type: String,
color: String,
title: String,
badge: numericProp,
badge: [...numericProp, Object] as PropType<
| Omit<
Pick<InstanceType<typeof Badge>['$props'], keyof BadgeProps>,
'dot' | 'showZero'
>
| string
| number
>,
shrink: Boolean,
isActive: Boolean,
disabled: Boolean,
Expand Down Expand Up @@ -60,13 +78,18 @@ export const TabTitle = defineComponent({
</span>
);

if (props.dot || (isDef(props.badge) && props.badge !== '')) {
if (
props.dot ||
(isObject(props.badge)
? isDef(props.badge.content) && props.badge.content !== ''
: isDef(props.badge) && props.badge !== '')
) {
const rest =
typeof props.badge === 'number' || typeof props.badge === 'string'
? { content: props.badge }
: props.badge;
return (
<Badge
dot={props.dot}
content={props.badge}
showZero={props.showZeroBadge}
>
<Badge dot={props.dot} showZero={props.showZeroBadge} {...rest}>
{Text}
</Badge>
);
Expand Down
20 changes: 0 additions & 20 deletions packages/vant/src/tab/test/__snapshots__/index.spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -161,26 +161,6 @@ exports[`should not render empty tab 1`] = `
</div>
`;

exports[`should render badge prop correctly 1`] = `
<div
id="van-tabs-0"
role="tab"
class="van-tab van-tab--line van-tab--active"
tabindex="0"
aria-selected="true"
aria-controls="van-tab"
data-allow-mismatch="attribute"
>
<div class="van-badge__wrapper">
<span class="van-tab__text van-tab__text--ellipsis">
</span>
<div class="van-badge van-badge--top-right van-badge--fixed">
10
</div>
</div>
</div>
`;

exports[`should render nav-left、nav-right slot correctly 1`] = `
<div class="van-tabs__wrap">
<div
Expand Down
9 changes: 7 additions & 2 deletions packages/vant/src/tab/test/index.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ref } from 'vue';
import { mount, later, triggerDrag, mockScrollTop } from '../../../test';
import { Tab } from '..';
import { Tab, type TabProps } from '..';
import { Tabs, TabsInstance } from '../../tabs';

test('should emit clickTab event when tab is clicked', async () => {
Expand Down Expand Up @@ -169,16 +169,21 @@ test('should render dot prop correctly', async () => {
test('should render badge prop correctly', async () => {
const wrapper = mount({
render() {
const badge: TabProps['badge'] = { content: '20' };
return (
<Tabs>
<Tab badge="10">Text</Tab>
<Tab badge={badge}>Text</Tab>
</Tabs>
);
},
});

await later();
expect(wrapper.find('.van-tab').html()).toMatchSnapshot();
const tabs = wrapper.findAll('.van-badge');
expect(expect.length).toBe(2);
expect(tabs[0].text()).toBe('10');
expect(tabs[1].text()).toBe('20');
});

test('should change title style when using title-style prop', async () => {
Expand Down