Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 13x 13x | /**
* The one list of app-navigation destinations.
*
* Four surfaces render app nav: the hamburger drawer and the desktop dropdown
* (both inside `AppNavBar`), the handful of always-visible links in that same
* bar, and the standalone `FloatingHamburgerMenu` used on distraction-free
* pages. Before this file each kept its own hardcoded array, and they had
* already drifted — the floating menu showed 🏠/🎯 where the drawer showed
* 🧮/📚 for the very same two routes.
*
* Surfaces may now differ in *which* items they show and nothing else: a
* route's href, emoji, and label come from here for everyone.
*
* Deliberately free of JSX and styled-system imports so a server component, or
* a test that walks the filesystem looking for the route on disk, can import
* it. The Panda classes that implement `desktopFrom` live in `AppNavBar.tsx`,
* because Panda can only extract responsive keys it can see statically.
*/
/** Where a nav item can appear. */
export type NavSurface =
/** The full-screen mobile drawer inside `AppNavBar`. */
| 'drawer'
/** The desktop dropdown inside `AppNavBar`. */
| 'dropdown'
/** The always-visible links in the desktop bar (space-constrained). */
| 'desktop'
/** The standalone `FloatingHamburgerMenu` on distraction-free pages. */
| 'floating'
/**
* The breakpoint at which a desktop-bar link becomes visible. The bar reveals
* links progressively as the viewport widens, so each item declares its own
* threshold rather than the bar hardcoding four `<div>` wrappers.
*/
export type NavDesktopBreakpoint = 'sm' | 'md' | 'lg' | 'xl'
export interface NavItem {
href: string
/** Key under the `common.nav` namespace. */
labelKey: string
/**
* English label. Not a fallback the app renders — `navItems.test.ts` asserts
* it equals `en.common.nav[labelKey]`, which is what stops the config and the
* locale files from drifting apart silently.
*/
label: string
emoji: string
/** Present iff `surfaces` includes `'desktop'`. */
desktopFrom?: NavDesktopBreakpoint
surfaces: readonly NavSurface[]
}
const ALL_MENUS = ['drawer', 'dropdown'] as const
/**
* Canonical order. Every surface renders its items in this order, which is how
* the drawer, the dropdown, the desktop bar, and the floating menu stay in
* agreement about what comes first.
*/
export const NAV_ITEMS: readonly NavItem[] = [
{
href: '/',
labelKey: 'home',
label: 'Home',
emoji: '🧮',
surfaces: [...ALL_MENUS, 'floating'],
},
{
href: '/create',
labelKey: 'create',
label: 'Create',
emoji: '✏️',
desktopFrom: 'sm',
surfaces: [...ALL_MENUS, 'desktop', 'floating'],
},
{
href: '/practice',
labelKey: 'practice',
label: 'Practice',
emoji: '📚',
desktopFrom: 'md',
surfaces: [...ALL_MENUS, 'desktop', 'floating'],
},
{
href: '/my-stuff',
labelKey: 'myStuff',
label: 'My Stuff',
emoji: '⭐',
surfaces: ALL_MENUS,
},
{
href: '/flowchart',
labelKey: 'flowcharts',
label: 'Flowcharts',
emoji: '🗺️',
surfaces: [...ALL_MENUS, 'floating'],
},
{
href: '/games',
labelKey: 'games',
label: 'Games',
emoji: '🎮',
desktopFrom: 'lg',
surfaces: [...ALL_MENUS, 'desktop', 'floating'],
},
{
href: '/toys',
labelKey: 'toys',
label: 'Toys',
emoji: '🧸',
surfaces: ALL_MENUS,
},
{
href: '/guide',
labelKey: 'guide',
label: 'Guide',
emoji: '📖',
surfaces: ALL_MENUS,
},
{
href: '/blog',
labelKey: 'blog',
label: 'Blog',
emoji: '📝',
desktopFrom: 'xl',
surfaces: [...ALL_MENUS, 'desktop'],
},
] as const
/** The items one surface shows, in canonical order. */
export function navItemsFor(surface: NavSurface): NavItem[] {
return NAV_ITEMS.filter((item) => item.surfaces.includes(surface))
}
|