Skip to content

Commit b502737

Browse files
committed
Fix: Preserve route param in URL, default sidebar open on desktop
1 parent ee46820 commit b502737

File tree

2 files changed

+32
-19
lines changed

2 files changed

+32
-19
lines changed

packages/playground/website/src/lib/state/redux/slice-sites.ts

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -251,14 +251,19 @@ export function setTemporarySiteSpec(
251251
getState: () => PlaygroundReduxState
252252
) => {
253253
const siteSlug = deriveSlugFromSiteName(siteName);
254-
// Filter out UI-only params so they don't cause unnecessary site recreation.
255-
// This ensures existing temporary sites are reused when only route/modal changed.
256-
const newSiteUrlParams = {
257-
searchParams: filterUIOnlyParams(
258-
parseSearchParams(playgroundUrlWithQueryApiArgs.searchParams)
254+
// Store the full URL params including UI params like route/modal.
255+
const fullUrlParams = {
256+
searchParams: parseSearchParams(
257+
playgroundUrlWithQueryApiArgs.searchParams
259258
),
260259
hash: playgroundUrlWithQueryApiArgs.hash,
261260
};
261+
// For comparison, filter out UI-only params so we don't recreate
262+
// the site when only route/modal changed.
263+
const paramsForComparison = {
264+
searchParams: filterUIOnlyParams(fullUrlParams.searchParams),
265+
hash: fullUrlParams.hash,
266+
};
262267

263268
const showTemporarySiteError = (params: {
264269
error: SiteError;
@@ -267,7 +272,7 @@ export function setTemporarySiteSpec(
267272
// Create a mock temporary site to associate the error with.
268273
const errorSite: SiteInfo = {
269274
slug: siteSlug,
270-
originalUrlParams: newSiteUrlParams,
275+
originalUrlParams: fullUrlParams,
271276
metadata: {
272277
name: siteName,
273278
id: crypto.randomUUID(),
@@ -318,11 +323,17 @@ export function setTemporarySiteSpec(
318323

319324
const currentTemporarySite = selectTemporarySite(getState());
320325
if (currentTemporarySite) {
321-
// If the current temporary site is the same as the site we're setting,
322-
// then we don't need to create a new site.
326+
// If the current temporary site has the same non-UI params,
327+
// we don't need to create a new site.
328+
const currentParamsForComparison = {
329+
searchParams: filterUIOnlyParams(
330+
currentTemporarySite.originalUrlParams?.searchParams || {}
331+
),
332+
hash: currentTemporarySite.originalUrlParams?.hash || '',
333+
};
323334
if (
324-
JSON.stringify(currentTemporarySite.originalUrlParams) ===
325-
JSON.stringify(newSiteUrlParams)
335+
JSON.stringify(currentParamsForComparison) ===
336+
JSON.stringify(paramsForComparison)
326337
) {
327338
return currentTemporarySite;
328339
}
@@ -373,7 +384,7 @@ export function setTemporarySiteSpec(
373384
// Compute the runtime configuration based on the resolved Blueprint:
374385
const newSiteInfo: SiteInfo = {
375386
slug: siteSlug,
376-
originalUrlParams: newSiteUrlParams,
387+
originalUrlParams: fullUrlParams,
377388
metadata: {
378389
name: siteName,
379390
id: crypto.randomUUID(),

packages/playground/website/src/lib/state/redux/slice-ui.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -128,17 +128,20 @@ export interface UIState {
128128
const query = new URL(document.location.href).searchParams;
129129
const isEmbeddedInAnIframe = window.self !== window.top;
130130
// @TODO: Centralize these breakpoint sizes.
131-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
132131
const isMobile = window.innerWidth < 875;
133132

134133
// Parse the route parameter for sidebar/tab state
135134
const routeState = parseRouteParam(query.get('route'));
136-
137-
// Check if there's an explicit route param requesting the sidebar to be open.
138-
// If so, respect it regardless of viewport size (but not in seamless mode or iframes).
139-
const hasExplicitRouteParam = query.has('route') && routeState.sidebarOpen;
140135
const isSeamlessMode = query.get('mode') === 'seamless';
141136

137+
// Determine initial sidebar open state:
138+
// - If route param exists, use it (route=closed → closed, otherwise → open)
139+
// - If no route param, default to open on desktop, closed on mobile
140+
const hasExplicitRouteParam = query.has('route');
141+
const shouldSidebarBeOpen = hasExplicitRouteParam
142+
? routeState.sidebarOpen
143+
: !isMobile;
144+
142145
const initialState: UIState = {
143146
/**
144147
* Don't show certain modals after a page refresh.
@@ -165,9 +168,8 @@ const initialState: UIState = {
165168
!isSeamlessMode &&
166169
// We do not expect to render the Playground app UI in an iframe.
167170
!isEmbeddedInAnIframe &&
168-
// If there's an explicit route param requesting sidebar open, respect it.
169-
// Otherwise default to closed on all viewport sizes.
170-
hasExplicitRouteParam,
171+
// Use explicit route param if provided, otherwise default based on viewport.
172+
shouldSidebarBeOpen,
171173
siteManagerSection: routeState.section,
172174
};
173175

0 commit comments

Comments
 (0)