Skip to content

Commit 9714aa8

Browse files
V48 (implementation-only): Nav logo-area docs|whitepaper links; Read|Packs|Deposit order
Replace logo-area page-name subtext with docs (text) and whitepaper (icon) links, remove Docs from the primary nav, and reorder public product links to Read, Packs, Deposit.
1 parent ec4dd48 commit 9714aa8

8 files changed

Lines changed: 167 additions & 127 deletions

File tree

uapi/components/bitcode/layout/BitcodePublicCopy/bitcode-public-copy.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,11 @@ export const BITCODE_PUBLIC_COPY = {
113113
},
114114
},
115115
publicNav: {
116+
// Product order: Read → Packs → Deposit. Docs lives under the logo-area.
116117
links: [
118+
{ href: '/reads', label: 'Read' },
117119
{ href: '/packs', label: 'Packs' },
118-
{ href: '/deposits', label: 'Deposits' },
119-
{ href: '/reads', label: 'Reads' },
120-
{ href: '/docs', label: 'Docs' },
120+
{ href: '/deposits', label: 'Deposit' },
121121
],
122122
guestPrimaryCta: 'Open Auxillaries',
123123
guestSecondaryCta: 'Connect Wallet',

uapi/components/bitcode/layout/Nav/Nav.tsx

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -398,12 +398,12 @@ export default function Nav() {
398398
const isDepositRoute = href === '/deposits';
399399
const isReadRoute = href === '/reads';
400400
const isDisabledRoute = isPacksRoute && disableExchangeLink;
401-
const isActiveRoute =
402-
isPacksRoute
403-
? pathname === '/packs' || pathname?.startsWith('/packs/') || pathname === '/exchange' || pathname?.startsWith('/exchange/')
404-
: href === '/docs'
405-
? pathname === '/docs' || pathname?.startsWith('/docs/')
406-
: pathname === href || pathname?.startsWith(`${href}/`);
401+
const isActiveRoute = isPacksRoute
402+
? pathname === '/packs' ||
403+
pathname?.startsWith('/packs/') ||
404+
pathname === '/exchange' ||
405+
pathname?.startsWith('/exchange/')
406+
: pathname === href || pathname?.startsWith(`${href}/`);
407407

408408
return (
409409
<li
@@ -462,12 +462,6 @@ export default function Nav() {
462462
side="bottom"
463463
triggerClassName="h-4.5 w-4.5 border-white/10 bg-white/[0.03] text-[0.58rem] text-neutral-300 hover:border-emerald-300/30 hover:bg-emerald-400/10 hover:text-emerald-100"
464464
/>
465-
) : href === '/docs' ? (
466-
<BitcodeInlineExplainer
467-
explainer={BITCODE_PUBLIC_EXPLAINERS.docs}
468-
side="bottom"
469-
triggerClassName="h-4.5 w-4.5 border-white/10 bg-white/[0.03] text-[0.58rem] text-neutral-300 hover:border-emerald-300/30 hover:bg-emerald-400/10 hover:text-emerald-100"
470-
/>
471465
) : null}
472466
</span>
473467
</li>
Lines changed: 88 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,114 @@
11
"use client";
22

3+
/**
4+
* Nav brand mark + logo-area secondary links.
5+
*
6+
* Logo + "Bitcode" eyebrow navigate home. The former page-name subtext is
7+
* replaced by fixed public links: docs (spelled) | whitepaper (icon).
8+
*/
9+
310
import React from "react";
11+
import Link from "next/link";
12+
import { FileText } from "lucide-react";
413

514
import Logo from "@/components/bitcode/branding/Logo/Logo";
615

716
export type NavSurface = "packs" | "auxillaries" | "conversations" | null;
8-
export type NavBrandSurface = Exclude<NavSurface, null> | 'home' | 'network' | 'deposit' | 'read' | 'docs' | null;
17+
export type NavBrandSurface =
18+
| Exclude<NavSurface, null>
19+
| "home"
20+
| "network"
21+
| "deposit"
22+
| "read"
23+
| "docs"
24+
| "terminal"
25+
| null;
926

1027
interface NavBrandProps {
1128
animated?: boolean;
1229
visible?: boolean;
1330
onClick: () => void;
31+
/** Kept for route-aware callers; subtext is fixed docs | whitepaper links. */
1432
surface: NavBrandSurface;
1533
}
1634

17-
const SURFACE_COPY: Record<Exclude<NavBrandSurface, null>, { eyebrow: string; title: string }> = {
18-
home: {
19-
eyebrow: "Bitcode",
20-
title: "homepage",
21-
},
22-
terminal: {
23-
eyebrow: "Bitcode",
24-
title: "terminal",
25-
},
26-
network: {
27-
eyebrow: "Bitcode",
28-
title: "packs",
29-
},
30-
deposit: {
31-
eyebrow: "Bitcode",
32-
title: "deposit",
33-
},
34-
read: {
35-
eyebrow: "Bitcode",
36-
title: "read",
37-
},
38-
docs: {
39-
eyebrow: "Bitcode",
40-
title: "docs",
41-
},
42-
auxillaries: {
43-
eyebrow: "Bitcode",
44-
title: "auxillaries",
45-
},
46-
conversations: {
47-
eyebrow: "Bitcode",
48-
title: "conversations",
49-
},
50-
};
35+
/** Protocol lightpaper / whitepaper (source-bearing public reference). */
36+
export const BITCODE_WHITEPAPER_URL =
37+
process.env.NEXT_PUBLIC_BITCODE_WHITEPAPER_URL?.trim() ||
38+
"https://github.com/engineeredsoftware/ENGI/blob/main/BITCODE_LIGHTOPAPER.md";
39+
40+
const DOCS_HREF = "/docs";
5141

52-
export default function NavBrand({ animated = true, visible = true, onClick, surface }: NavBrandProps) {
53-
const surfaceCopy = surface ? SURFACE_COPY[surface] : null;
54-
const entranceClassName = animated ? 'nav-logo-animated' : visible ? 'opacity-100' : 'opacity-0';
42+
export default function NavBrand({
43+
animated = true,
44+
visible = true,
45+
onClick,
46+
surface,
47+
}: NavBrandProps) {
48+
const entranceClassName = animated
49+
? "nav-logo-animated"
50+
: visible
51+
? "opacity-100"
52+
: "opacity-0";
53+
const showWordmark = surface !== null;
5554

5655
return (
57-
<button
58-
type="button"
59-
onClick={onClick}
60-
className={`flex min-w-0 items-center gap-3 cursor-pointer appearance-none border-0 bg-transparent p-0 text-left ${entranceClassName}`}
56+
<div
57+
className={`flex min-w-0 items-center gap-3 ${entranceClassName}`}
58+
data-nav-brand-surface={surface ?? "null"}
6159
>
62-
<div
63-
className={
64-
surfaceCopy
65-
? "flex h-11 w-11 shrink-0 items-center justify-center rounded-[1.2rem] border border-emerald-400/18 bg-[linear-gradient(180deg,rgba(101,254,183,0.16),rgba(101,254,183,0.06))] shadow-[0_10px_24px_rgba(0,0,0,0.18)]"
66-
: ""
67-
}
60+
<button
61+
type="button"
62+
onClick={onClick}
63+
aria-label="Bitcode home"
64+
className="flex shrink-0 cursor-pointer appearance-none items-center border-0 bg-transparent p-0"
6865
>
69-
<Logo beta={!surfaceCopy} height="h-9" width="w-9" />
70-
</div>
71-
{surfaceCopy ? (
66+
<div
67+
className={
68+
showWordmark
69+
? "flex h-11 w-11 shrink-0 items-center justify-center rounded-[1.2rem] border border-emerald-400/18 bg-[linear-gradient(180deg,rgba(101,254,183,0.16),rgba(101,254,183,0.06))] shadow-[0_10px_24px_rgba(0,0,0,0.18)]"
70+
: ""
71+
}
72+
>
73+
<Logo beta={!showWordmark} height="h-9" width="w-9" />
74+
</div>
75+
</button>
76+
77+
{showWordmark ? (
7278
<div className="min-w-0">
73-
<p className="text-[0.58rem] uppercase tracking-[0.24em] text-emerald-300/80 sm:text-[0.62rem]">
74-
{surfaceCopy.eyebrow}
79+
<button
80+
type="button"
81+
onClick={onClick}
82+
className="cursor-pointer appearance-none border-0 bg-transparent p-0 text-left"
83+
>
84+
<p className="text-[0.58rem] uppercase tracking-[0.24em] text-emerald-300/80 sm:text-[0.62rem]">
85+
Bitcode
86+
</p>
87+
</button>
88+
<p className="mt-1 flex min-w-0 items-center gap-1.5 text-[0.84rem] text-neutral-200 sm:text-sm">
89+
<Link
90+
href={DOCS_HREF}
91+
className="truncate transition hover:text-emerald-200"
92+
aria-label="Docs"
93+
>
94+
docs
95+
</Link>
96+
<span className="select-none text-neutral-500" aria-hidden="true">
97+
|
98+
</span>
99+
<a
100+
href={BITCODE_WHITEPAPER_URL}
101+
target="_blank"
102+
rel="noopener noreferrer"
103+
aria-label="Whitepaper"
104+
title="Whitepaper"
105+
className="inline-flex shrink-0 items-center text-neutral-300 transition hover:text-emerald-200"
106+
>
107+
<FileText className="h-3.5 w-3.5" aria-hidden="true" />
108+
</a>
75109
</p>
76-
<p className="mt-1 truncate text-[0.84rem] text-neutral-200 sm:text-sm">{surfaceCopy.title}</p>
77110
</div>
78111
) : null}
79-
</button>
112+
</div>
80113
);
81114
}

uapi/tests/e2e/commercial-mvp.responsive.spec.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,9 @@ test.describe('commercial MVP responsive route health', () => {
6363
await page.setViewportSize({ width: 1024, height: 768 });
6464
await openCommercialRoute(page, '/terminal', /The Bitcode Terminal is where operators prepare Deposit and Read work/i);
6565

66-
await expect(page.getByRole('link', { name: /^Terminal$/ })).toBeVisible();
66+
await expect(page.getByRole('link', { name: /^Read$/ })).toBeVisible();
67+
await expect(page.getByRole('link', { name: /^Packs$/ })).toBeVisible();
68+
await expect(page.getByRole('link', { name: /^Deposit$/ })).toBeVisible();
6769
await expect(page.getByRole('link', { name: /^Docs$/ })).toBeVisible();
6870
await expect(page.getByLabel(/Open BTD wallet auxillary/i)).toBeVisible();
6971

uapi/tests/e2e/commercial-mvp.routes.spec.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ test.describe('commercial MVP route surfaces', () => {
125125
});
126126
}
127127

128-
test('public navigation keeps Terminal and Docs as first-class commercial routes', async ({
128+
test('public navigation keeps Read, Packs, Deposit, and logo-area docs as commercial routes', async ({
129129
page,
130130
}, testInfo) => {
131131
const trap = installCommercialBrowserErrorTrap(page, testInfo);
@@ -136,11 +136,17 @@ test.describe('commercial MVP route surfaces', () => {
136136
/Bitcode is auditable market infrastructure for technical knowledge/i,
137137
);
138138

139-
await page.locator('a[href="/packs"]').first().click();
140-
await expect(page).toHaveURL(/\/terminal$/);
141-
await expectCommercialRouteReady(page, /The Bitcode Terminal is where operators prepare Deposit and Read work/i);
139+
// Product order: Read | Packs | Deposit; docs lives under the logo-area.
140+
await page.getByRole('link', { name: 'Read' }).first().click();
141+
await expect(page).toHaveURL(/\/reads/);
142142

143-
await page.locator('a[href="/docs"]').first().click();
143+
await page.getByRole('link', { name: 'Packs' }).first().click();
144+
await expect(page).toHaveURL(/\/packs/);
145+
146+
await page.getByRole('link', { name: 'Deposit' }).first().click();
147+
await expect(page).toHaveURL(/\/deposits/);
148+
149+
await page.getByRole('link', { name: 'Docs' }).first().click();
144150
await expect(page).toHaveURL(/\/docs$/);
145151
await expectCommercialRouteReady(page, /Learn Bitcode from AssetPacks to proof/i);
146152

uapi/tests/navBrand.test.tsx

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,39 @@
11
import React from 'react';
2+
import '@testing-library/jest-dom';
23
import { fireEvent, render, screen } from '@testing-library/react';
34

4-
import NavBrand from '@/components/bitcode/layout/NavBrand/NavBrand';
5+
import NavBrand, {
6+
BITCODE_WHITEPAPER_URL,
7+
} from '@/components/bitcode/layout/NavBrand/NavBrand';
58

69
describe('NavBrand', () => {
7-
it('renders product-surface copy for the terminal workspace', () => {
8-
render(<NavBrand surface="terminal" onClick={() => {}} />);
9-
10-
expect(screen.getByLabelText('Bitcode logo')).toBeTruthy();
11-
expect(screen.getByText('Bitcode')).toBeTruthy();
12-
expect(screen.getByText('terminal')).toBeTruthy();
13-
});
14-
15-
it('renders packs copy for mounted pack activity routes', () => {
16-
render(<NavBrand surface="network" onClick={() => {}} />);
17-
18-
expect(screen.getByLabelText('Bitcode logo')).toBeTruthy();
19-
expect(screen.getByText('Bitcode')).toBeTruthy();
20-
expect(screen.getByText('packs')).toBeTruthy();
21-
});
22-
23-
it('renders homepage copy for the public homepage', () => {
10+
it('renders logo-area docs and whitepaper links instead of page-name subtext', () => {
2411
render(<NavBrand surface="home" onClick={() => {}} />);
2512

2613
expect(screen.getByLabelText('Bitcode logo')).toBeTruthy();
2714
expect(screen.getByText('Bitcode')).toBeTruthy();
28-
expect(screen.getByText('homepage')).toBeTruthy();
15+
expect(screen.queryByText('homepage')).toBeNull();
16+
expect(screen.getByRole('link', { name: 'Docs' })).toHaveAttribute('href', '/docs');
17+
expect(screen.getByRole('link', { name: 'Whitepaper' })).toHaveAttribute(
18+
'href',
19+
BITCODE_WHITEPAPER_URL,
20+
);
21+
expect(screen.getByRole('link', { name: 'Whitepaper' })).toHaveAttribute('target', '_blank');
2922
});
3023

31-
it('renders docs copy for mounted docs routes', () => {
32-
render(<NavBrand surface="docs" onClick={() => {}} />);
24+
it('keeps docs | whitepaper links on product surfaces (no page-name subtext)', () => {
25+
render(<NavBrand surface="deposit" onClick={() => {}} />);
3326

34-
expect(screen.getByLabelText('Bitcode logo')).toBeTruthy();
35-
expect(screen.getByText('Bitcode')).toBeTruthy();
36-
expect(screen.getByText('docs')).toBeTruthy();
27+
expect(screen.queryByText('deposit')).toBeNull();
28+
expect(screen.getByRole('link', { name: 'Docs' })).toHaveAttribute('href', '/docs');
29+
expect(screen.getByRole('link', { name: 'Whitepaper' })).toBeInTheDocument();
3730
});
3831

39-
it('renders auxillaries copy for mounted auxiliary routes', () => {
40-
render(<NavBrand surface="auxillaries" onClick={() => {}} />);
32+
it('keeps docs | whitepaper links on docs routes', () => {
33+
render(<NavBrand surface="docs" onClick={() => {}} />);
4134

42-
expect(screen.getByLabelText('Bitcode logo')).toBeTruthy();
43-
expect(screen.getByText('Bitcode')).toBeTruthy();
44-
expect(screen.getByText('auxillaries')).toBeTruthy();
35+
expect(screen.queryByText(/^docs$/i)).toBeTruthy(); // the spelled docs link
36+
expect(screen.getByRole('link', { name: 'Docs' })).toHaveAttribute('href', '/docs');
4537
});
4638

4739
it('renders beta posture outside the product workspace and remains clickable', () => {
@@ -54,5 +46,15 @@ describe('NavBrand', () => {
5446
expect(screen.getByText('V26')).toBeTruthy();
5547
expect(screen.getByText('PRC')).toBeTruthy();
5648
expect(onClick).toHaveBeenCalled();
49+
expect(screen.queryByRole('link', { name: 'Docs' })).toBeNull();
50+
});
51+
52+
it('home control remains clickable via the brand mark', () => {
53+
const onClick = jest.fn();
54+
55+
render(<NavBrand surface="network" onClick={onClick} />);
56+
57+
fireEvent.click(screen.getByRole('button', { name: 'Bitcode home' }));
58+
expect(onClick).toHaveBeenCalled();
5759
});
5860
});

0 commit comments

Comments
 (0)