228 lines
13 KiB
TypeScript
228 lines
13 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState } from 'react';
|
|
|
|
const materialsData = [
|
|
{
|
|
num: "01",
|
|
cat: "mesh",
|
|
name: "Chain Link Mesh",
|
|
desc: "The primary fencing fabric — available in galvanized and vinyl coated black finishes. Multiple gauge and mesh sizes for residential and commercial use.",
|
|
specs: ["Galvanized", "Black vinyl coated", "Multiple gauges", "2\" mesh typical"],
|
|
img: "/assets/chain-link-fence/chain-link-mesh.webp"
|
|
},
|
|
{
|
|
num: "02",
|
|
cat: "structure",
|
|
name: "Terminal Posts",
|
|
desc: "Heavy-duty end, corner, and gate posts that anchor the fence line. Larger diameter than line posts for maximum structural strength at key points.",
|
|
specs: ["End posts", "Corner posts", "Gate posts", "Multiple diameters"],
|
|
img: "/assets/chain-link-fence/terminal-post.webp"
|
|
},
|
|
{
|
|
num: "03",
|
|
cat: "structure",
|
|
name: "Line Posts",
|
|
desc: "Intermediate posts set between terminal posts to support the mesh and top rail at regular intervals, typically every 10 feet.",
|
|
specs: ["Galvanized steel", "Multiple heights", "Multiple diameters"],
|
|
img: "/assets/chain-link-fence/line-posts.webp"
|
|
},
|
|
{
|
|
num: "04",
|
|
cat: "structure",
|
|
name: "Top Rail",
|
|
desc: "Horizontal pipe running along the top of the fence, threading through loop caps on line posts to stabilise the mesh and define the top edge.",
|
|
specs: ["Galvanized pipe", "21ft lengths", "Sleeve-joined"],
|
|
img: "/assets/chain-link-fence/top-rail.webp"
|
|
},
|
|
{
|
|
num: "05",
|
|
cat: "mesh",
|
|
name: "Bottom Tension Wire",
|
|
desc: "Heavy gauge galvanized wire run along the bottom of the mesh to keep the fence taut and prevent mesh lift. Also available as bottom rail pipe.",
|
|
specs: ["Galvanized wire", "Bottom rail option", "High tension"],
|
|
img: "/assets/chain-link-fence/bottom-tension-wire.webp"
|
|
},
|
|
{
|
|
num: "06",
|
|
cat: "hardware",
|
|
name: "Tension Bars",
|
|
desc: "Flat steel bars woven vertically through the end of the mesh fabric and secured with tension bands to the terminal post, pulling the mesh taut.",
|
|
specs: ["Galvanized steel", "Multiple lengths"],
|
|
img: "/assets/chain-link-fence/tension-bars.webp"
|
|
},
|
|
{
|
|
num: "07",
|
|
cat: "hardware",
|
|
name: "Tension Bands",
|
|
desc: "Clamp bands bolted around terminal posts to hold tension bars and rail ends securely in place. Spaced evenly along the post height.",
|
|
specs: ["Galvanized steel", "Various post sizes"],
|
|
img: "/assets/chain-link-fence/tension-bands.webp"
|
|
},
|
|
{
|
|
num: "08",
|
|
cat: "hardware",
|
|
name: "Brace Bands",
|
|
desc: "Used to attach rail ends to line posts, securing the top rail into position around the post perimeter. Essential for top rail alignment and stability.",
|
|
specs: ["Galvanized", "All post sizes"],
|
|
img: "/assets/chain-link-fence/brace-bands.webp"
|
|
},
|
|
{
|
|
num: "09",
|
|
cat: "hardware",
|
|
name: "Rail Ends",
|
|
desc: "Pressed steel fittings that attach the end of the top rail to a terminal post via a tension band. Provides a neat, secure termination point for the rail.",
|
|
specs: ["Pressed steel", "Galvanized"],
|
|
img: "/assets/chain-link-fence/rail-ends.webp"
|
|
},
|
|
{
|
|
num: "10",
|
|
cat: "hardware",
|
|
name: "Post Caps",
|
|
desc: "Loop caps thread the top rail through the line post for support. Dome caps seal the tops of terminal posts, preventing water ingress and corrosion.",
|
|
specs: ["Loop caps", "Dome caps", "All post sizes"],
|
|
img: "/assets/chain-link-fence/post-caps.webp"
|
|
},
|
|
{
|
|
num: "11",
|
|
cat: "hardware",
|
|
name: "Fence Ties",
|
|
desc: "Aluminum or steel wire ties that fasten the chain link mesh to line posts and top rail, securing the fabric in place throughout the fence run.",
|
|
specs: ["Aluminum", "Steel", "Bulk packs"],
|
|
img: "/assets/chain-link-fence/fence-ties.webp"
|
|
},
|
|
{
|
|
num: "12",
|
|
cat: "gates",
|
|
name: "Gates",
|
|
desc: "Chain link walk gates and double drive gates in standard and custom widths. Pre-built frames ready to hang, or materials for field-fabricated gates.",
|
|
specs: ["Single walk gates", "Double drive gates", "Custom widths"],
|
|
img: "/assets/chain-link-fence/gates.webp"
|
|
},
|
|
{
|
|
num: "13",
|
|
cat: "gates",
|
|
name: "Gate Hardware",
|
|
desc: "Heavy-duty hinges, fork latches, cane bolts, and gate stops. All hardware required for proper gate installation and long-term operation.",
|
|
specs: ["Hinges", "Latches", "Cane bolts", "Padlock eyes"],
|
|
img: "/assets/chain-link-fence/gate-hardware.webp"
|
|
},
|
|
{
|
|
num: "14",
|
|
cat: "structure",
|
|
name: "Concrete",
|
|
desc: "Fast-setting concrete mix for post setting. Properly set posts are critical to fence longevity — use concrete on every terminal post and every line post in loose or sandy soil.",
|
|
specs: ["Fast-setting", "Bags available", "Post setting mix"],
|
|
img: "/assets/chain-link-fence/concrete.webp"
|
|
},
|
|
{
|
|
num: "15",
|
|
cat: "extras",
|
|
name: "Privacy Slats",
|
|
desc: "Vertical or horizontal slats woven through chain link mesh to add privacy and visual screening. Available in multiple colours to complement any project.",
|
|
specs: ["Multiple colours", "Vertical weave", "UV resistant"],
|
|
img: "/assets/chain-link-fence/privacy-slats.webp"
|
|
},
|
|
{
|
|
num: "16",
|
|
cat: "extras",
|
|
name: "Windscreen / Privacy Mesh",
|
|
desc: "Woven or knitted privacy screen attached to the fence exterior. Popular for sports facilities, construction sites, and commercial properties requiring visual screening.",
|
|
specs: ["Woven fabric", "Commercial grade", "Custom sizes"],
|
|
img: "/assets/chain-link-fence/windscreen.webp"
|
|
},
|
|
{
|
|
num: "17",
|
|
cat: "extras",
|
|
name: "Barbed Wire",
|
|
desc: "Two-strand galvanized barbed wire for security enhancement on commercial and industrial fence installations. Attached at the top with barbed wire arms.",
|
|
specs: ["Commercial use", "Galvanized", "Barbed wire arms"],
|
|
img: "/assets/chain-link-fence/barbed-wire.webp"
|
|
}
|
|
];
|
|
|
|
const ChainLinkMaterials = () => {
|
|
const [activeCat, setActiveCat] = useState('all');
|
|
|
|
const filteredMaterials = activeCat === 'all'
|
|
? materialsData
|
|
: materialsData.filter(m => m.cat === activeCat);
|
|
|
|
const categories = [
|
|
{ id: 'all', label: 'All materials' },
|
|
{ id: 'structure', label: 'Structure & posts' },
|
|
{ id: 'mesh', label: 'Mesh & wire' },
|
|
{ id: 'hardware', label: 'Hardware & fittings' },
|
|
{ id: 'gates', label: 'Gates & access' },
|
|
{ id: 'extras', label: 'Extras & accessories' }
|
|
];
|
|
|
|
return (
|
|
<section className="materials" id="materials">
|
|
<div className="reveal">
|
|
<div className="materials-intro">
|
|
<div>
|
|
<div className="section-eyebrow">Product catalogue</div>
|
|
<h2 className="sh">Chain link fence<br /><span>materials list.</span></h2>
|
|
</div>
|
|
<p>Every component you need for a complete chain link fence installation — all stocked and ready for delivery across Ontario.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="cat-tabs reveal">
|
|
{categories.map(cat => (
|
|
<button
|
|
key={cat.id}
|
|
className={`cat-tab ${activeCat === cat.id ? 'active' : ''}`}
|
|
onClick={() => setActiveCat(cat.id)}
|
|
>
|
|
{cat.label}
|
|
</button>
|
|
))}
|
|
</div>
|
|
|
|
<div className="mat-grid">
|
|
{filteredMaterials.map((mat) => (
|
|
<div key={mat.num} className="mat-card">
|
|
<div className="mat-img-wrap">
|
|
<img src={mat.img} alt={mat.name} />
|
|
</div>
|
|
<div className="mat-num">{mat.num}</div>
|
|
<div className="mat-icon">
|
|
{/* Simplified version of the icons since they are many, keeping a generic but nice look or using the specific ones from HTML if I can extract them easily.
|
|
Actually, I'll just use the SVG types from the HTML for each card. */}
|
|
{mat.num === "01" && <svg viewBox="0 0 20 20" fill="none"><path d="M2 2 L10 10 L18 2" stroke="white" strokeWidth="1.5" fill="none" strokeLinecap="round"/><path d="M2 10 L10 18 L18 10" stroke="white" strokeWidth="1.5" fill="none" strokeLinecap="round"/><path d="M2 6 L18 6" stroke="white" strokeWidth="1" opacity=".5"/><path d="M2 14 L18 14" stroke="white" strokeWidth="1" opacity=".5"/></svg>}
|
|
{mat.num === "02" && <svg viewBox="0 0 20 20" fill="none"><rect x="7" y="1" width="6" height="18" rx="1.5" fill="white" opacity=".9"/><rect x="4" y="1" width="3" height="4" rx="1" fill="white" opacity=".4"/><rect x="13" y="1" width="3" height="4" rx="1" fill="white" opacity=".4"/></svg>}
|
|
{mat.num === "03" && <svg viewBox="0 0 20 20" fill="none"><rect x="8" y="1" width="4" height="18" rx="1.5" fill="white"/><line x1="4" y1="7" x2="16" y2="7" stroke="white" strokeWidth="1" opacity=".5"/><line x1="4" y1="13" x2="16" y2="13" stroke="white" strokeWidth="1" opacity=".5"/></svg>}
|
|
{mat.num === "04" && <svg viewBox="0 0 20 20" fill="none"><rect x="1" y="8" width="18" height="4" rx="2" fill="white"/><rect x="4" y="2" width="2" height="6" rx="1" fill="white" opacity=".5"/><rect x="14" y="2" width="2" height="6" rx="1" fill="white" opacity=".5"/></svg>}
|
|
{mat.num === "05" && <svg viewBox="0 0 20 20" fill="none"><line x1="1" y1="10" x2="19" y2="10" stroke="white" strokeWidth="2.5" strokeLinecap="round"/><circle cx="5" cy="10" r="2" fill="white" opacity=".6"/><circle cx="10" cy="10" r="2" fill="white" opacity=".6"/><circle cx="15" cy="10" r="2" fill="white" opacity=".6"/></svg>}
|
|
{mat.num === "06" && <svg viewBox="0 0 20 20" fill="none"><rect x="8" y="1" width="4" height="18" rx="1" fill="white"/><rect x="5" y="4" width="10" height="2" rx="1" fill="white" opacity=".5"/><rect x="5" y="14" width="10" height="2" rx="1" fill="white" opacity=".5"/></svg>}
|
|
{mat.num === "07" && <svg viewBox="0 0 20 20" fill="none"><circle cx="10" cy="10" r="7" fill="none" stroke="white" strokeWidth="2"/><rect x="8" y="1" width="4" height="3" rx="1" fill="white" opacity=".7"/></svg>}
|
|
{mat.num === "08" && <svg viewBox="0 0 20 20" fill="none"><path d="M3 10 Q10 4 17 10" stroke="white" strokeWidth="2" fill="none" strokeLinecap="round"/><path d="M3 12 Q10 6 17 12" stroke="white" strokeWidth="1" fill="none" strokeLinecap="round" opacity=".4"/></svg>}
|
|
{mat.num === "09" && <svg viewBox="0 0 20 20" fill="none"><rect x="2" y="8" width="10" height="4" rx="1.5" fill="white"/><circle cx="16" cy="10" r="3" fill="white" opacity=".7"/></svg>}
|
|
{mat.num === "10" && <svg viewBox="0 0 20 20" fill="none"><circle cx="10" cy="6" r="4" fill="white" opacity=".9"/><rect x="8" y="10" width="4" height="9" rx="1" fill="white" opacity=".6"/></svg>}
|
|
{mat.num === "11" && <svg viewBox="0 0 20 20" fill="none"><path d="M5 10 C5 6 10 4 15 7" stroke="white" strokeWidth="2" fill="none" strokeLinecap="round"/><path d="M5 10 C5 14 10 16 15 13" stroke="white" strokeWidth="1" fill="none" strokeLinecap="round" opacity=".5"/></svg>}
|
|
{mat.num === "12" && <svg viewBox="0 0 20 20" fill="none"><rect x="1" y="3" width="7" height="14" rx="1" fill="white" opacity=".9"/><rect x="12" y="3" width="7" height="14" rx="1" fill="white" opacity=".9"/><line x1="8" y1="10" x2="12" y2="10" stroke="white" strokeWidth="1.5" strokeDasharray="2 1"/></svg>}
|
|
{mat.num === "13" && <svg viewBox="0 0 20 20" fill="none"><circle cx="6" cy="10" r="4" fill="none" stroke="white" strokeWidth="2"/><rect x="10" y="9" width="9" height="2" rx="1" fill="white"/><circle cx="6" cy="10" r="1.5" fill="white"/></svg>}
|
|
{mat.num === "14" && <svg viewBox="0 0 20 20" fill="none"><rect x="3" y="10" width="14" height="9" rx="1.5" fill="white" opacity=".8"/><path d="M5 10 L10 3 L15 10" fill="white" opacity=".5"/></svg>}
|
|
{mat.num === "15" && <svg viewBox="0 0 20 20" fill="none"><rect x="2" y="2" width="3" height="16" rx="1" fill="white"/><rect x="7" y="2" width="3" height="16" rx="1" fill="white" opacity=".7"/><rect x="12" y="2" width="3" height="16" rx="1" fill="white" opacity=".5"/><rect x="17" y="2" width="2" height="16" rx="1" fill="white" opacity=".3"/></svg>}
|
|
{mat.num === "16" && <svg viewBox="0 0 20 20" fill="none"><rect x="1" y="5" width="18" height="10" rx="2" fill="white" opacity=".3" stroke="white" strokeWidth="1.5"/><line x1="5" y1="5" x2="5" y2="15" stroke="white" strokeWidth="1" opacity=".5"/><line x1="10" y1="5" x2="10" y2="15" stroke="white" strokeWidth="1" opacity=".5"/><line x1="15" y1="5" x2="15" y2="15" stroke="white" strokeWidth="1" opacity=".5"/></svg>}
|
|
{mat.num === "17" && <svg viewBox="0 0 20 20" fill="none"><line x1="1" y1="10" x2="19" y2="10" stroke="white" strokeWidth="2" strokeLinecap="round"/><path d="M5 7 L5 13 M5 7 L7 9 M5 7 L3 9" stroke="white" strokeWidth="1.2" strokeLinecap="round"/><path d="M12 7 L12 13 M12 7 L14 9 M12 7 L10 9" stroke="white" strokeWidth="1.2" strokeLinecap="round"/></svg>}
|
|
</div>
|
|
<div className="mat-name">{mat.name}</div>
|
|
<div className="mat-desc">{mat.desc}</div>
|
|
<div className="mat-specs">
|
|
{mat.specs.map((spec, i) => (
|
|
<span key={i} className="mat-spec">{spec}</span>
|
|
))}
|
|
</div>
|
|
<div className="mat-arrow">→</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</section>
|
|
);
|
|
};
|
|
|
|
export default ChainLinkMaterials;
|