|
139 | 139 | <div |
140 | 140 | ref="tabsContainer" |
141 | 141 | class="studio-navigation__tabs-container" |
142 | | - @keydown="handleTabsKeydown" |
143 | 142 | > |
144 | 143 | <slot name="tabs"></slot> |
145 | 144 | <div |
|
421 | 420 | }, |
422 | 421 | }, |
423 | 422 | mounted() { |
424 | | - this.updateTabIndices(); |
425 | 423 | this.updateWindowWidth(); |
426 | 424 | this.updateToolbarWidth(); |
427 | 425 | window.addEventListener('resize', this.handleResize); |
|
438 | 436 | }, |
439 | 437 | updated() { |
440 | 438 | this.$nextTick(() => { |
441 | | - this.updateTabIndices(); |
442 | 439 | this.updateToolbarWidth(); |
443 | 440 | }); |
444 | 441 | }, |
|
562 | 559 | } |
563 | 560 | return value; |
564 | 561 | }, |
565 | | - handleTabsKeydown(event) { |
566 | | - const tabs = this.getTabElements(); |
567 | | - if (!tabs.length) return; |
568 | 562 |
|
569 | | - const currentIndex = tabs.findIndex( |
570 | | - tab => tab === event.target || tab.contains(event.target), |
571 | | - ); |
572 | | -
|
573 | | - if (currentIndex === -1) return; |
574 | | -
|
575 | | - let nextIndex = currentIndex; |
576 | | -
|
577 | | - switch (event.key) { |
578 | | - case 'ArrowLeft': |
579 | | - event.preventDefault(); |
580 | | - nextIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1; |
581 | | - if (this.$isRTL) { |
582 | | - nextIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0; |
583 | | - } |
584 | | - break; |
585 | | -
|
586 | | - case 'ArrowRight': |
587 | | - event.preventDefault(); |
588 | | - nextIndex = currentIndex < tabs.length - 1 ? currentIndex + 1 : 0; |
589 | | - if (this.$isRTL) { |
590 | | - nextIndex = currentIndex > 0 ? currentIndex - 1 : tabs.length - 1; |
591 | | - } |
592 | | - break; |
593 | | -
|
594 | | - default: |
595 | | - return; |
596 | | - } |
597 | | -
|
598 | | - this.focusTab(tabs[nextIndex]); |
599 | | - }, |
600 | | - getTabElements() { |
601 | | - if (!this.$refs.tabsContainer) return []; |
602 | | -
|
603 | | - const tabs = Array.from( |
604 | | - this.$refs.tabsContainer.querySelectorAll('a[role], button[role="tab"], a[href]'), |
605 | | - ); |
606 | | -
|
607 | | - return tabs; |
608 | | - }, |
609 | | - focusTab(tabElement) { |
610 | | - if (!tabElement) return; |
611 | | -
|
612 | | - const vueInstance = tabElement.__vueParentComponent?.ctx; |
613 | | - if (vueInstance?.focus) { |
614 | | - vueInstance.focus(); |
615 | | - } else { |
616 | | - tabElement.focus(); |
617 | | - } |
618 | | - }, |
619 | | - updateTabIndices() { |
620 | | - const tabs = this.getTabElements(); |
621 | | - if (!tabs.length) return; |
622 | | -
|
623 | | - const activeTab = tabs.find( |
624 | | - tab => |
625 | | - tab.getAttribute('aria-current') === 'page' || |
626 | | - tab.getAttribute('aria-selected') === 'true', |
627 | | - ); |
628 | | - const focusableTab = activeTab || tabs[0]; |
629 | | -
|
630 | | - tabs.forEach(tab => { |
631 | | - tab.setAttribute('tabindex', tab === focusableTab ? '0' : '-1'); |
632 | | - }); |
633 | | - }, |
634 | 563 | }, |
635 | 564 | $trs: { |
636 | 565 | title: 'Kolibri Studio', |
|
0 commit comments