<div class="ff-container">
<div class="ff-panel">
<!-- SEARCH -->
<input
type="text"
id="ffSearch"
class="ff-search"
placeholder="🔍 Search..."
onkeyup="applyFilters()"
>
<!-- FILTER CHIPS -->
<div class="ff-chips" id="chipContainer">
<div class="chip" data-filter="fwd">FWD</div>
<div class="chip" data-filter="rwd">RWD</div>
<div class="chip" data-filter="awd">AWD</div>
<div class="chip" data-filter="turbo">Turbo</div>
<div class="chip" data-filter="street">Street</div>
<div class="chip" data-filter="motorsport">Motorsport</div>
<div class="chip" data-filter="cheap">Budget</div>
<div class="chip" data-filter="performance">Performance</div>
</div>
<!-- TABLE -->
<div style="overflow-x:auto;">
<table class="ff-table" id="ffTable">
<thead>
<tr>
<th onclick="sortTable(0, this)">Jetta Mk3 <span class="arrow">⇅</span></th>
<th onclick="sortTable(1, this)">Sierra Sapphire <span class="arrow">⇅</span></th>
</tr>
</thead>
<tbody>
<tr data-tags="fwd street cheap">
<td>Compact tuner sedan</td>
<td>Mid-size performance sedan</td>
</tr>
<tr data-tags="fwd">
<td>Front-Wheel Drive (FWD)</td>
<td>Rear-Wheel Drive / AWD</td>
</tr>
<tr data-tags="turbo performance">
<td>Modified inline-4</td>
<td>2.0L turbocharged Cosworth</td>
</tr>
<tr data-tags="performance">
<td>~250–400+ hp</td>
<td>~204–220 hp</td>
</tr>
<tr data-tags="street">
<td>Street racing style</td>
<td>Motorsport heritage</td>
</tr>
<tr data-tags="street">
<td>Flashy decals</td>
<td>Sleeper look</td>
</tr>
<tr data-tags="cheap">
<td>Cheaper mods</td>
<td>Higher performance ceiling</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
let sortState = {};
let activeFilters = new Set();
/* CHIP CLICK (MULTI-SELECT) */
document.querySelectorAll(".chip").forEach(chip => {
chip.addEventListener("click", () => {
const value = chip.dataset.filter;
chip.classList.toggle("active");
if (activeFilters.has(value)) {
activeFilters.delete(value);
} else {
activeFilters.add(value);
}
applyFilters();
});
});
/* SORT */
function sortTable(colIndex, header) {
const table = document.getElementById("ffTable");
const tbody = table.querySelector("tbody");
const rows = Array.from(tbody.rows);
const headers = table.querySelectorAll("th");
headers.forEach(th => th.querySelector(".arrow").textContent = "⇅");
sortState[colIndex] = !sortState[colIndex];
const direction = sortState[colIndex];
header.querySelector(".arrow").textContent = direction ? "↑" : "↓";
rows.sort((a, b) => {
let A = a.cells[colIndex].innerText.toLowerCase();
let B = b.cells[colIndex].innerText.toLowerCase();
return direction
? A.localeCompare(B, undefined, {numeric:true})
: B.localeCompare(A, undefined, {numeric:true});
});
rows.forEach(row => tbody.appendChild(row));
}
/* FILTER */
function applyFilters() {
const search = document.getElementById("ffSearch").value.toLowerCase();
const rows = document.querySelectorAll("#ffTable tbody tr");
rows.forEach(row => {
const text = row.innerText.toLowerCase();
const tags = row.dataset.tags || "";
const matchSearch = text.includes(search);
let matchFilter = true;
if (activeFilters.size > 0) {
matchFilter = [...activeFilters].every(f => tags.includes(f));
}
row.style.display = (matchSearch && matchFilter) ? "" : "none";
});
}
</script>
<style>
.ff-container {
font-family:'IBM Plex Mono', monospace;
margin:20px 0;
color:#ffffff;
}
/* PANEL */
.ff-panel {
background:linear-gradient(145deg,dodgerblue,dodgerblue);
border-radius:14px;
padding:14px;
box-shadow:0 0 20px rgba(30,144,255,0.6);
}
/* SEARCH */
.ff-search {
width:100%;
padding:10px 14px;
border-radius:8px;
border:1px solid #ffffff33;
background:dodgerblue;
color:#ffffff;
margin-bottom:10px;
}
/* FILTER CHIPS */
.ff-chips {
display:flex;
flex-wrap:wrap;
gap:8px;
margin-bottom:12px;
}
.chip {
padding:6px 10px;
border-radius:999px;
font-size:12px;
background:dodgerblue;
border:1px solid #ffffff33;
cursor:pointer;
transition:0.25s;
color:#fff;
}
.chip.active {
background:#ffffff;
color:dodgerblue;
box-shadow:0 0 10px #ffffff;
}
.chip:hover {
box-shadow:0 0 8px #ffffff;
}
/* TABLE */
.ff-table {
width:100%;
border-collapse:separate;
border-spacing:0;
background:dodgerblue;
border-radius:12px;
overflow:hidden;
}
.ff-table th {
padding:14px;
text-align:left;
background:dodgerblue;
border-bottom:1px solid #ffffff33;
cursor:pointer;
position:relative;
color:#ffffff;
}
.ff-table th .arrow {
position:absolute;
right:10px;
opacity:0.7;
}
.ff-table td {
padding:12px;
border-bottom:1px solid #ffffff33;
transition:0.25s;
position:relative;
color:#ffffff;
}
/* ROW COLORS (slight variation for depth) */
.ff-table tr:nth-child(even) td { background:#1c86ee; }
.ff-table tr:nth-child(odd) td { background:dodgerblue; }
/* ROW HOVER */
.ff-table tr:hover td {
background:#187bcd;
box-shadow: inset 0 0 10px rgba(255,255,255,0.3),
0 0 12px rgba(255,255,255,0.4);
}
/* COLUMN HIGHLIGHT */
.ff-table td:hover::after,
.ff-table th:hover::after {
content:"";
position:absolute;
top:-5000px;
bottom:-5000px;
left:0;
right:0;
background:rgba(255,255,255,0.15);
z-index:-1;
}
</style>
Comments
Post a Comment