About
A high-fidelity, industrial sci-fi dashboard component that simulates a weathered, organic digital fabric. This interface creates a "tactile" user experience by blending CSS grid layouts with custom SVG turbulence filters (to create a rust/noise texture) and a 3D mouse-driven parallax effect. It features a high-performance, real-time data visualization (the tension bars) that runs outside the React render cycle for optimal frame rates.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds OxideLoomInterface to your project and fits it to your theme.
Code
How OxideLoomInterface is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
import React, { useEffect, useRef } from 'react';
const OxidizedUI: React.FC = () => {
const containerRef = useRef<HTMLDivElement>(null);
const tensionRef = useRef<HTMLDivElement>(null);
const barRefs = useRef<(HTMLDivElement | null)[]>([]);
// Initialize the refs array
barRefs.current = [];
const addToBarRefs = (el: HTMLDivElement | null) => {
if (el && !barRefs.current.includes(el)) {
barRefs.current.push(el);
}
};
useEffect(() => {
let animationFrameId: number;
// 1. Animation Loop for Tension and Bars
const animate = () => {
// Update Tension Text directly
if (tensionRef.current) {
const val = (142 + Math.random() * 0.5).toFixed(2);
tensionRef.current.innerText = val;
}
// Update Bars randomly
barRefs.current.forEach((bar) => {
if (bar && Math.random() > 0.8) {
const h = Math.random() * 80 + 10;
bar.style.height = `${h}%`;
}
});
animationFrameId = requestAnimationFrame(animate);
};
// Start animation
animate();
// 2. Mouse Parallax Effect
const handleMouseMove = (e: MouseEvent) => {
if (containerRef.current) {
const xAxis = (window.innerWidth / 2 - e.pageX) / 50;
const yAxis = (window.innerHeight / 2 - e.pageY) / 50;
containerRef.current.style.transform = `rotateY(${xAxis}deg) rotateX(${yAxis}deg)`;
}
};
document.addEventListener('mousemove', handleMouseMove);
// Cleanup
return () => {
cancelAnimationFrame(animationFrameId);
document.removeEventListener('mousemove', handleMouseMove);
};
}, []);
return (
<>
{/* Font Imports */}
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;800&family=JetBrains+Mono:wght@200;500&display=swap"
rel="stylesheet"
/>
{/* Scoped Styles */}
<style>{`
:root {
--oxide-deep: #121414;
--oxide-rust: #9c4a2f;
--oxide-copper: #d4805c;
--oxide-verdigris: #4a7c73;
--fiber-base: #e0d7c6;
--fiber-muted: rgba(224, 215, 198, 0.15);
--transition-fluid: all 0.6s cubic-bezier(0.23, 1, 0.32, 1);
}
.oxidized-body {
background-color: var(--oxide-deep);
color: var(--fiber-base);
font-family: 'Inter', sans-serif;
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
perspective: 1200px;
position: relative;
}
/* The Grain & Oxidation Filter */
.noise-overlay {
position: absolute;
top: 0; left: 0; width: 100%; height: 100%;
pointer-events: none;
z-index: 100;
opacity: 0.4;
mix-blend-mode: overlay;
}
/* The Weave Grid */
.weave-container {
position: relative;
width: 90vw;
max-width: 1100px;
height: 600px;
display: grid;
grid-template-columns: 1fr 350px;
grid-template-rows: 1fr auto;
gap: 2rem;
padding: 3rem;
background: radial-gradient(circle at 0% 0%, #1a1e1e 0%, #121414 100%);
border: 1px solid rgba(156, 74, 47, 0.2);
box-shadow: 0 50px 100px -20px rgba(0,0,0,0.7);
transform-style: preserve-3d;
}
.weave-container::before {
content: "";
position: absolute;
inset: 0;
background-image:
repeating-linear-gradient(0deg, transparent, transparent 1px, var(--fiber-muted) 1px, var(--fiber-muted) 2px),
repeating-linear-gradient(90deg, transparent, transparent 1px, var(--fiber-muted) 1px, var(--fiber-muted) 2px);
background-size: 20px 20px;
pointer-events: none;
mask-image: linear-gradient(to bottom right, black, transparent);
-webkit-mask-image: linear-gradient(to bottom right, black, transparent);
}
/* Branding/Typography Section */
.header-section {
display: flex;
flex-direction: column;
justify-content: flex-end;
z-index: 2;
}
.header-section h1 {
font-size: clamp(3rem, 8vw, 6rem);
font-weight: 800;
line-height: 0.85;
text-transform: uppercase;
letter-spacing: -0.04em;
background: linear-gradient(135deg, var(--fiber-base) 0%, var(--oxide-copper) 50%, var(--oxide-rust) 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
margin-bottom: 1.5rem;
animation: textReveal 1.2s cubic-bezier(0.77, 0, 0.175, 1);
}
.meta-data {
font-family: 'JetBrains Mono', monospace;
font-size: 0.75rem;
text-transform: uppercase;
letter-spacing: 0.2em;
color: var(--oxide-verdigris);
display: flex;
gap: 2rem;
}
/* The "Oxidized" Interactive Card */
.fiber-module {
position: relative;
background: rgba(20, 22, 22, 0.8);
border: 1px solid rgba(156, 74, 47, 0.4);
padding: 2rem;
backdrop-filter: blur(20px);
overflow: hidden;
transition: var(--transition-fluid);
display: flex;
flex-direction: column;
justify-content: space-between;
}
.fiber-module:hover {
border-color: var(--oxide-copper);
transform: translateY(-5px) scale(1.02);
box-shadow: 0 20px 40px rgba(0,0,0,0.4);
}
.fiber-module::after {
content: "";
position: absolute;
top: -50%; left: -50%; width: 200%; height: 200%;
background: radial-gradient(circle at center, var(--oxide-rust) 0%, transparent 70%);
opacity: 0.05;
pointer-events: none;
transition: var(--transition-fluid);
}
.fiber-module:hover::after {
opacity: 0.15;
transform: scale(1.2);
}
.strand-viz {
height: 150px;
width: 100%;
margin-top: 1rem;
display: flex;
align-items: flex-end;
gap: 4px;
}
.strand-bar {
flex: 1;
background: var(--oxide-rust);
min-height: 10%;
transition: var(--transition-fluid);
opacity: 0.6;
}
.fiber-module:hover .strand-bar {
background: var(--oxide-copper);
opacity: 1;
}
/* Decorative "Stitch" element */
.stitch-line {
position: absolute;
left: 0;
top: 15%;
width: 100%;
height: 1px;
background: repeating-linear-gradient(90deg, transparent, transparent 10px, var(--oxide-verdigris) 10px, var(--oxide-verdigris) 20px);
opacity: 0.3;
}
.data-label {
font-family: 'JetBrains Mono', monospace;
font-size: 0.7rem;
color: var(--oxide-copper);
margin-bottom: 0.5rem;
}
.data-value {
font-size: 2rem;
font-weight: 300;
color: var(--fiber-base);
}
/* Animations */
@keyframes textReveal {
from { opacity: 0; transform: translateY(40px) skewY(5deg); }
to { opacity: 1; transform: translateY(0) skewY(0deg); }
}
/* SVG Filter Definitions for Grain */
svg.filters {
position: absolute;
width: 0; height: 0;
}
.cta-button {
margin-top: 2rem;
padding: 1rem 2rem;
background: transparent;
border: 1px solid var(--fiber-base);
color: var(--fiber-base);
font-family: 'JetBrains Mono', monospace;
font-size: 0.8rem;
text-transform: uppercase;
cursor: pointer;
transition: var(--transition-fluid);
position: relative;
overflow: hidden;
align-self: flex-start;
}
.cta-button:hover {
background: var(--fiber-base);
color: var(--oxide-deep);
}
.sidebar-indicator {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%) rotate(90deg);
font-family: 'JetBrains Mono', monospace;
font-size: 10px;
letter-spacing: 0.5em;
color: var(--oxide-rust);
white-space: nowrap;
}
`}</style>
<div className="oxidized-body">
<svg className="filters">
<filter id="rustNoise">
<feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="4" stitchTiles="stitch" />
<feColorMatrix type="saturate" values="0" />
<feComponentTransfer>
<feFuncR type="linear" slope="0.3" />
<feFuncG type="linear" slope="0.3" />
<feFuncB type="linear" slope="0.3" />
</feComponentTransfer>
</filter>
</svg>
<div className="noise-overlay" style={{ filter: 'url(#rustNoise)' }}></div>
<div className="weave-container" ref={containerRef}>
<div className="sidebar-indicator">INTEGRITY_INDEX // 0.992</div>
<div className="header-section">
<div className="meta-data">
<span>Ref: OX-882</span>
<span>Type: Fibrous Composite</span>
</div>
<h1>The<br />Weaver's<br />Ghost</h1>
<p style={{ maxWidth: '400px', fontSize: '0.9rem', lineHeight: '1.6', opacity: 0.7, marginTop: '1rem' }}>
A tactile digital environment exploring the intersection of industrial oxidation and organic fiber tension. Every interaction rewrites the warp.
</p>
<button className="cta-button">Initiate Sequence</button>
</div>
<div className="fiber-module">
<div className="stitch-line"></div>
<div>
<div className="data-label">TENSION_LOAD</div>
<div className="data-value" ref={tensionRef}>142.08</div>
</div>
<div className="strand-viz" id="strand-container">
{/* Generate 24 bars */}
{Array.from({ length: 24 }).map((_, i) => (
<div
key={i}
className="strand-bar"
ref={addToBarRefs}
style={{
height: `${Math.random() * 80 + 10}%`,
transitionDelay: `${i * 0.02}s`
}}
/>
))}
</div>
<div style={{ marginTop: '1.5rem', borderTop: '1px solid var(--fiber-muted)', paddingTop: '1rem' }}>
<div className="data-label">OXIDE_STATE</div>
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span style={{ fontFamily: 'JetBrains Mono', fontSize: '0.8rem' }}>VULCANIZED</span>
<span style={{ color: 'var(--oxide-verdigris)' }}>● ACTIVE</span>
</div>
</div>
</div>
<div style={{ gridColumn: 'span 2', borderTop: '1px solid var(--fiber-muted)', paddingTop: '1.5rem', display: 'flex', justifyContent: 'space-between', fontFamily: 'JetBrains Mono', fontSize: '0.65rem', opacity: 0.5 }}>
<span>SYSTEM_CORE_V4.0</span>
<span>ENCRYPTED_FIBER_PROTOCOL</span>
<span>© 2024 OXIDE_UI</span>
</div>
</div>
</div>
</>
);
};
export default OxidizedUI;













