Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extends virtual module astro:transitions/client to export swapFunctions #11708

Merged
merged 11 commits into from
Aug 28, 2024
32 changes: 32 additions & 0 deletions .changeset/new-monkeys-sit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
'astro': minor
---

Adds a new object `swapFunctions` to expose the necessary utility functions on `astro:transitions/client` that allow you to build custom swap functions to be used with view transitions.

The example below uses these functions to replace the default `swap` function with one that only swaps the `<main>` part of the page:
martrapp marked this conversation as resolved.
Show resolved Hide resolved

```astro
<script>
import { swapFunctions } from 'astro:transitions/client';

document.addEventListener('astro:before-swap', (e) => { e.swap = () => swapMainOnly(e.newDocument) });

function swapMainOnly(doc: Document) {
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = swapFunctions.saveFocus();
const newMain = doc.querySelector('main');
const oldMain = document.querySelector('main');
if (newMain && oldMain) {
swapFunctions.swapBodyElement(newMain, oldMain);
} else {
swapFunctions.swapBodyElement(doc.body, document.body);
}
restoreFocusFunction();
};
<script>
```
martrapp marked this conversation as resolved.
Show resolved Hide resolved

See the [view transitions guide](https://docs.astro.build/en/guides/view-transitions/#astrobefore-swap) for more information about hooking into the `astro:before-swap` lifecycle event and adding a custom swap implementation.
2 changes: 2 additions & 0 deletions packages/astro/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ declare module 'astro:transitions/client' {
import('./dist/virtual-modules/transitions-events.js').TransitionBeforeSwapEvent;
export const isTransitionBeforePreparationEvent: EventModule['isTransitionBeforePreparationEvent'];
export const isTransitionBeforeSwapEvent: EventModule['isTransitionBeforeSwapEvent'];
type TransitionSwapFunctionModule = typeof import('./dist/virtual-modules/transitions-swap-functions.js');
export const swapFunctions: TransitionSwapFunctionModule['swapFunctions']
}

declare module 'astro:prefetch' {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@ import Layout from '../components/Layout.astro';
</Layout>
<script>

import { deselectScripts, saveFocus, swapBodyElement, swapHeadElements, swapRootAttributes } from '../../node_modules/astro/dist/transitions/swap-functions'
import { swapFunctions } from 'astro:transitions/client';

document.addEventListener('astro:before-swap', (e) => {
e.swap = () => keepStyle(e.newDocument)
});

function keepStyle(doc: Document) {
deselectScripts(doc);
swapRootAttributes(doc);
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
{
const dynamicStyle = document.head.querySelector('style:not(:empty)');
swapHeadElements(doc);
swapFunctions.swapHeadElements(doc);
dynamicStyle && document.head.insertAdjacentElement('afterbegin', dynamicStyle);
}
const restoreFocusFunction = saveFocus();
swapBodyElement(doc.body, document.body)
const restoreFocusFunction = swapFunctions.saveFocus();
swapFunctions.swapBodyElement(doc.body, document.body)
restoreFocusFunction();
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import Layout from '../components/Layout.astro';
<a id="click" href="/keep-two">go to next page</a>
</Layout>
<script>
import { deselectScripts, saveFocus, swapBodyElement, swapHeadElements, swapRootAttributes } from '../../node_modules/astro/dist/transitions/swap-functions'
import { swapFunctions } from 'astro:transitions/client';

function keepTheme(doc:Document) {
deselectScripts(doc);
swapFunctions.deselectScripts(doc);
{
const theme = document.documentElement.getAttribute('data-theme')!;
swapRootAttributes(doc);
swapFunctions.swapRootAttributes(doc);
document.documentElement.setAttribute('data-theme', theme);
}
swapHeadElements(doc);
const restoreFocusFunction = saveFocus();
swapBodyElement(doc.body, document.body)
swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = swapFunctions.saveFocus();
swapFunctions.swapBodyElement(doc.body, document.body)
restoreFocusFunction();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@ import Layout from '../components/Layout.astro';
<a id="click" href="/keep-two">go to next page</a>
</Layout>
<script>
import { deselectScripts, saveFocus, swapBodyElement, swapHeadElements, swapRootAttributes } from "../../node_modules/astro/dist/transitions/swap-functions"
import { swapFunctions } from 'astro:transitions/client';

document.addEventListener('astro:before-swap', (e) => {
e.swap = () => replaceMain(e.newDocument)
});

function replaceMain(doc:Document){
deselectScripts(doc);
swapRootAttributes(doc);
swapHeadElements(doc);
const restoreFocusFunction = saveFocus();
swapFunctions.deselectScripts(doc);
swapFunctions.swapRootAttributes(doc);
swapFunctions.swapHeadElements(doc);
const restoreFocusFunction = swapFunctions.saveFocus();
{
const newMain = doc.body.querySelector('main section');
const oldMain = document.body.querySelector('main section');
if (newMain && oldMain) {
swapBodyElement(newMain, oldMain);
swapFunctions.swapBodyElement(newMain, oldMain);
} else {
swapBodyElement(doc.body, document.body);
swapFunctions.swapBodyElement(doc.body, document.body);
}
}
restoreFocusFunction();
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/e2e/view-transitions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1445,7 +1445,7 @@ test.describe('View Transitions', () => {
await page.click('#click');
await expect(page.locator('#name'), 'should have content').toHaveText('Keep 2');

const styleElement = await page.$('head > style');
const styleElement = await page.$('head > style:nth-child(1)');
const styleContent = await page.evaluate((style) => style.innerHTML, styleElement);
expect(styleContent).toBe('body { background-color: purple; }');
});
Expand Down
8 changes: 8 additions & 0 deletions packages/astro/src/transitions/swap-functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ const shouldCopyProps = (el: HTMLElement): boolean => {
return persistProps == null || persistProps === 'false';
};

export const swapFunctions = {
deselectScripts,
swapRootAttributes,
swapHeadElements,
swapBodyElement,
saveFocus,
};

export const swap = (doc: Document) => {
deselectScripts(doc);
swapRootAttributes(doc);
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/transitions/vite-plugin-transitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export default function astroTransitions({ settings }: { settings: AstroSettings
TRANSITION_BEFORE_SWAP, isTransitionBeforeSwapEvent, TransitionBeforeSwapEvent,
TRANSITION_AFTER_SWAP, TRANSITION_PAGE_LOAD
} from "astro/virtual-modules/transitions-events.js";
export { swapFunctions } from "astro/virtual-modules/transitions-swap-functions.js";
`;
}
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from '../transitions/swap-functions.js';
Loading