diff --git a/app/components/malio/tab/TabList.test.ts b/app/components/malio/tab/TabList.test.ts index 7e91ad2..12a90c0 100644 --- a/app/components/malio/tab/TabList.test.ts +++ b/app/components/malio/tab/TabList.test.ts @@ -304,6 +304,23 @@ describe('MalioTabList — fenêtrage maxVisibleTabs', () => { expect(wrapper.text()).toContain('Panel 1') }) + it('keeps exactly one rendered tab with tabindex=0 when the active tab scrolls out of the window', async () => { + const wrapper = mountComponent({tabs: sevenTabs, maxVisibleTabs: 5}) + + // active tab is the first one (t1) by default; scroll it out of the window + await wrapper.find('[data-test="tab-next"]').trigger('click') + await wrapper.find('[data-test="tab-next"]').trigger('click') + + // t1 is no longer rendered + const labels = wrapper.findAll('[role="tab"]').map(b => b.text()) + expect(labels.some(l => l.includes('Tab 1'))).toBe(false) + + const focusable = wrapper.findAll('[role="tab"]').filter(b => b.attributes('tabindex') === '0') + expect(focusable).toHaveLength(1) + // falls back to the first visible tab (Tab 3) + expect(focusable[0].text()).toContain('Tab 3') + }) + it('arrows expose aria-labels', () => { const wrapper = mountComponent({tabs: sevenTabs, maxVisibleTabs: 5}) expect(wrapper.find('[data-test="tab-prev"]').attributes('aria-label')).toBe('Onglets précédents') diff --git a/app/components/malio/tab/TabList.vue b/app/components/malio/tab/TabList.vue index 969e26a..0e58b7e 100644 --- a/app/components/malio/tab/TabList.vue +++ b/app/components/malio/tab/TabList.vue @@ -1,8 +1,7 @@