22
33import { ChevronDownIcon , ChevronRightIcon } from "lucide-react" ;
44import Link from "next/link" ;
5- import { Suspense , useMemo , useState } from "react" ;
5+ import { useMemo , useState } from "react" ;
66import {
77 Collapsible ,
88 CollapsibleContent ,
@@ -29,9 +29,9 @@ import {
2929 useSidebar ,
3030} from "@/components/ui/sidebar" ;
3131import { cn } from "@/lib/utils" ;
32- import { useFullPath } from "../../hooks/full-path" ;
3332import { ThirdwebIcon } from "../../icons/ThirdwebMiniLogo" ;
3433import { ThemeToggle } from "../ThemeToggle" ;
34+ import { FullPathSuspense } from "./full-path-suspence" ;
3535
3636type 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
227249function 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: {
254269function 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
@@ -335,6 +343,7 @@ function RenderSidebarSubmenuInner(props: {
335343 < RenderSidebarSubmenu
336344 key = { `submenu_${ link . subMenu . label } _${ index } ` }
337345 links = { link . links }
346+ fullPath = { props . fullPath }
338347 subMenu = { link . subMenu }
339348 />
340349 ) ;
@@ -346,6 +355,7 @@ function RenderSidebarSubmenuInner(props: {
346355 key = { `group_${ link . group } _${ index } ` }
347356 groupName = { link . group }
348357 sidebarLinks = { link . links }
358+ fullPath = { props . fullPath }
349359 />
350360 ) ;
351361 }
@@ -361,7 +371,10 @@ function RenderSidebarSubmenuInner(props: {
361371 ) ;
362372}
363373
364- function RenderSidebarMenu ( props : { links : ShadcnSidebarLink [ ] } ) {
374+ function RenderSidebarMenu ( props : {
375+ links : ShadcnSidebarLink [ ] ;
376+ fullPath : string ;
377+ } ) {
365378 const sidebar = useSidebar ( ) ;
366379
367380 // Add null check for links
@@ -412,6 +425,7 @@ function RenderSidebarMenu(props: { links: ShadcnSidebarLink[] }) {
412425 key = { `submenu_${ link . subMenu . label } _${ idx } ` }
413426 links = { link . links }
414427 subMenu = { link . subMenu }
428+ fullPath = { props . fullPath }
415429 />
416430 ) ;
417431 }
@@ -423,6 +437,7 @@ function RenderSidebarMenu(props: { links: ShadcnSidebarLink[] }) {
423437 groupName = { link . group }
424438 sidebarLinks = { link . links }
425439 key = { `group_${ link . group } _${ idx } ` }
440+ fullPath = { props . fullPath }
426441 />
427442 ) ;
428443 }
0 commit comments