Components
A dark-themed, interactive landing page component. It features dynamic parallax mouse tracking, custom CSS geometry animations, a machined grid background, and a fully responsive layout.
Loading preview...
import React, { useState, useRef } from 'react';
export default function ThermalRoasting() {
const containerRef = useRef<HTMLDivElement>(null);
const [mousePos, setMousePos] = useState({ x: 0.5, y: 0.5 });
const [isHovering, setIsHovering] = useState(false);
const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {
if (!containerRef.current) return;
const { left, top, width, height } = containerRef.current.getBoundingClientRect();
const x = (e.clientX - left) / width;
const y = (e.clientY - top) / height;
setMousePos({ x, y });
setIsHovering(true);
};
const handleMouseLeave = () => {
setIsHovering(false);
setMousePos({ x: 0.5, y: 0.5 }); // Reset to center
};
// Calculates the dynamic parallax shift for each thermal layer
const getLayerStyle = (index: number) => {
if (!isHovering) return { transform: 'translate(0, 0)', transition: 'transform 0.3s ease' };
const shift = (index + 1) * 10;
return {
transform: `translate(${(mousePos.x - 0.5) * shift}px, ${(mousePos.y - 0.5) * shift}px)`,
transition: 'none' // Remove transition during hover for instant tracking
};
};
return (
<div className="thermal-app-container">
<style>{`
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700;900&family=Space+Mono:wght@400;700&display=swap');
.thermal-app-container {
--obsidian: #080808;
--steel: #242424;
--machined: #a1a1a1;
--thermal-core: #ff3c00;
--thermal-glow: rgba(255, 60, 0, 0.4);
--thermal-mid: #ff9100;
--grid-line: rgba(255, 255, 255, 0.05);
--transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1);
background-color: var(--obsidian);
color: #fff;
font-family: 'Inter', sans-serif;
min-height: 100vh;
overflow-x: hidden;
line-height: 1.4;
position: relative;
}
.thermal-app-container * {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Machined Grid Background */
.thermal-grid {
position: absolute;
inset: 0;
background-image:
linear-gradient(var(--grid-line) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
background-size: 40px 40px;
z-index: 0;
pointer-events: none;
}
.thermal-grid::after {
content: '';
position: absolute;
inset: 0;
background: radial-gradient(circle at 50% 50%, transparent 0%, var(--obsidian) 80%);
}
/* Layout Structure */
.wrapper {
max-width: 1400px;
margin: 0 auto;
padding: 0 40px;
position: relative;
z-index: 1;
}
nav {
display: flex;
justify-content: space-between;
align-items: center;
height: 100px;
border-bottom: 1px solid var(--steel);
font-family: 'Space Mono', monospace;
text-transform: uppercase;
letter-spacing: 2px;
font-size: 12px;
}
.logo {
font-weight: 900;
font-size: 24px;
display: flex;
align-items: center;
gap: 10px;
}
.logo-icon {
width: 20px;
height: 20px;
background: var(--thermal-core);
clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
animation: pulse 2s infinite ease-in-out;
}
/* Hero Section */
.hero {
display: grid;
grid-template-columns: 1.2fr 0.8fr;
min-height: calc(100vh - 100px);
align-items: center;
gap: 60px;
padding: 60px 0;
}
.hero-content h1 {
font-size: clamp(60px, 8vw, 120px);
font-weight: 900;
line-height: 0.9;
text-transform: uppercase;
margin-bottom: 40px;
letter-spacing: -4px;
}
.hero-content h1 span {
display: block;
color: var(--obsidian);
-webkit-text-stroke: 1px var(--machined);
}
.thermal-signature {
position: relative;
aspect-ratio: 1;
background: var(--steel);
border: 1px solid var(--machined);
padding: 2px;
clip-path: polygon(0 0, 90% 0, 100% 10%, 100% 100%, 10% 100%, 0 90%);
overflow: hidden;
box-shadow: 0 0 50px rgba(0,0,0,0.5);
}
.thermal-viz {
width: 100%;
height: 100%;
background: #111;
position: relative;
display: grid;
place-items: center;
}
/* CSS Thermal Geometry Visualization */
.viz-object {
position: relative;
width: 300px;
height: 300px;
filter: blur(20px);
animation: rotate 20s infinite linear;
}
.viz-layer {
position: absolute;
inset: 0;
border-radius: 40% 60% 70% 30% / 40% 50% 60% 70%;
mix-blend-mode: screen;
}
.layer-1 { background: var(--thermal-core); opacity: 0.8; animation: morph 8s infinite alternate; }
.layer-2 { background: var(--thermal-mid); opacity: 0.6; animation: morph 12s infinite alternate-reverse; }
.layer-3 { background: #fff; opacity: 0.3; transform: scale(0.8); }
.viz-specs {
position: absolute;
bottom: 20px;
left: 20px;
font-family: 'Space Mono', monospace;
font-size: 10px;
color: var(--machined);
pointer-events: none;
}
.viz-specs span {
display: block;
margin-bottom: 4px;
color: var(--thermal-mid);
}
/* UI Elements */
.cta-group {
display: flex;
gap: 20px;
}
.btn {
padding: 20px 40px;
font-family: 'Space Mono', monospace;
font-weight: bold;
text-transform: uppercase;
cursor: pointer;
transition: var(--transition);
position: relative;
border: none;
overflow: hidden;
}
.btn-primary {
background: var(--thermal-core);
color: #fff;
clip-path: polygon(0 0, 100% 0, 100% 70%, 85% 100%, 0 100%);
}
.btn-primary:hover {
background: #fff;
color: var(--obsidian);
transform: translateY(-5px);
box-shadow: 0 10px 30px var(--thermal-glow);
}
.btn-secondary {
background: transparent;
color: var(--machined);
border: 1px solid var(--steel);
clip-path: polygon(15% 0, 100% 0, 100% 100%, 0 100%, 0 30%);
}
.btn-secondary:hover {
border-color: var(--machined);
color: #fff;
}
/* Feature Section */
.features {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--steel);
border: 1px solid var(--steel);
margin-bottom: 100px;
}
.feature-item {
background: var(--obsidian);
padding: 60px 40px;
position: relative;
transition: var(--transition);
}
.feature-item:hover {
background: #0c0c0c;
}
.feature-item::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 4px;
height: 0;
background: var(--thermal-core);
transition: var(--transition);
}
.feature-item:hover::before {
height: 100%;
}
.feature-label {
font-family: 'Space Mono', monospace;
font-size: 10px;
color: var(--thermal-core);
margin-bottom: 20px;
display: block;
}
.feature-item h3 {
font-size: 24px;
text-transform: uppercase;
margin-bottom: 15px;
letter-spacing: -1px;
}
.feature-item p {
color: var(--machined);
font-size: 14px;
line-height: 1.6;
}
/* Scanned Data Overlay */
.data-overlay {
position: absolute;
top: 40px;
right: 40px;
text-align: right;
font-family: 'Space Mono', monospace;
font-size: 10px;
color: var(--steel);
line-height: 1;
}
/* Animations */
@keyframes pulse {
0% { transform: scale(1); opacity: 1; }
50% { transform: scale(1.2); opacity: 0.7; }
100% { transform: scale(1); opacity: 1; }
}
@keyframes morph {
0% { border-radius: 40% 60% 70% 30% / 40% 50% 60% 70%; }
100% { border-radius: 70% 30% 50% 50% / 30% 60% 40% 70%; }
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.reveal {
animation: revealUp 1s cubic-bezier(0.16, 1, 0.3, 1) forwards;
}
@keyframes revealUp {
from { opacity: 0; transform: translateY(40px); }
to { opacity: 1; transform: translateY(0); }
}
/* Responsive */
@media (max-width: 1024px) {
.hero { grid-template-columns: 1fr; text-align: center; }
.cta-group { justify-content: center; }
.features { grid-template-columns: 1fr; }
.thermal-signature { max-width: 500px; margin: 0 auto; }
}
`}</style>
<div className="thermal-grid"></div>
<div className="wrapper">
<nav>
<div className="logo">
<div className="logo-icon"></div>
Thermal
</div>
<div style={{ display: 'flex', gap: '40px' }}>
<span>Roasts</span>
<span>Origins</span>
<span>Science</span>
</div>
<div>
[ 001_SHOP_BAG ]
</div>
</nav>
<section className="hero">
<div className="hero-content">
<div className="data-overlay">
REF_CORE_TEMP: 204.4°C<br />
EXTRACTION_PSI: 9.2<br />
STABILITY: 99.8%
</div>
<h1 className="reveal">Engineered<br /><span>Extraction</span></h1>
<p
className="reveal"
style={{ color: 'var(--machined)', fontSize: '18px', marginBottom: '40px', maxWidth: '500px' }}
>
Every bean is a dataset. We use machined thermal geometry to map the perfect roast profile, ensuring molecular precision in every cup.
</p>
<div className="cta-group reveal" style={{ animationDelay: '0.2s' }}>
<button className="btn btn-primary">Begin Calibration</button>
<button className="btn btn-secondary">Thermal Archive</button>
</div>
</div>
<div
className="thermal-signature reveal"
style={{ animationDelay: '0.4s' }}
ref={containerRef}
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
>
<div className="thermal-viz">
<div className="viz-object">
<div className="viz-layer layer-1" style={getLayerStyle(0)}></div>
<div className="viz-layer layer-2" style={getLayerStyle(1)}></div>
<div className="viz-layer layer-3" style={getLayerStyle(2)}></div>
</div>
<div className="viz-specs">
<span>// THERMAL_MAPPING_ACTIVE</span>
OBJECT: ETHIOPIA_YIRGACHEFFE<br />
HEAT_DENSITY: HIGH_ALTITUDE<br />
NOTES: CITRUS_FLORAL_TECTONIC
</div>
{/* Technical UI Details */}
<div style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
pointerEvents: 'none',
border: '20px solid transparent',
boxSizing: 'border-box',
backgroundImage: 'linear-gradient(to right, var(--machined) 1px, transparent 1px), linear-gradient(to bottom, var(--machined) 1px, transparent 1px)',
backgroundSize: '40px 40px',
opacity: 0.1
}}></div>
</div>
</div>
</section>
<section className="features">
<div className="feature-item">
<span className="feature-label">01 // HEAT_CONTROL</span>
<h3>Kinetic Roasting</h3>
<p>Milled aluminum drums maintain a thermodynamic equilibrium that traditional roasters simply cannot achieve.</p>
</div>
<div className="feature-item">
<span className="feature-label">02 // SENSOR_ARRAY</span>
<h3>Optical Sorting</h3>
<p>Every single bean is scanned via infrared sensors to detect density anomalies before entering the thermal chamber.</p>
</div>
<div className="feature-item">
<span className="feature-label">03 // MOLECULAR_BOND</span>
<h3>Cryo-Sealing</h3>
<p>Roasts are flash-cooled with liquid nitrogen to lock in volatile aromatic compounds at the moment of peak flavor.</p>
</div>
</section>
<footer style={{
padding: '60px 0',
borderTop: '1px solid var(--steel)',
fontFamily: "'Space Mono', monospace",
fontSize: '10px',
color: 'var(--steel)',
display: 'flex',
justifyContent: 'space-between'
}}>
<div>©2024 THERMAL_GEOMETRY_SYSTEMS</div>
<div>STAY_CAFFEINATED // KEEP_PRECISION</div>
<div>40.7128° N, 74.0060° W</div>
</footer>
</div>
</div>
);
}