summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/wise-lions-lay.md5
-rw-r--r--packages/astro/src/runtime/server/hydration.ts15
-rw-r--r--packages/astro/src/runtime/server/render/component.ts6
-rw-r--r--packages/astro/test/fixtures/view-transitions/astro.config.mjs7
-rw-r--r--packages/astro/test/fixtures/view-transitions/package.json5
-rw-r--r--packages/astro/test/fixtures/view-transitions/src/components/Island.css11
-rw-r--r--packages/astro/test/fixtures/view-transitions/src/components/Island.jsx19
-rw-r--r--packages/astro/test/fixtures/view-transitions/src/pages/hasIsland.astro10
-rw-r--r--packages/astro/test/view-transitions.test.js10
-rw-r--r--pnpm-lock.yaml9
10 files changed, 90 insertions, 7 deletions
diff --git a/.changeset/wise-lions-lay.md b/.changeset/wise-lions-lay.md
new file mode 100644
index 000000000..5718740fe
--- /dev/null
+++ b/.changeset/wise-lions-lay.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fix transition attributes on islands
diff --git a/packages/astro/src/runtime/server/hydration.ts b/packages/astro/src/runtime/server/hydration.ts
index 09f42a9b5..8c5635105 100644
--- a/packages/astro/src/runtime/server/hydration.ts
+++ b/packages/astro/src/runtime/server/hydration.ts
@@ -12,13 +12,16 @@ export interface HydrationMetadata {
directive: string;
value: string;
componentUrl: string;
- componentExport: { value: string };
+ componentExport: { value: string; };
}
+type Props = Record<string | number | symbol, any>;
+
interface ExtractedProps {
isPage: boolean;
hydration: HydrationMetadata | null;
- props: Record<string | number | symbol, any>;
+ props: Props;
+ propsWithoutTransitionAttributes: Props;
}
const transitionDirectivesToCopyOnIsland = Object.freeze([
@@ -26,16 +29,18 @@ const transitionDirectivesToCopyOnIsland = Object.freeze([
'data-astro-transition-persist',
]);
+
// Used to extract the directives, aka `client:load` information about a component.
// Finds these special props and removes them from what gets passed into the component.
export function extractDirectives(
- inputProps: Record<string | number | symbol, any>,
+ inputProps: Props,
clientDirectives: SSRResult['clientDirectives']
): ExtractedProps {
let extracted: ExtractedProps = {
isPage: false,
hydration: null,
props: {},
+ propsWithoutTransitionAttributes: {},
};
for (const [key, value] of Object.entries(inputProps)) {
if (key.startsWith('server:')) {
@@ -96,10 +101,14 @@ export function extractDirectives(
}
} else {
extracted.props[key] = value;
+ if (!transitionDirectivesToCopyOnIsland.includes(key)) {
+ extracted.propsWithoutTransitionAttributes[key] = value;
+ }
}
}
for (const sym of Object.getOwnPropertySymbols(inputProps)) {
extracted.props[sym] = inputProps[sym];
+ extracted.propsWithoutTransitionAttributes[sym] = inputProps[sym];
}
return extracted;
diff --git a/packages/astro/src/runtime/server/render/component.ts b/packages/astro/src/runtime/server/render/component.ts
index 158a88a07..91d74e812 100644
--- a/packages/astro/src/runtime/server/render/component.ts
+++ b/packages/astro/src/runtime/server/render/component.ts
@@ -92,7 +92,7 @@ async function renderFrameworkComponent(
displayName,
};
- const { hydration, isPage, props } = extractDirectives(_props, clientDirectives);
+ const { hydration, isPage, props, propsWithoutTransitionAttributes } = extractDirectives(_props, clientDirectives);
let html = '';
let attrs: Record<string, string> | undefined = undefined;
@@ -217,7 +217,7 @@ async function renderFrameworkComponent(
({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
{ result },
Component,
- props,
+ propsWithoutTransitionAttributes,
children,
metadata
));
@@ -242,7 +242,7 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr
({ html, attrs } = await renderer.ssr.renderToStaticMarkup.call(
{ result },
Component,
- props,
+ propsWithoutTransitionAttributes,
children,
metadata
));
diff --git a/packages/astro/test/fixtures/view-transitions/astro.config.mjs b/packages/astro/test/fixtures/view-transitions/astro.config.mjs
new file mode 100644
index 000000000..8a6f1951c
--- /dev/null
+++ b/packages/astro/test/fixtures/view-transitions/astro.config.mjs
@@ -0,0 +1,7 @@
+import { defineConfig } from 'astro/config';
+import react from '@astrojs/react';
+
+// https://astro.build/config
+export default defineConfig({
+ integrations: [react()],
+});
diff --git a/packages/astro/test/fixtures/view-transitions/package.json b/packages/astro/test/fixtures/view-transitions/package.json
index bc6790df4..41cee5081 100644
--- a/packages/astro/test/fixtures/view-transitions/package.json
+++ b/packages/astro/test/fixtures/view-transitions/package.json
@@ -3,6 +3,9 @@
"version": "0.0.0",
"private": true,
"dependencies": {
- "astro": "workspace:*"
+ "astro": "workspace:*",
+ "@astrojs/react": "workspace:*",
+ "react": "^18.1.0",
+ "react-dom": "^18.1.0"
}
}
diff --git a/packages/astro/test/fixtures/view-transitions/src/components/Island.css b/packages/astro/test/fixtures/view-transitions/src/components/Island.css
new file mode 100644
index 000000000..fb21044d7
--- /dev/null
+++ b/packages/astro/test/fixtures/view-transitions/src/components/Island.css
@@ -0,0 +1,11 @@
+.counter {
+ display: grid;
+ font-size: 2em;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ margin-top: 2em;
+ place-items: center;
+}
+
+.counter-message {
+ text-align: center;
+}
diff --git a/packages/astro/test/fixtures/view-transitions/src/components/Island.jsx b/packages/astro/test/fixtures/view-transitions/src/components/Island.jsx
new file mode 100644
index 000000000..cde384980
--- /dev/null
+++ b/packages/astro/test/fixtures/view-transitions/src/components/Island.jsx
@@ -0,0 +1,19 @@
+import React, { useState } from 'react';
+import './Island.css';
+
+export default function Counter({ children, count: initialCount, id }) {
+ const [count, setCount] = useState(initialCount);
+ const add = () => setCount((i) => i + 1);
+ const subtract = () => setCount((i) => i - 1);
+
+ return (
+ <>
+ <div id={id} className="counter">
+ <button className="decrement" onClick={subtract}>-</button>
+ <pre>{count}</pre>
+ <button className="increment" onClick={add}>+</button>
+ </div>
+ <div className="counter-message">{children}</div>
+ </>
+ );
+}
diff --git a/packages/astro/test/fixtures/view-transitions/src/pages/hasIsland.astro b/packages/astro/test/fixtures/view-transitions/src/pages/hasIsland.astro
new file mode 100644
index 000000000..378afb180
--- /dev/null
+++ b/packages/astro/test/fixtures/view-transitions/src/pages/hasIsland.astro
@@ -0,0 +1,10 @@
+---
+import Island from '../components/Island.jsx';
+---
+<html>
+ <head>
+ </head>
+ <body>
+ <Island id="1" count="{1}" children="Greetings!" transition:persist="here" client:load/>
+ </body>
+</html>
diff --git a/packages/astro/test/view-transitions.test.js b/packages/astro/test/view-transitions.test.js
index 6d4d19cbb..008a6e09f 100644
--- a/packages/astro/test/view-transitions.test.js
+++ b/packages/astro/test/view-transitions.test.js
@@ -22,4 +22,14 @@ describe('View Transitions styles', () => {
expect($('head style')).to.have.a.lengthOf(3);
});
+
+ it('should not duplicate transition attributes on island contents', async () => {
+ let res = await fixture.fetch('/hasIsland');
+ let html = await res.text();
+ let $ = cheerio.load(html);
+ expect($('astro-island[data-astro-transition-persist]')).to.have.a.lengthOf(1);
+ expect(
+ $('astro-island[data-astro-transition-persist] > [data-astro-transition-persist]')
+ ).to.have.a.lengthOf(0);
+ });
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d70075993..c39875566 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -3531,9 +3531,18 @@ importers:
packages/astro/test/fixtures/view-transitions:
dependencies:
+ '@astrojs/react':
+ specifier: workspace:*
+ version: link:../../../../integrations/react
astro:
specifier: workspace:*
version: link:../../..
+ react:
+ specifier: ^18.1.0
+ version: 18.2.0
+ react-dom:
+ specifier: ^18.1.0
+ version: 18.2.0(react@18.2.0)
packages/astro/test/fixtures/virtual-astro-file:
dependencies: