diff --git a/src/components/tabs/tab/Tab.vue b/src/components/tabs/tab/Tab.vue index e6fb74f..675a640 100644 --- a/src/components/tabs/tab/Tab.vue +++ b/src/components/tabs/tab/Tab.vue @@ -6,8 +6,9 @@ export interface TabProps { color?: ContextColorsType; disabled?: boolean; grow?: boolean; - tabValue?: number | string; + value?: number | string; active?: boolean; + activeClass?: string; link?: boolean; target?: string; to?: string; @@ -25,8 +26,9 @@ const props = withDefaults(defineProps(), { color: undefined, disabled: false, grow: false, - tabValue: generateId(), + value: generateId(), active: false, + activeClass: '', link: false, to: '', target: '_self', @@ -37,10 +39,10 @@ const props = withDefaults(defineProps(), { }); const emit = defineEmits<{ - (e: 'click', tabValue: string | number): void; + (e: 'click', value: string | number): void; }>(); -const { target, grow, active, disabled, vertical, align, tabValue } +const { target, grow, active, activeClass, disabled, vertical, align, value } = toRefs(props); const css = useCssModule(); @@ -52,7 +54,7 @@ const tabClass = computed(() => [ css[`tab--${get(align)}`], { [css['tab--grow']]: get(grow), - [`${css['tab--active']} active-tab`]: get(active), + [`${css['tab--active']} active-tab ${get(activeClass)}`]: get(active), [css['tab--disabled']]: get(disabled), [css['tab--vertical']]: get(vertical), }, @@ -62,7 +64,7 @@ const slots = useSlots(); const attrs = useAttrs(); function click() { - emit('click', get(tabValue)); + emit('click', get(value)); } diff --git a/src/components/tabs/tabs/Tabs.spec.ts b/src/components/tabs/tabs/Tabs.spec.ts index 9c40b69..a5f1248 100644 --- a/src/components/tabs/tabs/Tabs.spec.ts +++ b/src/components/tabs/tabs/Tabs.spec.ts @@ -4,16 +4,14 @@ import Tabs from '@/components/tabs/tabs/Tabs.vue'; import Tab from '@/components/tabs/tab/Tab.vue'; import { RouterLinkStub } from '~/tests/stubs/RouterLinkStub'; -function createWrapper(options?: any) { +function createWrapper(options: any = {}, customTabValue: boolean = false) { return mount(Tabs, { ...options, slots: { - default: [ - `Tab 1`, - `Tab 2`, - `Tab 3`, - `Tab 4`, - ], + default: [...new Array(4).keys()].map(item => + customTabValue + ? `Tab ${item}` + : `Tab ${item}`), }, stubs: { RouterLink: RouterLinkStub, @@ -40,7 +38,7 @@ describe('tabs/Tabs', () => { }); it('pass vertical props', async () => { - const wrapper = createWrapper({}); + const wrapper = createWrapper(); expect(wrapper.classes()).not.toEqual( expect.arrayContaining([expect.stringMatching(/_tabs--vertical_/)]), @@ -60,7 +58,7 @@ describe('tabs/Tabs', () => { }); it('pass grow props', async () => { - const wrapper = createWrapper({}); + const wrapper = createWrapper(); expect(wrapper.find('div[class*=tabs-bar]').classes()).not.toEqual( expect.arrayContaining([expect.stringMatching(/_tabs-bar--grow/)]), @@ -79,7 +77,7 @@ describe('tabs/Tabs', () => { }); it('pass disabled props', async () => { - const wrapper = createWrapper({}); + const wrapper = createWrapper(); expect(wrapper.find('button').attributes('disabled')).toBeUndefined(); @@ -91,7 +89,7 @@ describe('tabs/Tabs', () => { }); it('pass align props', async () => { - const wrapper = createWrapper({}); + const wrapper = createWrapper(); expect(wrapper.find('button').classes()).toEqual( expect.arrayContaining([expect.stringMatching(/_tab--center_/)]), @@ -141,4 +139,17 @@ describe('tabs/Tabs', () => { await nextTick(); expect(get(value)).toBe(3); }); + + it ('works with custom tab value', async () => { + const wrapper = createWrapper({}, true); + + await nextTick(); + + const buttons = wrapper.findAll('div[class*=_tabs-wrapper] > button'); + + expect(buttons).toHaveLength(4); + expect(buttons.at(0).classes()).toEqual( + expect.arrayContaining([expect.stringMatching(/active-tab/)]), + ); + }); }); diff --git a/src/components/tabs/tabs/Tabs.vue b/src/components/tabs/tabs/Tabs.vue index 5d9356f..9ab90e3 100644 --- a/src/components/tabs/tabs/Tabs.vue +++ b/src/components/tabs/tabs/Tabs.vue @@ -62,7 +62,7 @@ const children = computed(() => { || tab.componentOptions?.propsData || {}) as TabProps; - let tabValue: string | number = propsData?.tabValue ?? index; + let tabValue: string | number = propsData?.value ?? index; if (propsData.link !== false && propsData.to) tabValue = propsData.to; @@ -71,7 +71,7 @@ const children = computed(() => { const newProps = { ...inheritedProps, ...propsData, - tabValue, + value: tabValue, active, }; @@ -160,8 +160,8 @@ function applyNewValue(onlyLink = false) { let newValue: string | number = get(value) || 0; enabledChildren.forEach((child, index) => { const props = child.node.componentOptions?.propsData as TabProps; - if (!onlyLink && index === 0 && props.tabValue) - newValue = props.tabValue; + if (!onlyLink && index === 0 && props.value) + newValue = props.value; if (props.link !== false && props.to && isPathMatch(props.to, props)) newValue = props.to; @@ -192,7 +192,8 @@ const { top, bottom, left, right } = toRefs(arrivedState); const { trigger: triggerHorizontal, stop: stopHorizontal } = watchTriggerable( [wrapperWidth, width], ([ww, w]) => { - set(showArrows, ww > w); + if (w > 0) + set(showArrows, ww > w); }, { eventFilter: throttleFilter(50), @@ -202,7 +203,8 @@ const { trigger: triggerHorizontal, stop: stopHorizontal } = watchTriggerable( const { trigger: triggerVertical, stop: stopVertical } = watchTriggerable( [wrapperHeight, height], ([wh, h]) => { - set(showArrows, wh > h); + if (h > 0) + set(showArrows, wh > h); }, { eventFilter: throttleFilter(500),