Skip to content

Commit

Permalink
Fix <Tabs> sync issue with inconsistent use of icon on `<TabItem>…
Browse files Browse the repository at this point in the history
…` components (#1811)

Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
  • Loading branch information
HiDeoo and delucis committed May 6, 2024
1 parent 24b92ca commit fe06aa1
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/blue-otters-shave.md
@@ -0,0 +1,5 @@
---
'@astrojs/starlight': patch
---

Fixes a `<Tabs>` sync issue when inconsistently using the `icon` prop or not on `<TabItem>` components.
Expand Up @@ -35,3 +35,20 @@ A set of tabs using the `style` sync key.
<TabItem label="css">css code</TabItem>
<TabItem label="tailwind">tailwind code</TabItem>
</Tabs>

Another set of tabs using the `pkg` sync key and using icons.

<Tabs syncKey="pkg">
<TabItem label="npm" icon="seti:npm">
another npm command
</TabItem>
<TabItem label="pnpm" icon="pnpm">
another pnpm command
</TabItem>
<TabItem label="bun" icon="bun">
another bun command
</TabItem>
<TabItem label="yarn" icon="seti:yarn">
another yarn command
</TabItem>
</Tabs>
23 changes: 23 additions & 0 deletions packages/starlight/__e2e__/tabs.test.ts
Expand Up @@ -116,6 +116,29 @@ test('preserves tabs position when alternating between tabs with different conte
expect((await tabs.boundingBox())?.y).toBe(initialBoundingBox?.y);
});

test('syncs tabs with the same sync key if they do not consistenly use icons', async ({
page,
starlight,
}) => {
await starlight.goto('/tabs');

const tabs = page.locator('starlight-tabs');
const pkgTabsA = tabs.nth(0); // This set does not use icons for tab items.
const pkgTabsB = tabs.nth(4); // This set uses icons for tab items.

// Select the pnpm tab in the first set of synced tabs.
await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click();

await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command');
await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command');

// Select the yarn tab in the second set of synced tabs.
await pkgTabsB.getByRole('tab').filter({ hasText: 'yarn' }).click();

await expectSelectedTab(pkgTabsB, 'yarn', 'another yarn command');
await expectSelectedTab(pkgTabsA, 'yarn', 'yarn command');
});

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);
Expand Down
4 changes: 2 additions & 2 deletions packages/starlight/user-components/Tabs.astro
Expand Up @@ -158,7 +158,7 @@ const { html, panels } = processPanels(panelHtml);
newTab.setAttribute('aria-selected', 'true');
if (shouldSync) {
newTab.focus();
StarlightTabs.#syncTabs(this, newTab.textContent);
StarlightTabs.#syncTabs(this, newTab.innerText);
window.scrollTo({
top: window.scrollY + (this.getBoundingClientRect().top - previousTabsOffset),
});
Expand All @@ -173,7 +173,7 @@ const { html, panels } = processPanels(panelHtml);

for (const receiver of syncedTabs) {
if (receiver === emitter) continue;
const labelIndex = receiver.tabs.findIndex((tab) => tab.textContent === label);
const labelIndex = receiver.tabs.findIndex((tab) => tab.innerText === label);
if (labelIndex === -1) continue;
receiver.switchTab(receiver.tabs[labelIndex], labelIndex, false);
}
Expand Down

0 comments on commit fe06aa1

Please sign in to comment.