// Cases — Highlite Inc. の公式実績(https://highlite.co.jp/work/)を一覧表示。 // 各行は当該案件の公式ページへ、写真は同社公式サイトの実写真を自社ホストして使用。 const { useState: useStateCase, useRef: useRefCase, useEffect: useEffectCase } = React; function Cases() { const [hover, setHover] = useStateCase(null); const [pos, setPos] = useStateCase({ x: 0, y: 0 }); const cases = window.BRANDRI_CASES; useEffectCase(() => { const move = (e) => setPos({ x: e.clientX, y: e.clientY }); window.addEventListener("mousemove", move); return () => window.removeEventListener("mousemove", move); }, []); // clamp preview within viewport const previewStyle = (() => { if (!hover) return { opacity: 0 }; const w = 300, h = 380; const pad = 24; let x = pos.x + 220; // offset to the right let y = pos.y; if (x + w/2 > window.innerWidth - pad) x = window.innerWidth - pad - w/2; if (x - w/2 < pad) x = pad + w/2; if (y - h/2 < pad + 80) y = pad + 80 + h/2; if (y + h/2 > window.innerHeight - pad) y = window.innerHeight - pad - h/2; return { left: x + "px", top: y + "px" }; })(); return ( <>
{cases.map((c, i) => ( setHover(c)} onMouseLeave={() => setHover(null)} >
{c.cat} {c.client}
— {c.title}
{c.year}
{c.excerpt && (
▸ Overview

{c.excerpt}

)}
))}
{hover && ( <>
Case № {hover.num} {hover.year}
{hover.cat}
{hover.client} — {hover.title.slice(0, 20)}{hover.title.length > 20 ? "…" : ""}
{hover.excerpt}
)}
); } ReactDOM.createRoot(document.getElementById("cases-app")).render();