Skip to content

Commit 849a855

Browse files
authored
feat: add Stand Out to the shared header (#171)
1 parent 350d650 commit 849a855

4 files changed

Lines changed: 63 additions & 2 deletions

File tree

ctw.studio/design-system/components.css

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@
170170
background: color-mix(in srgb, var(--ctw-color-text) 8%, transparent);
171171
}
172172

173+
.ctw-masthead--studio .ctw-primary-nav__link--stand-out {
174+
flex-shrink: 0;
175+
white-space: nowrap;
176+
}
177+
173178
.ctw-masthead--studio .ctw-primary-nav__link[aria-current] {
174179
background: color-mix(in srgb, var(--ctw-color-action) 12%, transparent);
175180
color: var(--ctw-color-action);
@@ -432,6 +437,21 @@
432437
}
433438
}
434439

440+
@media (max-width: 22rem) {
441+
.ctw-masthead--studio .ctw-liquid-contact__plus {
442+
display: none;
443+
}
444+
445+
.ctw-masthead--studio .ctw-liquid-contact__label {
446+
font-size: 0;
447+
}
448+
449+
.ctw-masthead--studio .ctw-liquid-contact__label::after {
450+
content: "Talk";
451+
font-size: 0.7rem;
452+
}
453+
}
454+
435455
.ctw-container {
436456
width: min(100% - 2rem, var(--ctw-size-container));
437457
margin-inline: auto;

ctw.studio/src/components/SiteHeader.astro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const { current } = Astro.props;
1717
<a class="ctw-primary-nav__link" href="/portfolio/" aria-current={current === 'portfolio' ? 'page' : undefined}>Work</a>
1818
<a class="ctw-primary-nav__link" href="/writing/" aria-current={current === 'writing' ? 'page' : undefined}>Writing</a>
1919
<a class="ctw-primary-nav__link" href="/signals/" aria-current={current === 'signals' ? 'page' : undefined}>Signals</a>
20+
<a class="ctw-primary-nav__link ctw-primary-nav__link--stand-out" href="/stand-out/" aria-label="Stand Out">Stand Out</a>
2021
<a
2122
class="ctw-primary-nav__link ctw-liquid-contact"
2223
href="/#about"

ctw.studio/tests/e2e/liquid-contact.spec.mjs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ test('shared header exposes one native Contact link with decorative liquid layer
2121
await expect(contact.locator('.ctw-liquid-contact__plus')).toHaveAttribute('aria-hidden', 'true');
2222
await expect(contact.locator('.ctw-liquid-contact__label')).toHaveText('Contact');
2323
await expect(contact.locator('canvas')).toHaveCount(0);
24+
25+
const standOut = page.getByRole('navigation', { name: 'Primary navigation' })
26+
.getByRole('link', { name: 'Stand Out', exact: true });
27+
await expect(standOut).toHaveCount(1);
28+
await expect(standOut).toHaveAttribute('href', '/stand-out/');
2429
}
2530

2631
await page.goto('/portfolio/');
@@ -31,6 +36,15 @@ test('shared header exposes one native Contact link with decorative liquid layer
3136
await expect(page.locator('#about')).toBeInViewport();
3237
});
3338

39+
test('shared header Stand Out link opens the canonical landing page', async ({ page }) => {
40+
await page.goto('/');
41+
await page.getByRole('navigation', { name: 'Primary navigation' })
42+
.getByRole('link', { name: 'Stand Out', exact: true })
43+
.click();
44+
await expect(page).toHaveURL(/\/stand-out\/$/);
45+
await expect(page).toHaveTitle('Stand Out — Bring your real business online');
46+
});
47+
3448
test('fine pointer tracks metal position and clears active state on leave', async ({ page }) => {
3549
await page.setViewportSize({ width: 1440, height: 900 });
3650
await page.goto('/');
@@ -287,10 +301,35 @@ for (const width of [390, 320]) {
287301
expect(box?.width ?? 0).toBeGreaterThanOrEqual(43.99);
288302
expect(box?.height ?? 0).toBeGreaterThanOrEqual(43.99);
289303
expect(await contact.locator('.ctw-liquid-contact__label').evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
304+
const contactCopy = await contact.locator('.ctw-liquid-contact__label').evaluate((element) => ({
305+
fontSize: Number.parseFloat(getComputedStyle(element).fontSize),
306+
compactContent: getComputedStyle(element, '::after').content
307+
}));
308+
if (width === 320) {
309+
expect(contactCopy.fontSize).toBe(0);
310+
expect(contactCopy.compactContent).toBe('"Talk"');
311+
} else {
312+
expect(contactCopy.fontSize).toBeGreaterThan(0);
313+
expect(contactCopy.compactContent).toBe('none');
314+
}
290315
const navigationLabels = await page.getByRole('navigation', { name: 'Primary navigation' })
291316
.getByRole('link')
292317
.evaluateAll((links) => links.map((link) => link.getAttribute('aria-label') ?? link.textContent.trim()));
293-
expect(navigationLabels).toEqual(['Work', 'Writing', 'Signals', 'Contact']);
318+
expect(navigationLabels).toEqual(['Work', 'Writing', 'Signals', 'Stand Out', 'Contact']);
319+
const navigationBoxes = await page.getByRole('navigation', { name: 'Primary navigation' })
320+
.getByRole('link')
321+
.evaluateAll((links) => links.map((link) => {
322+
const box = link.getBoundingClientRect();
323+
return { name: link.getAttribute('aria-label') ?? link.textContent.trim(), width: box.width, height: box.height };
324+
}));
325+
for (const target of navigationBoxes) {
326+
expect(target.width, target.name).toBeGreaterThanOrEqual(43.99);
327+
expect(target.height, target.name).toBeGreaterThanOrEqual(43.99);
328+
}
329+
const standOut = page.getByRole('navigation', { name: 'Primary navigation' })
330+
.getByRole('link', { name: 'Stand Out', exact: true });
331+
await expect(standOut).toHaveCSS('white-space', 'nowrap');
332+
expect(await standOut.evaluate((element) => element.scrollWidth <= element.clientWidth)).toBe(true);
294333
await context.close();
295334
});
296335
}

ctw.studio/tests/identity.test.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ test('header presents Jesse identity and exact primary navigation while retainin
1111
assert.match(source, />Jesse Gonzalez</);
1212
const nav = source.slice(source.indexOf('<nav class="ctw-primary-nav"'), source.indexOf('</nav>'));
1313
assert.deepEqual([...nav.matchAll(/href="([^"]+)"/g)].map((match) => match[1]), [
14-
'/portfolio/', '/writing/', '/signals/', '/#about'
14+
'/portfolio/', '/writing/', '/signals/', '/stand-out/', '/#about'
1515
]);
16+
assert.match(nav, /href="\/stand-out\/"[^>]*aria-label="Stand Out"/);
1617
assert.doesNotMatch(nav, /AI Workshop|\/workshop\//);
1718
for (const sentinel of [
1819
'ctw-liquid-contact', 'data-liquid-contact', 'data-liquid-mode="static"',

0 commit comments

Comments
 (0)