feat: deep-link sidebar Layouts to specific design surface
- Sidebar Layouts items now link to /design?surface=<surfaceId> - Design page reads ?surface= param and opens that surface directly - DesignPage split into DesignPageInner + Suspense wrapper so useSearchParams works in the Next.js static build Made-with: Cursor
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { use, useState, useEffect } from "react";
|
import { use, useState, useEffect, Suspense } from "react";
|
||||||
|
import { useSearchParams } from "next/navigation";
|
||||||
import { toast } from "sonner";
|
import { toast } from "sonner";
|
||||||
import {
|
import {
|
||||||
SCAFFOLD_REGISTRY, THEME_REGISTRY,
|
SCAFFOLD_REGISTRY, THEME_REGISTRY,
|
||||||
@@ -958,8 +959,9 @@ function SurfacePicker({
|
|||||||
// Page
|
// Page
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
export default function DesignPage({ params }: { params: Promise<{ workspace: string; projectId: string }> }) {
|
function DesignPageInner({ projectId }: { projectId: string }) {
|
||||||
const { projectId } = use(params);
|
const searchParams = useSearchParams();
|
||||||
|
const requestedSurface = searchParams.get("surface");
|
||||||
|
|
||||||
const [surfaces, setSurfaces] = useState<string[]>([]);
|
const [surfaces, setSurfaces] = useState<string[]>([]);
|
||||||
const [surfaceThemes, setSurfaceThemes] = useState<Record<string, string>>({});
|
const [surfaceThemes, setSurfaceThemes] = useState<Record<string, string>>({});
|
||||||
@@ -979,7 +981,11 @@ export default function DesignPage({ params }: { params: Promise<{ workspace: st
|
|||||||
setSurfaces(loaded);
|
setSurfaces(loaded);
|
||||||
setSurfaceThemes(d.surfaceThemes ?? {});
|
setSurfaceThemes(d.surfaceThemes ?? {});
|
||||||
setSelectedThemes(d.surfaceThemes ?? {});
|
setSelectedThemes(d.surfaceThemes ?? {});
|
||||||
if (loaded.length > 0) setActiveSurfaceId(loaded[0]);
|
// Honour ?surface= param if valid, otherwise default to first
|
||||||
|
const initial = requestedSurface && loaded.includes(requestedSurface)
|
||||||
|
? requestedSurface
|
||||||
|
: loaded[0] ?? null;
|
||||||
|
setActiveSurfaceId(initial);
|
||||||
return loaded;
|
return loaded;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1137,3 +1143,12 @@ export default function DesignPage({ params }: { params: Promise<{ workspace: st
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default function DesignPage({ params }: { params: Promise<{ workspace: string; projectId: string }> }) {
|
||||||
|
const { projectId } = use(params);
|
||||||
|
return (
|
||||||
|
<Suspense fallback={<div style={{ display: "flex", height: "100%", alignItems: "center", justifyContent: "center", color: "#a09a90", fontFamily: "Outfit, sans-serif", fontSize: "0.85rem" }}>Loading…</div>}>
|
||||||
|
<DesignPageInner projectId={projectId} />
|
||||||
|
</Suspense>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
@@ -338,12 +338,12 @@ export function VIBNSidebar({ workspace }: VIBNSidebarProps) {
|
|||||||
key={s}
|
key={s}
|
||||||
icon={SURFACE_ICONS[s] ?? "◌"}
|
icon={SURFACE_ICONS[s] ?? "◌"}
|
||||||
label={SURFACE_LABELS[s] ?? s}
|
label={SURFACE_LABELS[s] ?? s}
|
||||||
href={`${base}/design`}
|
href={`${base}/design?surface=${encodeURIComponent(s)}`}
|
||||||
collapsed={collapsed}
|
collapsed={collapsed}
|
||||||
/>
|
/>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<SectionRow icon="◌" label="Not configured" dim collapsed={collapsed} />
|
<SectionRow icon="◌" label="Not configured" dim href={`${base}/design`} collapsed={collapsed} />
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<SectionDivider />
|
<SectionDivider />
|
||||||
|
|||||||
Reference in New Issue
Block a user