diff --git a/.changeset/config.json b/.changeset/config.json index 1a3e4d0dc8f..f50e3128e03 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -9,7 +9,7 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["starlight-docs", "@example/*", "starlight-file-icons-generator"], + "ignore": ["starlight-docs", "@example/*", "starlight-file-icons-generator", "@e2e/*"], "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": { "onlyUpdatePeerDependentsWhenOutOfRange": true } diff --git a/.changeset/eight-pens-end.md b/.changeset/eight-pens-end.md new file mode 100644 index 00000000000..4aaee094c93 --- /dev/null +++ b/.changeset/eight-pens-end.md @@ -0,0 +1,5 @@ +--- +'@astrojs/starlight': minor +--- + +Adds support for syncing multiple sets of tabs on the same page. diff --git a/.changeset/slimy-swans-teach.md b/.changeset/slimy-swans-teach.md new file mode 100644 index 00000000000..ae11506755d --- /dev/null +++ b/.changeset/slimy-swans-teach.md @@ -0,0 +1,13 @@ +--- +'@astrojs/starlight': minor +--- + +Updates the default `line-height` from `1.8` to `1.75`. This change avoids having a line height with a fractional part which can cause scripts accessing dimensions involving the line height to get an inconsistent rounded value in various browsers. + +If you want to preserve the previous `line-height`, you can add the following custom CSS to your site: + +```css +:root { + --sl-line-height: 1.8; +} +``` diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbde0027a03..beb12cf4dd5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,20 @@ jobs: - name: Test packages run: pnpm -r test:coverage + e2e-test: + name: Run E2E tests + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v3 + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: 'pnpm' + - run: pnpm i + - name: Test packages + run: pnpm -r test:e2e + pa11y: name: Check for accessibility issues runs-on: ubuntu-20.04 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 275ead4017a..973d01ef261 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -187,6 +187,36 @@ pnpm test:coverage This will print a table to your terminal and also generate an HTML report you can load in a web browser by opening [`packages/starlight/__coverage__/index.html`](./packages/starlight/__coverage__/index.html). +### End-to-end (E2E) tests + +Starlight also includes E2E tests in [`packages/starlight/__e2e__/`](./packages/starlight/__e2e__/), which are run using [Playwright][playwright]. + +To run these tests, move into the Starlight package and then run `pnpm test:e2e`: + +```sh +cd packages/starlight +pnpm test:e2e +``` + +#### Test fixtures + +Each subdirectory of `packages/starlight/__e2e__/fixtures` should contain the basic files needed to run Starlight (`package.json`, `astro.config.mjs`, a content collection configuration in `src/content/config.ts` and some content to render in `src/content/docs/`). + +The `testFactory()` helper can be used in a test file to define the fixture which will be built and loaded in a preview server during a set of tests. + +```ts +// packages/starlight/__e2e__/feature.test.ts +import { testFactory } from './test-utils'; + +const test = await testFactory('./fixtures/basics/'); +``` + +This allows you to run tests against different combinations of Astro and Starlight configuration options for various content. + +#### When to add E2E tests? + +E2E are most useful for testing what happens on a page after it has been loaded by a browser. They run slower than unit tests so they should be used sparingly when unit tests aren’t sufficient. + ## Translations Translations help make Starlight accessible to more people. @@ -254,6 +284,7 @@ To add a language, you will need its BCP-47 tag and a label. See [“Adding a ne [gfi]: https://github.com/withastro/starlight/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22+ [api-docs]: https://docs.astro.build/en/reference/integrations-reference/ [vitest]: https://vitest.dev/ +[playwright]: https://playwright.dev/ ## Showcase diff --git a/docs/src/content/docs/getting-started.mdx b/docs/src/content/docs/getting-started.mdx index eb3a8f3e25b..810b17f849e 100644 --- a/docs/src/content/docs/getting-started.mdx +++ b/docs/src/content/docs/getting-started.mdx @@ -15,7 +15,7 @@ See the [manual setup instructions](/manual-setup/) to add Starlight to an exist Create a new Astro + Starlight project by running the following command in your terminal: - + ```sh @@ -52,7 +52,7 @@ When working locally, [Astro’s development server](https://docs.astro.build/en Inside your project directory, run the following command to start the development server: - + ```sh @@ -103,7 +103,7 @@ Be sure to update Starlight regularly! Starlight is an Astro integration. You can update it and other Astro packages by running the following command in your terminal: - + ```sh diff --git a/docs/src/content/docs/guides/components.mdx b/docs/src/content/docs/guides/components.mdx index a193175b389..b01050f0e99 100644 --- a/docs/src/content/docs/guides/components.mdx +++ b/docs/src/content/docs/guides/components.mdx @@ -87,6 +87,50 @@ The code above generates the following tabs on the page: +#### Synced tabs + +Keep multiple tab groups synchronized by adding the `syncKey` attribute. + +All `` on a page with the same `syncKey` value will display the same active label. This allows your reader to choose once (e.g. their operating system or package manager), and see their choice reflected throughout the page. + +To synchronize related tabs, add an identical `syncKey` property to each `` component and ensure that they all use the same `` labels: + +```mdx 'syncKey="constellations"' +# src/content/docs/example.mdx + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +_Some stars:_ + + + Bellatrix, Rigel, Betelgeuse + Pollux, Castor A, Castor B + + +_Some exoplanets:_ + + + HD 34445 b, Gliese 179 b, Wasp-82 b + Pollux b, HAT-P-24b, HD 50554 b + +``` + +The code above generates the following on the page: + +_Some stars:_ + + + Bellatrix, Rigel, Betelgeuse + Pollux, Castor A, Castor B + + +_Some exoplanets:_ + + + HD 34445 b, Gliese 179 b, Wasp-82 b + Pollux b, HAT-P-24b, HD 50554 b + + ### Cards import { Card, CardGrid } from '@astrojs/starlight/components'; diff --git a/docs/src/content/docs/guides/css-and-tailwind.mdx b/docs/src/content/docs/guides/css-and-tailwind.mdx index 2ef37b60eb6..45c88e652b6 100644 --- a/docs/src/content/docs/guides/css-and-tailwind.mdx +++ b/docs/src/content/docs/guides/css-and-tailwind.mdx @@ -63,7 +63,7 @@ The Starlight Tailwind plugin applies the following configuration: Start a new Starlight project with Tailwind CSS pre-configured using `create astro`: - + ```sh @@ -95,7 +95,7 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these 1. Add Astro’s Tailwind integration: - + @@ -125,7 +125,7 @@ If you already have a Starlight site and want to add Tailwind CSS, follow these 2. Install the Starlight Tailwind plugin: - + diff --git a/docs/src/content/docs/guides/customization.mdx b/docs/src/content/docs/guides/customization.mdx index c2eaa328bf5..1bb35d21166 100644 --- a/docs/src/content/docs/guides/customization.mdx +++ b/docs/src/content/docs/guides/customization.mdx @@ -130,7 +130,7 @@ You can customize — or even disable — the table of contents globally in the By default, `

` and `

` headings are included in the table of contents. Change which headings levels to include site-wide using the `minHeadingLevel` and `maxHeadingLevel` options in your [global `tableOfContents`](/reference/configuration/#tableofcontents). Override these defaults on an individual page by adding the corresponding [frontmatter `tableOfContents`](/reference/frontmatter/#tableofcontents) properties: - + ```md {4-6} @@ -164,7 +164,7 @@ defineConfig({ Disable the table of contents entirely by setting the `tableOfContents` option to `false`: - + ```md {4} diff --git a/package.json b/package.json index e0609e2ae0e..8e0fd9e6ce1 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ { "name": "/_astro/*.js", "path": "examples/basics/dist/_astro/*.js", - "limit": "22.5 kB" + "limit": "23 kB" }, { "name": "/_astro/*.css", diff --git a/packages/starlight/__e2e__/.gitignore b/packages/starlight/__e2e__/.gitignore new file mode 100644 index 00000000000..bde2931f74f --- /dev/null +++ b/packages/starlight/__e2e__/.gitignore @@ -0,0 +1,3 @@ +# generated types +.astro/ +dist/ diff --git a/packages/starlight/__e2e__/fixtures/basics/astro.config.mjs b/packages/starlight/__e2e__/fixtures/basics/astro.config.mjs new file mode 100644 index 00000000000..9e96cbad3d1 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/astro.config.mjs @@ -0,0 +1,10 @@ +import starlight from '@astrojs/starlight'; +import { defineConfig } from 'astro/config'; + +export default defineConfig({ + integrations: [ + starlight({ + title: 'Basics', + }), + ], +}); diff --git a/packages/starlight/__e2e__/fixtures/basics/package.json b/packages/starlight/__e2e__/fixtures/basics/package.json new file mode 100644 index 00000000000..bbdb1613026 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/package.json @@ -0,0 +1,9 @@ +{ + "name": "@e2e/basics", + "version": "0.0.0", + "private": true, + "dependencies": { + "@astrojs/starlight": "workspace:*", + "astro": "^4.3.5" + } +} diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/config.ts b/packages/starlight/__e2e__/fixtures/basics/src/content/config.ts new file mode 100644 index 00000000000..45f60b01542 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/config.ts @@ -0,0 +1,6 @@ +import { defineCollection } from 'astro:content'; +import { docsSchema } from '@astrojs/starlight/schema'; + +export const collections = { + docs: defineCollection({ schema: docsSchema() }), +}; diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx new file mode 100644 index 00000000000..7c7a0485864 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs-variable-height.mdx @@ -0,0 +1,151 @@ +--- +title: Tabs with varying content heights +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +**A set of tabs using a sync key with content of different heights between tabs.** + + + + +A little bit of text. + + + + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + + + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +**Another set of tabs using the same sync key with content of different heights between tabs.** + + + + +A little bit of text. + + + + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + +A lot more text. + + + + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. diff --git a/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs.mdx b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs.mdx new file mode 100644 index 00000000000..17e643a6131 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/content/docs/tabs.mdx @@ -0,0 +1,37 @@ +--- +title: Tabs +--- + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +A set of tabs using the `pkg` sync key. + + + npm command + pnpm command + yarn command + + +A basic set of tabs. + + + tab 1 + tab 2 + tab 3 + + +Another set of tabs using the `pkg` sync key and an extra tab. + + + another npm command + another pnpm command + another bun command + another yarn command + + +A set of tabs using the `style` sync key. + + + css code + tailwind code + diff --git a/packages/starlight/__e2e__/fixtures/basics/src/env.d.ts b/packages/starlight/__e2e__/fixtures/basics/src/env.d.ts new file mode 100644 index 00000000000..c13bd73c723 --- /dev/null +++ b/packages/starlight/__e2e__/fixtures/basics/src/env.d.ts @@ -0,0 +1,2 @@ +/// +/// \ No newline at end of file diff --git a/packages/starlight/__e2e__/tabs.test.ts b/packages/starlight/__e2e__/tabs.test.ts new file mode 100644 index 00000000000..e0a36ed5367 --- /dev/null +++ b/packages/starlight/__e2e__/tabs.test.ts @@ -0,0 +1,122 @@ +import { expect, testFactory, type Locator } from './test-utils'; + +const test = await testFactory('./fixtures/basics/'); + +test('syncs tabs with a click event', async ({ page, starlight }) => { + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); + + // 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'); +}); + +test('syncs tabs with a keyboard event', async ({ page, starlight }) => { + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); + + // Select the pnpm tab in the first set of synced tabs with the keyboard. + await pkgTabsA.getByRole('tab', { selected: true }).press('ArrowRight'); + + await expectSelectedTab(pkgTabsA, 'pnpm', 'pnpm command'); + await expectSelectedTab(pkgTabsB, 'pnpm', 'another pnpm command'); + + // Select back the npm tab in the second set of synced tabs with the keyboard. + const selectedTabB = pkgTabsB.getByRole('tab', { selected: true }); + await selectedTabB.press('ArrowRight'); + await selectedTabB.press('ArrowLeft'); + await selectedTabB.press('ArrowLeft'); + + await expectSelectedTab(pkgTabsA, 'npm', 'npm command'); + await expectSelectedTab(pkgTabsB, 'npm', 'another npm command'); +}); + +test('syncs only tabs using the same sync key', async ({ page, starlight }) => { + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const unsyncedTabs = tabs.nth(1); + const styleTabs = tabs.nth(3); + + // Select the pnpm tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab').filter({ hasText: 'pnpm' }).click(); + + await expectSelectedTab(unsyncedTabs, 'one', 'tab 1'); + await expectSelectedTab(styleTabs, 'css', 'css code'); +}); + +test('supports synced tabs with different tab items', async ({ page, starlight }) => { + await starlight.goto('/tabs'); + + const tabs = page.locator('starlight-tabs'); + const pkgTabsA = tabs.nth(0); + const pkgTabsB = tabs.nth(2); // This set contains an extra tab item. + + // Select the bun tab in the second set of synced tabs. + await pkgTabsB.getByRole('tab').filter({ hasText: 'bun' }).click(); + + await expectSelectedTab(pkgTabsA, 'npm', 'npm command'); + await expectSelectedTab(pkgTabsB, 'bun', 'another bun command'); +}); + +test('persists the focus when syncing tabs', async ({ page, starlight }) => { + await starlight.goto('/tabs'); + + const pkgTabsA = page.locator('starlight-tabs').nth(0); + + // Focus the selected tab in the set of tabs synced with the 'pkg' key. + await pkgTabsA.getByRole('tab', { selected: true }).focus(); + // Select the pnpm tab in the set of tabs synced with the 'pkg' key using the keyboard. + await page.keyboard.press('ArrowRight'); + + expect( + await pkgTabsA + .getByRole('tab', { selected: true }) + .evaluate((node) => document.activeElement === node) + ).toBe(true); +}); + +test('preserves tabs position when alternating between tabs with different content heights', async ({ + page, + starlight, +}) => { + await starlight.goto('/tabs-variable-height'); + + const tabs = page.locator('starlight-tabs').nth(1); + const selectedTab = tabs.getByRole('tab', { selected: true }); + + // Scroll to the second set of synced tabs and focus the selected tab. + await tabs.scrollIntoViewIfNeeded(); + await selectedTab.focus(); + + // Get the bounding box of the tabs. + const initialBoundingBox = await tabs.boundingBox(); + + // Select the second tab which has a different height. + await selectedTab.press('ArrowRight'); + + // Ensure the tabs vertical position is exactly the same after selecting the second tab. + // Note that a small difference could be the result of the base line-height having a fractional part which can cause a + // sub-pixel difference in some browsers like Chrome or Firefox. + expect((await tabs.boundingBox())?.y).toBe(initialBoundingBox?.y); +}); + +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); +} diff --git a/packages/starlight/__e2e__/test-utils.ts b/packages/starlight/__e2e__/test-utils.ts new file mode 100644 index 00000000000..e604732357d --- /dev/null +++ b/packages/starlight/__e2e__/test-utils.ts @@ -0,0 +1,53 @@ +import { fileURLToPath } from 'node:url'; +import { test as baseTest, type Page } from '@playwright/test'; +import { build, preview } from 'astro'; + +export { expect, type Locator } from '@playwright/test'; + +// Setup a test environment that will build and start a preview server for a given fixture path and +// provide a Starlight Playwright fixture accessible from within all tests. +export async function testFactory(fixturePath: string) { + let previewServer: PreviewServer | undefined; + + const test = baseTest.extend<{ starlight: StarlightPage }>({ + starlight: async ({ page }, use) => { + if (!previewServer) { + throw new Error('Could not find a preview server to run tests against.'); + } + + await use(new StarlightPage(previewServer, page)); + }, + }); + + test.beforeAll(async () => { + const root = fileURLToPath(new URL(fixturePath, import.meta.url)); + await build({ logLevel: 'error', root }); + previewServer = await preview({ logLevel: 'error', root }); + }); + + test.afterAll(async () => { + await previewServer?.stop(); + }); + + return test; +} + +// A Playwright test fixture accessible from within all tests. +class StarlightPage { + constructor( + private readonly previewServer: PreviewServer, + private readonly page: Page + ) {} + + // Navigate to a URL relative to the server used during a test run and return the resource response. + goto(url: string) { + return this.page.goto(this.resolveUrl(url)); + } + + // Resolve a URL relative to the server used during a test run. + resolveUrl(url: string) { + return `http://localhost:${this.previewServer.port}${url.replace(/^\/?/, '/')}`; + } +} + +type PreviewServer = Awaited>; diff --git a/packages/starlight/package.json b/packages/starlight/package.json index 4991eec2338..7f9c4f92b49 100644 --- a/packages/starlight/package.json +++ b/packages/starlight/package.json @@ -4,7 +4,8 @@ "description": "Build beautiful, high-performance documentation websites with Astro", "scripts": { "test": "vitest", - "test:coverage": "vitest run --coverage" + "test:coverage": "vitest run --coverage", + "test:e2e": "playwright install --with-deps chromium && playwright test" }, "keywords": [ "docs", @@ -183,6 +184,7 @@ }, "devDependencies": { "@astrojs/markdown-remark": "^4.2.1", + "@playwright/test": "^1.43.1", "@types/node": "^18.16.19", "@vitest/coverage-v8": "^1.3.1", "astro": "^4.3.5", diff --git a/packages/starlight/playwright.config.ts b/packages/starlight/playwright.config.ts new file mode 100644 index 00000000000..01098ea8b0d --- /dev/null +++ b/packages/starlight/playwright.config.ts @@ -0,0 +1,15 @@ +import { defineConfig, devices } from '@playwright/test'; + +export default defineConfig({ + forbidOnly: !!process.env['CI'], + projects: [ + { + name: 'Chrome Stable', + use: { + ...devices['Desktop Chrome'], + headless: true, + }, + }, + ], + testMatch: '__e2e__/*.test.ts', +}); diff --git a/packages/starlight/style/props.css b/packages/starlight/style/props.css index be9bbb9d74a..d8ef97ea4dd 100644 --- a/packages/starlight/style/props.css +++ b/packages/starlight/style/props.css @@ -79,7 +79,7 @@ --sl-text-h4: var(--sl-text-xl); --sl-text-h5: var(--sl-text-lg); - --sl-line-height: 1.8; + --sl-line-height: 1.75; --sl-line-height-headings: 1.2; --sl-font-system: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, diff --git a/packages/starlight/user-components/Tabs.astro b/packages/starlight/user-components/Tabs.astro index 2f58103d726..376fb19c935 100644 --- a/packages/starlight/user-components/Tabs.astro +++ b/packages/starlight/user-components/Tabs.astro @@ -2,11 +2,16 @@ import Icon from './Icon.astro'; import { processPanels } from './rehype-tabs'; +interface Props { + syncKey?: string; +} + +const { syncKey } = Astro.props; const panelHtml = await Astro.slots.render('default'); const { html, panels } = processPanels(panelHtml); --- - + { panels && (
@@ -74,14 +79,25 @@ const { html, panels } = processPanels(panelHtml);