// Components.jsx — shared primitives for 1snob umbrella site const { useState, useEffect, useMemo } = React; // ---------- Copy dictionary (EN / FR) ---------- const COPY = { nav: { home: { en: 'Index', fr: 'Index' }, work: { en: 'Work', fr: 'Travail' }, about: { en: 'About', fr: 'À propos' }, contact: { en: 'Contact', fr: 'Contact' }, }, footer: { cta: { en: 'Hire a snob.', fr: 'Engagez un snob.' }, note: { en: 'Based in Montréal. Working worldwide.', fr: 'Basé à Montréal. Partout, autrement.' }, email: { en: 'hi@1snob.com', fr: 'hi@1snob.com' }, rights: { en: '© 2025 1snob. All rights reserved.', fr: '© 2025 1snob. Tous droits réservés.' }, est: { en: 'Est. 2024 — Montréal', fr: 'Depuis 2024 — Montréal' }, }, }; // ---------- Logo ---------- const Logo = ({ size = 32, color = 'var(--ink-1)', onClick }) => ( SNOB ); // ---------- Rainbow bar ---------- const RainbowBar = ({ thick = false }) => (
); // ---------- Lang toggle ---------- const LangToggle = ({ lang, setLang }) => (
); // ---------- Header ---------- const Header = ({ route, go, lang, setLang }) => { const L = (k) => COPY.nav[k][lang]; const item = (id) => ( { e.preventDefault(); go(id); }} >{L(id)} ); return (
{ e.preventDefault(); go('home'); }} />
); }; // ---------- Footer ---------- const Footer = ({ lang, go }) => { const F = COPY.footer; return ( ); }; // ---------- Button ---------- const Btn = ({ children, href, onClick, ghost, arrow = true }) => { const Comp = href ? 'a' : 'button'; return ( {children}{arrow && } ); }; // ---------- Section wrapper ---------- const Section = ({ eyebrow, children, dark, noBorder, style }) => (
{eyebrow && (
{eyebrow}
)} {children}
); // ---------- useHashRoute ---------- const useHashRoute = () => { const parse = () => (location.hash.replace(/^#\/?/, '') || 'home').split('/')[0] || 'home'; const [route, setRoute] = useState(parse()); useEffect(() => { const on = () => setRoute(parse()); window.addEventListener('hashchange', on); return () => window.removeEventListener('hashchange', on); }, []); const go = (id) => { location.hash = '#/' + (id === 'home' ? '' : id); window.scrollTo({ top: 0, behavior: 'instant' }); }; return [route, go]; }; // ---------- Export to window ---------- Object.assign(window, { COPY, Logo, RainbowBar, LangToggle, Header, Footer, Btn, Section, useHashRoute });