/* Bluehaus — shared components: Nav, Footer, Logo, Marquee, ProjectCard, Lightbox, etc. */
const { useState, useEffect, useRef } = React;
// ---------- LOGO ----------
function Logo({ size = 28 }) {
// Small wordmark logo lock-up. The brand is in transition; we render text mark + sub-line
// (per brief — confirm final post-merger lock-up). Avoids reproducing the upload SVG colours.
return (
);
}
// ---------- NAV ----------
function Nav({ route, navigate, dark = false }) {
const [scrolled, setScrolled] = useState(false);
const [drawer, setDrawer] = useState(false);
useEffect(() => {
const onScroll = () => setScrolled(window.scrollY > 8);
window.addEventListener('scroll', onScroll);
return () => window.removeEventListener('scroll', onScroll);
}, []);
const links = [
{ href: 'projects', label: 'Projects' },
{ href: 'sectors', label: 'Sectors' },
{ href: 'services', label: 'Services' },
{ href: 'about', label: 'Studio' },
{ href: 'awards', label: 'Awards' },
{ href: 'contact', label: 'Contact' },
];
const onLink = (e, href) => {
e.preventDefault();
setDrawer(false);
navigate(href);
};
return (
<>
{drawer && (
)}
>
);
}
// ---------- FOOTER ----------
function Footer({ navigate }) {
return (
);
}
// ---------- MARQUEE ----------
function Marquee({ items }) {
const list = [...items, ...items, ...items];
return (
{list.map((t, i) => (
{t.it ? {t.text} : t.text}
{' '}·
))}
);
}
// ---------- PROJECT CARD ----------
function ProjectCard({ project, variant, navigate }) {
return (
{ e.preventDefault(); navigate('projects/' + project.slug); window.scrollTo(0, 0); }}>
{project.name}
{project.location.split(',').pop().trim()} · {project.year}
{project.tagline}
);
}
// ---------- SECTION HEADER ----------
function SectionHead({ label, title, action, children }) {
return (
{label &&
{label}
}
{title}{children}
{action}
);
}
// ---------- LIGHTBOX ----------
function Lightbox({ src, alt, onClose }) {
useEffect(() => {
const onKey = (e) => { if (e.key === 'Escape') onClose(); };
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, [onClose]);
return (
Close ✕
);
}
// Expose globally
Object.assign(window, { Logo, Nav, Footer, Marquee, ProjectCard, SectionHead, Lightbox });