From 3aab28b7a9e461d5b331eaeb20eb84bd0af7d85d Mon Sep 17 00:00:00 2001 From: Brian Love Date: Sat, 29 Aug 2026 12:59:28 -0700 Subject: [PATCH 1/4] refactor(website): move Footer chrome to chrome.css, hover handlers become :hover Move Footer.tsx's static presentation (root background/border, tagline, newsletter success/input, column eyebrows, social icons, link colors, bottom bar) into chrome.css as .footer-* classes. Replace all 23 onMouseEnter/onMouseLeave color-toggle pairs with :hover rules; one .footer-link class covers the 19 identical column-link styles and one .footer-social-link covers the two icon links. Footer keeps 'use client' (NewsletterForm has real submit state). --- apps/website/src/components/shared/Footer.tsx | 164 ++++++------------ apps/website/src/styles/chrome.css | 52 ++++++ 2 files changed, 103 insertions(+), 113 deletions(-) diff --git a/apps/website/src/components/shared/Footer.tsx b/apps/website/src/components/shared/Footer.tsx index 2ba7567e1..658022dbf 100644 --- a/apps/website/src/components/shared/Footer.tsx +++ b/apps/website/src/components/shared/Footer.tsx @@ -1,7 +1,6 @@ 'use client'; import { useState } from 'react'; import Link from 'next/link'; -import { tokens } from '@threadplane/design-tokens'; import { analyticsEvents } from '../../lib/analytics/events'; import { track, trackCtaClick, trackExternalLinkClick } from '../../lib/analytics/client'; import { SHORT_POSITIONING_DESCRIPTION } from '../../lib/positioning'; @@ -62,7 +61,7 @@ function NewsletterForm() { }; if (state === 'done') { - return

✓ You're subscribed!

; + return

✓ You're subscribed!

; } return ( @@ -77,13 +76,7 @@ function NewsletterForm() { onChange={e => setEmail(e.target.value)} required disabled={state === 'submitting'} - className="text-sm rounded-lg px-3 py-2 flex-1 min-w-0" - style={{ - background: tokens.surfaces.surface, - border: `1px solid ${tokens.surfaces.border}`, - color: tokens.colors.textPrimary, - outline: 'none', - }} + className="text-sm rounded-lg px-3 py-2 flex-1 min-w-0 footer-newsletter-input" /> {open && ( -
+
{DEMOS.map((demo) => ( { setOpen(false); trackExternalLinkClick(demo.href, { surface: 'nav', cta_id: `nav_demo_${demoCtaSuffix(demo.key)}`, cta_text: demo.label }); }} - className="text-sm font-mono" - style={{ display: 'block', padding: '10px 14px', color: tokens.colors.textSecondary, textDecoration: 'none' }} - onMouseEnter={(e) => (e.currentTarget.style.color = tokens.colors.accent)} - onMouseLeave={(e) => (e.currentTarget.style.color = tokens.colors.textSecondary)}> + className="text-sm font-mono nav-demo-item"> {demo.label} ))} @@ -117,25 +111,6 @@ export function Nav() { }); }; - const tabStyle = (active: boolean): React.CSSProperties => ({ - flex: 1, textAlign: 'center', padding: '10px 0', - fontSize: 15, fontWeight: 500, fontFamily: 'Inter, sans-serif', - background: active ? tokens.colors.accentSurface : 'transparent', - color: active ? tokens.colors.accent : tokens.colors.textMuted, - border: 'none', borderRadius: 8, cursor: 'pointer', - minHeight: 44, - }); - - const subTabStyle = (active: boolean): React.CSSProperties => ({ - flex: 1, textAlign: 'center', padding: '8px 0', - fontFamily: 'var(--font-mono,"JetBrains Mono",monospace)', - fontSize: '0.75rem', fontWeight: 600, - background: active ? tokens.colors.accentSurface : 'transparent', - color: active ? tokens.colors.accent : tokens.colors.textMuted, - border: 'none', borderRadius: 6, cursor: 'pointer', - minHeight: 36, - }); - const currentLib = docsConfig.find(lib => lib.id === mobileLibrary); const trackNavLink = (label: string, href: string, external: boolean, surface: 'nav' | 'mobile_nav') => { const slug = label.toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_|_$/g, ''); @@ -150,17 +125,10 @@ export function Nav() { return ( <> -