diff options
author | HiDeoo | 2024-09-19 20:55:48 +0200 |
---|---|---|
committer | GitHub | 2024-09-19 20:55:48 +0200 |
commit | a257b83f1e5704ff41bcbe85482ac81a1a61ce1f (patch) | |
tree | be1ba93533d4716b6c8d809b6ab7b2ebba0649b2 | |
parent | b02b935513819cd8634e3f656831ff184e713e91 (diff) | |
download | IT.starlight-a257b83f1e5704ff41bcbe85482ac81a1a61ce1f.tar.gz IT.starlight-a257b83f1e5704ff41bcbe85482ac81a1a61ce1f.tar.bz2 IT.starlight-a257b83f1e5704ff41bcbe85482ac81a1a61ce1f.zip |
Fix synced nested `<Tabs>` restoration issue (#2377)
-rw-r--r-- | .changeset/beige-knives-visit.md | 5 | ||||
-rw-r--r-- | packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx | 47 | ||||
-rw-r--r-- | packages/starlight/__e2e__/tabs.test.ts | 40 | ||||
-rw-r--r-- | packages/starlight/user-components/Tabs.astro | 2 |
4 files changed, 90 insertions, 4 deletions
diff --git a/.changeset/beige-knives-visit.md b/.changeset/beige-knives-visit.md new file mode 100644 index 00000000..443bbf07 --- /dev/null +++ b/.changeset/beige-knives-visit.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': patch +--- + +Fixes an issue with synced `<Tabs>` components containing nested `<Tabs>` causing tab panels to not render correctly. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx new file mode 100644 index 00000000..1be29663 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-nested.mdx @@ -0,0 +1,47 @@ +--- +title: Tabs +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +A set of tabs using the `pkg` sync key with some nested tabs using an `os` sync key. + +<Tabs syncKey="pkg"> + + <TabItem label="npm"> + + npm content + + <Tabs syncKey="os"> + <TabItem label="macos">npm macOS</TabItem> + <TabItem label="windows">npm Windows</TabItem> + <TabItem label="linux">npm GNU/Linux</TabItem> + </Tabs> + + </TabItem> + + <TabItem label="pnpm"> + + pnpm content + + <Tabs syncKey="os"> + <TabItem label="macos">pnpm macOS</TabItem> + <TabItem label="windows">pnpm Windows</TabItem> + <TabItem label="linux">pnpm GNU/Linux</TabItem> + </Tabs> + + </TabItem> + + <TabItem label="yarn"> + + yarn content + + <Tabs syncKey="os"> + <TabItem label="macos">yarn macOS</TabItem> + <TabItem label="windows">yarn Windows</TabItem> + <TabItem label="linux">yarn GNU/Linux</TabItem> + </Tabs> + + </TabItem> + +</Tabs> diff --git a/packages/starlight/__e2e__/tabs.test.ts b/packages/starlight/__e2e__/tabs.test.ts index 45e96c84..2812494f 100644 --- a/packages/starlight/__e2e__/tabs.test.ts +++ b/packages/starlight/__e2e__/tabs.test.ts @@ -312,7 +312,41 @@ test('gracefully handles invalid persisted state for synced tabs', async ({ ); }); -async function expectSelectedTab(tabs: Locator, label: string, panel: string) { - expect((await tabs.getByRole('tab', { selected: true }).textContent())?.trim()).toBe(label); - expect((await tabs.getByRole('tabpanel').textContent())?.trim()).toBe(panel); +test('syncs and restores nested tabs', async ({ page, getProdServer }) => { + const starlight = await getProdServer(); + await starlight.goto('/tabs-nested'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabs = tabs.nth(0); + const osTabsA = tabs.nth(1); + const osTabsB = tabs.nth(2); + + // Select the linux tab in the npm tab. + await osTabsA.getByRole('tab').filter({ hasText: 'linux' }).click(); + + await expectSelectedTab(osTabsA, 'linux', 'npm GNU/Linux'); + + // Select the pnpm tab. + await pkgTabs.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(pkgTabs, 'pnpm'); + await expectSelectedTab(osTabsB, 'linux', 'pnpm GNU/Linux'); + + page.reload(); + + // The synced tabs should be restored. + await expectSelectedTab(pkgTabs, 'pnpm'); + await expectSelectedTab(osTabsB, 'linux', 'pnpm GNU/Linux'); +}); + +async function expectSelectedTab(tabs: Locator, label: string, panel?: string) { + expect( + (await tabs.locator(':scope > div [role=tab][aria-selected=true]').textContent())?.trim() + ).toBe(label); + + if (panel) { + const tabPanel = tabs.locator(':scope > [role=tabpanel]:not([hidden])'); + await expect(tabPanel).toBeVisible(); + expect((await tabPanel.textContent())?.trim()).toBe(panel); + } } diff --git a/packages/starlight/user-components/Tabs.astro b/packages/starlight/user-components/Tabs.astro index f3108806..4234eb01 100644 --- a/packages/starlight/user-components/Tabs.astro +++ b/packages/starlight/user-components/Tabs.astro @@ -54,7 +54,7 @@ if (isSynced) { const tabIndexToRestore = tabs.findIndex( (tab) => tab instanceof HTMLAnchorElement && tab.textContent?.trim() === label ); - const panels = starlightTabs?.querySelectorAll('[role="tabpanel"]'); + const panels = starlightTabs?.querySelectorAll(':scope > [role="tabpanel"]'); const newTab = tabs[tabIndexToRestore]; const newPanel = panels[tabIndexToRestore]; if (tabIndexToRestore < 1 || !newTab || !newPanel) return; |