Skip to content

Commit 57862d0

Browse files
committed
Playground: Improved sidebar search params suspense fallback, Fix ConnectEmbed width on mobile (#7784)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on enhancing layout responsiveness and improving the rendering of sidebar components by integrating full path management, along with some styling adjustments. ### Detailed summary - Added `className="!max-w-full"` to various components for responsive design. - Wrapped `StyledConnectEmbed` in a div with overflow and padding. - Changed heading and paragraph styles in `APIHeader`. - Introduced `FullPathSuspense` for managing full path rendering. - Modified `NavLink` to accept `fullPath` prop. - Updated sidebar components to use `fullPath` for link matching. - Removed unnecessary `Suspense` wrappers from sidebar rendering functions. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Introduced a component that enables rendering content based on the full current URL path, including query parameters. * **Refactor** * Updated sidebar and navigation components to receive the current path as a prop, simplifying active link determination and layout logic. * Consolidated suspense handling for sidebar components to a single top-level boundary. * **Style** * Improved visual layout and spacing for embedded components and page headers. * Enhanced responsiveness and maximum width handling for embedded connect components. * **Documentation** * Updated type names and component signatures for improved clarity. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 834bbc0 commit 57862d0

File tree

7 files changed

+111
-74
lines changed

7 files changed

+111
-74
lines changed

apps/playground-web/src/app/wallets/sign-in/button/RightSection.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ export function RightSection(props: {
185185
// TODO: should show the expanded connected modal here instead
186186
connectButton
187187
) : (
188-
<div className="relative">
188+
<div className="relative overflow-hidden">
189189
<ConnectEmbed
190190
accountAbstraction={
191191
connectOptions.enableAccountAbstraction
@@ -197,7 +197,7 @@ export function RightSection(props: {
197197
}
198198
auth={connectOptions.enableAuth ? playgroundAuth : undefined}
199199
autoConnect={false}
200-
className="shadow-xl"
200+
className="shadow-xl !max-w-full"
201201
client={THIRDWEB_CLIENT}
202202
header={{
203203
title: connectOptions.modalTitle,

apps/playground-web/src/app/wallets/sign-in/embed/page.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,11 @@ return (
5151
);
5252
};`}
5353
lang="tsx"
54-
preview={<StyledConnectEmbed />}
54+
preview={
55+
<div className="overflow-hidden max-w-full px-3">
56+
<StyledConnectEmbed />
57+
</div>
58+
}
5559
/>
5660
);
5761
}

apps/playground-web/src/components/blocks/APIHeader.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ export function PageHeader(props: {
2626
</div>
2727
</div>
2828

29-
<h1 className="mb-0.5 font-semibold text-3xl tracking-tight">
29+
<h1 className="mb-1 font-bold text-3xl tracking-tight">
3030
{props.title}
3131
</h1>
32-
<p className="text-sm md:text-base text-muted-foreground max-w-4xl">
32+
<p className="text-sm md:text-base text-balance text-muted-foreground max-w-5xl">
3333
{props.description}
3434
</p>
3535
</div>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { usePathname } from "next/navigation";
2+
import { Suspense } from "react";
3+
import { useFullPath } from "@/hooks/full-path";
4+
5+
export function FullPathSuspense(props: {
6+
render: (fullPath: string) => React.ReactNode;
7+
}) {
8+
// use pathname to render the fallback
9+
const pathname = usePathname();
10+
return (
11+
<Suspense fallback={props.render(pathname)}>
12+
<WithFullPath render={props.render} />
13+
</Suspense>
14+
);
15+
}
16+
17+
function WithFullPath(props: {
18+
render: (fullPath: string) => React.ReactNode;
19+
}) {
20+
// use pathname + search params to render the final result
21+
const fullPath = useFullPath();
22+
return props.render(fullPath);
23+
}

apps/playground-web/src/components/blocks/full-width-sidebar-layout.tsx

Lines changed: 70 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { ChevronDownIcon, ChevronRightIcon } from "lucide-react";
44
import Link from "next/link";
5-
import { Suspense, useMemo, useState } from "react";
5+
import { useMemo, useState } from "react";
66
import {
77
Collapsible,
88
CollapsibleContent,
@@ -29,9 +29,9 @@ import {
2929
useSidebar,
3030
} from "@/components/ui/sidebar";
3131
import { cn } from "@/lib/utils";
32-
import { useFullPath } from "../../hooks/full-path";
3332
import { ThirdwebIcon } from "../../icons/ThirdwebMiniLogo";
3433
import { ThemeToggle } from "../ThemeToggle";
34+
import { FullPathSuspense } from "./full-path-suspense";
3535

3636
type ShadcnSidebarBaseLink = {
3737
href: string;
@@ -58,12 +58,27 @@ export type ShadcnSidebarLink =
5858
links: ShadcnSidebarLink[];
5959
};
6060

61-
export function FullWidthSidebarLayout(props: {
61+
type FullWidthSidebarLayoutProps = {
6262
contentSidebarLinks: ShadcnSidebarLink[];
6363
footerSidebarLinks?: ShadcnSidebarLink[];
6464
children: React.ReactNode;
6565
className?: string;
66-
}) {
66+
fullPath: string;
67+
};
68+
69+
export function FullWidthSidebarLayout(
70+
props: Omit<FullWidthSidebarLayoutProps, "fullPath">,
71+
) {
72+
return (
73+
<FullPathSuspense
74+
render={(fullPath) => (
75+
<FullWidthSidebarLayoutInner {...props} fullPath={fullPath} />
76+
)}
77+
/>
78+
);
79+
}
80+
81+
function FullWidthSidebarLayoutInner(props: FullWidthSidebarLayoutProps) {
6782
const { contentSidebarLinks, children, footerSidebarLinks } = props;
6883
const sidebar = useSidebar();
6984

@@ -99,12 +114,18 @@ export function FullWidthSidebarLayout(props: {
99114
<SidebarSeparator />
100115

101116
<SidebarContent className="p-2 no-scrollbar">
102-
<RenderSidebarMenu links={contentSidebarLinks} />
117+
<RenderSidebarMenu
118+
links={contentSidebarLinks}
119+
fullPath={props.fullPath}
120+
/>
103121
</SidebarContent>
104122

105123
{footerSidebarLinks && (
106124
<SidebarFooter className="pb-3 pt-0">
107-
<RenderSidebarMenu links={footerSidebarLinks} />
125+
<RenderSidebarMenu
126+
links={footerSidebarLinks}
127+
fullPath={props.fullPath}
128+
/>
108129
<ThemeToggle />
109130
</SidebarFooter>
110131
)}
@@ -128,6 +149,7 @@ export function FullWidthSidebarLayout(props: {
128149

129150
<MobileSidebarTrigger
130151
links={[...contentSidebarLinks, ...(footerSidebarLinks || [])]}
152+
fullPath={props.fullPath}
131153
/>
132154

133155
<main className="flex min-w-0 grow flex-col max-sm:w-full">
@@ -138,16 +160,12 @@ export function FullWidthSidebarLayout(props: {
138160
);
139161
}
140162

141-
function MobileSidebarTrigger(props: { links: ShadcnSidebarLink[] }) {
142-
return (
143-
<Suspense fallback={null}>
144-
<MobileSidebarTriggerInner links={props.links} />
145-
</Suspense>
146-
);
147-
}
148-
149-
function MobileSidebarTriggerInner(props: { links: ShadcnSidebarLink[] }) {
150-
const activeLink = useActiveShadcnSidebarLink(props.links);
163+
function MobileSidebarTrigger(props: {
164+
links: ShadcnSidebarLink[];
165+
fullPath: string;
166+
}) {
167+
const { links, fullPath } = props;
168+
const activeLink = useActiveShadcnSidebarLink({ links, fullPath });
151169

152170
return (
153171
<div className="flex items-center gap-3 border-b px-4 py-4 lg:hidden">
@@ -169,19 +187,21 @@ function MobileSidebarTriggerInner(props: { links: ShadcnSidebarLink[] }) {
169187
);
170188
}
171189

172-
function useActiveShadcnSidebarLink(links: ShadcnSidebarLink[]) {
173-
const pathname = useFullPath();
174-
190+
function useActiveShadcnSidebarLink(params: {
191+
links: ShadcnSidebarLink[];
192+
fullPath: string;
193+
}) {
194+
const { links, fullPath } = params;
175195
const activeLink = useMemo(() => {
176196
const isActive = (link: ShadcnSidebarLink): boolean => {
177197
if ("href" in link) {
178198
// Handle exact match
179199
if (link.exactMatch) {
180-
return link.href === pathname;
200+
return link.href === fullPath;
181201
}
182202

183203
// Handle prefix match (ensure we don't match partial paths)
184-
return pathname.startsWith(link.href);
204+
return fullPath.startsWith(link.href);
185205
}
186206

187207
if ("links" in link) {
@@ -192,23 +212,25 @@ function useActiveShadcnSidebarLink(links: ShadcnSidebarLink[]) {
192212
};
193213

194214
return links.find(isActive);
195-
}, [links, pathname]);
215+
}, [links, fullPath]);
196216

197217
return activeLink;
198218
}
199219

200-
function useIsSubnavActive(links: ShadcnSidebarLink[]) {
201-
const pathname = useFullPath();
202-
220+
function useIsSubnavActive(params: {
221+
links: ShadcnSidebarLink[];
222+
fullPath: string;
223+
}) {
224+
const { links, fullPath } = params;
203225
const isSubnavActive = useMemo(() => {
204226
const isActive = (link: ShadcnSidebarLink): boolean => {
205227
if ("href" in link) {
206228
// Handle exact match
207229
if (link.exactMatch) {
208-
return link.href === pathname;
230+
return link.href === fullPath;
209231
}
210232

211-
return pathname.startsWith(link.href);
233+
return fullPath.startsWith(link.href);
212234
}
213235

214236
if ("links" in link) {
@@ -219,32 +241,25 @@ function useIsSubnavActive(links: ShadcnSidebarLink[]) {
219241
};
220242

221243
return links.some(isActive);
222-
}, [links, pathname]);
244+
}, [links, fullPath]);
223245

224246
return isSubnavActive;
225247
}
226248

227249
function RenderSidebarGroup(props: {
228250
sidebarLinks: ShadcnSidebarLink[];
229251
groupName: string;
230-
}) {
231-
return (
232-
<Suspense fallback={null}>
233-
<RenderSidebarGroupInner {...props} />
234-
</Suspense>
235-
);
236-
}
237-
238-
function RenderSidebarGroupInner(props: {
239-
sidebarLinks: ShadcnSidebarLink[];
240-
groupName: string;
252+
fullPath: string;
241253
}) {
242254
return (
243255
<SidebarGroup className="p-0">
244256
<SidebarMenuItem>
245257
<SidebarGroupLabel> {props.groupName}</SidebarGroupLabel>
246258
<SidebarGroupContent>
247-
<RenderSidebarMenu links={props.sidebarLinks} />
259+
<RenderSidebarMenu
260+
links={props.sidebarLinks}
261+
fullPath={props.fullPath}
262+
/>
248263
</SidebarGroupContent>
249264
</SidebarMenuItem>
250265
</SidebarGroup>
@@ -254,20 +269,13 @@ function RenderSidebarGroupInner(props: {
254269
function RenderSidebarSubmenu(props: {
255270
links: ShadcnSidebarLink[];
256271
subMenu: Omit<ShadcnSidebarBaseLink, "href" | "exactMatch">;
272+
fullPath: string;
257273
}) {
258-
return (
259-
<Suspense fallback={null}>
260-
<RenderSidebarSubmenuInner {...props} />
261-
</Suspense>
262-
);
263-
}
264-
265-
function RenderSidebarSubmenuInner(props: {
266-
links: ShadcnSidebarLink[];
267-
subMenu: Omit<ShadcnSidebarBaseLink, "href" | "exactMatch">;
268-
}) {
274+
const isSubnavActive = useIsSubnavActive({
275+
links: props.links,
276+
fullPath: props.fullPath,
277+
});
269278
const sidebar = useSidebar();
270-
const isSubnavActive = useIsSubnavActive(props.links);
271279
const [_open, setOpen] = useState<boolean | undefined>(undefined);
272280
const open = _open === undefined ? isSubnavActive : _open;
273281

@@ -319,6 +327,7 @@ function RenderSidebarSubmenuInner(props: {
319327
className="flex items-center gap-2 text-muted-foreground text-sm hover:bg-accent hover:text-foreground px-2 py-1.5 rounded-lg w-full"
320328
exactMatch={link.exactMatch}
321329
href={link.href}
330+
fullPath={props.fullPath}
322331
onClick={() => {
323332
sidebar.setOpenMobile(false);
324333
}}
@@ -335,6 +344,7 @@ function RenderSidebarSubmenuInner(props: {
335344
<RenderSidebarSubmenu
336345
key={`submenu_${link.subMenu.label}_${index}`}
337346
links={link.links}
347+
fullPath={props.fullPath}
338348
subMenu={link.subMenu}
339349
/>
340350
);
@@ -346,6 +356,7 @@ function RenderSidebarSubmenuInner(props: {
346356
key={`group_${link.group}_${index}`}
347357
groupName={link.group}
348358
sidebarLinks={link.links}
359+
fullPath={props.fullPath}
349360
/>
350361
);
351362
}
@@ -361,7 +372,10 @@ function RenderSidebarSubmenuInner(props: {
361372
);
362373
}
363374

364-
function RenderSidebarMenu(props: { links: ShadcnSidebarLink[] }) {
375+
function RenderSidebarMenu(props: {
376+
links: ShadcnSidebarLink[];
377+
fullPath: string;
378+
}) {
365379
const sidebar = useSidebar();
366380

367381
// Add null check for links
@@ -382,6 +396,7 @@ function RenderSidebarMenu(props: { links: ShadcnSidebarLink[] }) {
382396
className="flex items-center gap-2 text-muted-foreground text-sm hover:bg-accent"
383397
exactMatch={link.exactMatch}
384398
href={link.href}
399+
fullPath={props.fullPath}
385400
onClick={() => {
386401
sidebar.setOpenMobile(false);
387402
}}
@@ -412,6 +427,7 @@ function RenderSidebarMenu(props: { links: ShadcnSidebarLink[] }) {
412427
key={`submenu_${link.subMenu.label}_${idx}`}
413428
links={link.links}
414429
subMenu={link.subMenu}
430+
fullPath={props.fullPath}
415431
/>
416432
);
417433
}
@@ -423,6 +439,7 @@ function RenderSidebarMenu(props: { links: ShadcnSidebarLink[] }) {
423439
groupName={link.group}
424440
sidebarLinks={link.links}
425441
key={`group_${link.group}_${idx}`}
442+
fullPath={props.fullPath}
426443
/>
427444
);
428445
}

apps/playground-web/src/components/styled-connect-embed.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export function StyledConnectEmbed(
4949
abstract,
5050
]}
5151
client={THIRDWEB_CLIENT}
52+
className="!max-w-full"
5253
theme={theme === "light" ? "light" : "dark"}
5354
wallets={WALLETS}
5455
{...props}

0 commit comments

Comments
 (0)