Skip to content

Commit 6a87fb2

Browse files
committed
Support Reveal collapsed mode in string SSR
Provide RevealGroupContext in non-async Reveal so server-side collapsing works correctly for flat groups. Collapsed boundaries serialize $$f but render no HTML, letting the client manage them after hydration. Nested Reveal with collapsed/together logs a warning in renderToString since client-side coordination requires renderToStream. Made-with: Cursor
1 parent 159d204 commit 6a87fb2

3 files changed

Lines changed: 39 additions & 5 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"solid-js": patch
3+
---
4+
5+
Support Reveal collapsed mode in string (non-async) SSR by providing RevealGroupContext and collapsing non-frontier fallbacks server-side. Warn for nested Reveal in renderToString where client coordination is limited.

packages/solid/src/server/flow.ts

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { children } from "./core.js";
22
import {
33
createMemo,
44
createOwner,
5-
createRevealOrder,
65
mapArray,
76
repeat,
87
createErrorBoundary,
@@ -174,14 +173,38 @@ export function Reveal(props: {
174173
collapsed?: boolean;
175174
children: JSX.Element;
176175
}): JSX.Element {
177-
if (!sharedConfig.context?.async) {
178-
return createRevealOrder(() => props.children) as unknown as JSX.Element;
179-
}
180-
const ctx = sharedConfig.context;
181176
const o = createOwner();
182177
const id = o.id!;
183178
const together = !!props.together;
184179
const collapsed = !!props.collapsed;
180+
181+
if (!sharedConfig.context?.async) {
182+
const parent = getOwner();
183+
const parentGroup = parent ? runWithOwner(parent, () => getContext(RevealGroupContext)) : null;
184+
let collapsedByParent = false;
185+
if (parentGroup) {
186+
collapsedByParent = parentGroup.register(id);
187+
if (collapsed || together)
188+
console.warn(
189+
"Nested <Reveal> with collapsed/together won't coordinate correctly with renderToString. Use renderToStream for full support."
190+
);
191+
}
192+
let count = 0;
193+
return runWithOwner(o, () => {
194+
setContext(RevealGroupContext, {
195+
id,
196+
register(_key: string) {
197+
count++;
198+
if (collapsedByParent) return true;
199+
return !together && collapsed && count > 1;
200+
},
201+
onResolved() {}
202+
});
203+
return props.children;
204+
}) as unknown as JSX.Element;
205+
}
206+
207+
const ctx = sharedConfig.context;
185208
const keys: string[] = [];
186209
const resolved = new Set<string>();
187210
const composites = new Map<string, () => void>();

packages/solid/src/server/hydration.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,12 @@ export function createLoadingBoundary(
155155

156156
const collapseFallback = revealGroup ? revealGroup.register(id) : false;
157157

158+
if (collapseFallback && !ctx.async) {
159+
commitBoundaryState();
160+
ctx.serialize(id, "$$f");
161+
return () => undefined;
162+
}
163+
158164
const fallbackOwner = createOwner({ id });
159165
const fallbackResult = runWithOwner(fallbackOwner, () => {
160166
if (!ctx.async) return fallback();

0 commit comments

Comments
 (0)