|
2 | 2 | import "../app.css"; |
3 | 3 | import { Navigation } from "@skeletonlabs/skeleton-svelte"; |
4 | 4 | import { page } from "$app/state"; |
5 | | - import { navSections, type NavigationSection } from "$lib/config/navigation"; |
| 5 | + import { navSections as allNavSections, type NavigationSection } from "$lib/config/navigation"; |
| 6 | +
|
| 7 | + // Separate My Account from other sections so it renders right after API Explorer |
| 8 | + const myAccountSection = allNavSections.find(s => s.id === "my-account"); |
| 9 | + const navSections = allNavSections.filter(s => s.id !== "my-account"); |
6 | 10 | import Toast from "$lib/components/Toast.svelte"; |
7 | 11 | import ApiActivityIndicator from "$lib/components/ApiActivityIndicator.svelte"; |
8 | 12 | import { createLogger } from "$lib/utils/logger"; |
|
165 | 169 |
|
166 | 170 | // Some items in the menu are rendered conditionally based on the presence of URLs set in the environment variables. |
167 | 171 | // This is to ensure no broken links |
168 | | - let menuItems = $state([ |
| 172 | +
|
| 173 | + // Top menu items rendered before My Account |
| 174 | + let topMenuItems = $state([ |
169 | 175 | ...(data.externalLinks.API_EXPLORER_URL |
170 | 176 | ? [ |
171 | 177 | { |
|
186 | 192 | }, |
187 | 193 | ] |
188 | 194 | : []), |
| 195 | + ]); |
| 196 | +
|
| 197 | + // Menu items rendered after My Account |
| 198 | + let menuItems = $state([ |
189 | 199 | { |
190 | 200 | label: "Users", |
191 | 201 | href: "/users", |
|
268 | 278 | </Navigation.Header> |
269 | 279 |
|
270 | 280 | <Navigation.Content class=""> |
271 | | - <!-- Main Menu Group --> |
| 281 | + <!-- Top Menu: API Explorer, Portal --> |
| 282 | + <Navigation.Group> |
| 283 | + <Navigation.Menu class="flex flex-col gap-2 px-2"> |
| 284 | + {#each topMenuItems as item} |
| 285 | + {@const Icon = item.iconComponent} |
| 286 | + <a |
| 287 | + href={item.href} |
| 288 | + class="btn w-full justify-start gap-3 px-2 hover:preset-tonal" |
| 289 | + class:preset-filled-primary-50-950={page.url.pathname === |
| 290 | + item.href} |
| 291 | + class:border={page.url.pathname === item.href} |
| 292 | + class:border-solid-secondary-500={page.url.pathname === |
| 293 | + item.href} |
| 294 | + title={item.label} |
| 295 | + aria-label={item.label} |
| 296 | + target={item.external ? "_blank" : undefined} |
| 297 | + rel={item.external ? "noopener noreferrer" : undefined} |
| 298 | + > |
| 299 | + <Icon class="size-5" /> |
| 300 | + <span>{item.label}</span> |
| 301 | + </a> |
| 302 | + {/each} |
| 303 | + </Navigation.Menu> |
| 304 | + </Navigation.Group> |
| 305 | + |
| 306 | + <!-- My Account: right after Portal --> |
| 307 | + {#if isAuthenticated && myAccountSection} |
| 308 | + {@const SectionIcon = myAccountSection.iconComponent} |
| 309 | + {@const active = isSectionActive(myAccountSection)} |
| 310 | + <Navigation.Group> |
| 311 | + <button |
| 312 | + type="button" |
| 313 | + class="btn w-full justify-start gap-3 px-2 hover:preset-tonal" |
| 314 | + class:preset-filled-primary-50-950={active} |
| 315 | + class:border={active} |
| 316 | + class:border-solid-secondary-500={active} |
| 317 | + onclick={() => toggleSection(myAccountSection.id)} |
| 318 | + > |
| 319 | + <SectionIcon class="size-5" /> |
| 320 | + <span>{myAccountSection.label}</span> |
| 321 | + {#if expandedSections[myAccountSection.id]} |
| 322 | + <ChevronDown class="h-4 w-4" /> |
| 323 | + {:else} |
| 324 | + <ChevronRight class="h-4 w-4" /> |
| 325 | + {/if} |
| 326 | + </button> |
| 327 | + |
| 328 | + {#if expandedSections[myAccountSection.id]} |
| 329 | + <Navigation.Menu class="mt-1 ml-4 flex flex-col gap-1 px-2"> |
| 330 | + {#each myAccountSection.items as subItem} |
| 331 | + {@const SubIcon = subItem.iconComponent} |
| 332 | + <a |
| 333 | + href={subItem.href} |
| 334 | + class="btn w-full justify-start gap-3 px-2 pl-6 text-sm hover:preset-tonal" |
| 335 | + class:preset-filled-secondary-50-950={page.url.pathname === |
| 336 | + subItem.href} |
| 337 | + class:border-l-2={page.url.pathname === subItem.href} |
| 338 | + class:border-primary-500={page.url.pathname === |
| 339 | + subItem.href} |
| 340 | + title={subItem.label} |
| 341 | + aria-label={subItem.label} |
| 342 | + target={subItem.external ? "_blank" : undefined} |
| 343 | + rel={subItem.external ? "noopener noreferrer" : undefined} |
| 344 | + > |
| 345 | + <SubIcon class="size-4" /> |
| 346 | + <span>{subItem.label}</span> |
| 347 | + </a> |
| 348 | + {/each} |
| 349 | + </Navigation.Menu> |
| 350 | + {/if} |
| 351 | + </Navigation.Group> |
| 352 | + {/if} |
| 353 | + |
| 354 | + <!-- Other top-level items: Users, Consumers, etc. --> |
272 | 355 | <Navigation.Group> |
273 | 356 | <Navigation.Menu class="flex flex-col gap-2 px-2"> |
274 | 357 | {#each menuItems as item} |
|
0 commit comments