11<template >
2- <nav class =" ui-nav-tabs" :aria-label =" props.ariaLabel" >
3- <div
2+ <nav class =" ui-nav-tabs" :aria-label =" props.ariaLabel" role = " tablist " >
3+ <button
44 v-for =" item in props.items"
55 :key =" item.id"
6+ type =" button"
67 class =" ui-nav-tabs__item"
7- :class =" { 'ui-nav-tabs__item--active': item.active }" >
8- <span class =" ui-nav-tabs__icon material-symbols-outlined" :class =" { 'fill-1': item.active }" >
8+ role =" tab"
9+ :aria-selected =" isActive(item)"
10+ :tabindex =" isActive(item) ? 0 : -1"
11+ :class =" { 'ui-nav-tabs__item--active': isActive(item) }"
12+ @click =" handleItemClick(item.id)" >
13+ <span class =" ui-nav-tabs__icon material-symbols-outlined" :class =" { 'fill-1': isActive(item) }" >
914 {{ item.icon }}
1015 </span >
1116 <span class =" ui-nav-tabs__label" >{{ item.label }}</span >
12- </div >
17+ </button >
1318 </nav >
1419</template >
1520
1621<script setup lang="ts">
22+ import { computed , ref , watch } from ' vue' ;
23+
1724import type { NavTabsProps } from ' ./types' ;
1825
1926const props = withDefaults (defineProps <NavTabsProps >(), {
2027 ariaLabel: ' Main navigation'
2128});
29+
30+ const emit = defineEmits <{
31+ (event : ' update:modelValue' , value : string ): void ;
32+ (event : ' change' , value : string ): void ;
33+ }>();
34+
35+ const internalActiveId = ref (resolveInitialActiveId ());
36+ const activeId = computed (() => props .modelValue ?? internalActiveId .value );
37+
38+ watch (
39+ () => props .modelValue ,
40+ nextValue => {
41+ if (nextValue !== undefined ) {
42+ internalActiveId .value = nextValue ;
43+ }
44+ },
45+ { immediate: true }
46+ );
47+
48+ watch (
49+ () => props .items ,
50+ items => {
51+ if (! items .some (item => item .id === activeId .value )) {
52+ internalActiveId .value = resolveInitialActiveId ();
53+ }
54+ },
55+ { deep: true }
56+ );
57+
58+ function resolveInitialActiveId() {
59+ const preferredItem = props .items .find (item => item .active ) ?? props .items [0 ];
60+ return preferredItem ?.id ?? ' ' ;
61+ }
62+
63+ function isActive(item : NavTabsProps [' items' ][number ]) {
64+ return activeId .value === item .id ;
65+ }
66+
67+ function handleItemClick(id : string ) {
68+ if (props .modelValue === undefined ) {
69+ internalActiveId .value = id ;
70+ }
71+ emit (' update:modelValue' , id );
72+ emit (' change' , id );
73+ }
2274 </script >
2375
2476<style scoped lang="css">
@@ -38,6 +90,9 @@ const props = withDefaults(defineProps<NavTabsProps>(), {
3890}
3991
4092.ui-nav-tabs__item {
93+ appearance : none ;
94+ background : transparent ;
95+ width : 100% ;
4196 min-height : 56px ;
4297 display : flex ;
4398 flex-direction : column ;
@@ -46,6 +101,10 @@ const props = withDefaults(defineProps<NavTabsProps>(), {
46101 gap : 3px ;
47102 color : var (--ui-nav-tabs-text );
48103 border-bottom : 2px solid transparent ;
104+ border-left : 0 ;
105+ border-right : 0 ;
106+ border-top : 0 ;
107+ cursor : pointer ;
49108}
50109
51110.ui-nav-tabs__item--active {
0 commit comments