Spec, stylesheet, glitch script, Claude Code skill and the design canvas source. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
146 lines
9.9 KiB
HTML
146 lines
9.9 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Night Grid sample dashboard</title>
|
|
<script src="./support.js"></script>
|
|
</head>
|
|
<body>
|
|
<x-dc>
|
|
<helmet>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link href="https://fonts.googleapis.com/css2?family=Rajdhani:wght@500;600;700&family=JetBrains+Mono:wght@400;600&display=swap" rel="stylesheet">
|
|
<style>
|
|
body{margin:0;background:#050508}
|
|
a{color:#02D7F2}a:hover{color:#FCEE0A}
|
|
</style>
|
|
</helmet>
|
|
<div style="min-height: 100vh; background: #050508; color: #E6E8EC; font-family: 'Rajdhani', sans-serif; font-size: 18px; line-height: 1.5">
|
|
<div style="display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; padding: 16px 24px; border-bottom: 1px solid #2A2F3A">
|
|
<div style="display: flex; align-items: center; gap: 16px; flex-wrap: wrap">
|
|
<span style="background: #FCEE0A; color: #050508; padding: 4px 12px; font-size: 22px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase">Homelab</span>
|
|
<span style="font-family: 'JetBrains Mono', monospace; font-size: 13px; letter-spacing: 0.12em; color: #8A93A3">SYS.MONITOR // SAMPLE DATA</span>
|
|
</div>
|
|
<nav aria-label="Sections" style="display: flex; flex-wrap: wrap; gap: 4px">
|
|
<a href="#" style="min-height: 44px; display: inline-flex; align-items: center; padding: 0 16px; color: #FCEE0A; text-decoration: none; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; border-bottom: 2px solid #FCEE0A">Overview</a>
|
|
<a href="#" style="min-height: 44px; display: inline-flex; align-items: center; padding: 0 16px; color: #8A93A3; text-decoration: none; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase">Nodes</a>
|
|
<a href="#" style="min-height: 44px; display: inline-flex; align-items: center; padding: 0 16px; color: #8A93A3; text-decoration: none; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase">Network</a>
|
|
<a href="#" style="min-height: 44px; display: inline-flex; align-items: center; padding: 0 16px; color: #8A93A3; text-decoration: none; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase">Logs</a>
|
|
</nav>
|
|
<span style="font-family: 'JetBrains Mono', monospace; font-size: 13px; color: #02D7F2">● LIVE 22:41:07</span>
|
|
</div>
|
|
|
|
<div style="max-width: 1360px; margin: 0 auto; padding: 32px 24px 64px; display: flex; flex-direction: column; gap: 24px">
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 16px">
|
|
<sc-for list="{{stats}}" as="s" hint-placeholder-count="4">
|
|
<div style="background: #0E1016; border: 1px solid #2A2F3A; padding: 20px 24px; display: flex; flex-direction: column; gap: 8px; clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%)">
|
|
<div style="font-family: 'JetBrains Mono', monospace; font-size: 12px; letter-spacing: 0.15em; color: #8A93A3">{{s.label}}</div>
|
|
<div style="font-family: 'JetBrains Mono', monospace; font-size: 40px; font-weight: 600; line-height: 1.1; color: {{s.color}}">{{s.value}}<span style="font-size: 18px; color: #8A93A3">{{s.unit}}</span></div>
|
|
<div style="display: flex; gap: 3px">
|
|
<sc-for list="{{s.segs}}" as="g" hint-placeholder-count="10"><div style="flex: 1; height: 6px; background: {{g}}"></div></sc-for>
|
|
</div>
|
|
<div style="font-family: 'JetBrains Mono', monospace; font-size: 12px; color: {{s.noteColor}}">{{s.note}}</div>
|
|
</div>
|
|
</sc-for>
|
|
</div>
|
|
|
|
<div style="display: flex; flex-wrap: wrap; gap: 16px">
|
|
<div style="flex: 999 1 560px; min-width: 0; background: #0E1016; border: 1px solid #2A2F3A; padding: 24px; display: flex; flex-direction: column; gap: 16px; clip-path: polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% 100%, 0 100%)">
|
|
<div style="display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: 8px">
|
|
<h2 style="margin: 0; font-size: 24px; font-weight: 700; text-transform: uppercase">Network throughput</h2>
|
|
<div style="display: flex; gap: 16px; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #8A93A3">
|
|
<span><span style="display: inline-block; width: 10px; height: 10px; background: #02D7F2; margin-right: 6px"></span>RX</span>
|
|
<span><span style="display: inline-block; width: 10px; height: 10px; background: #FCEE0A; margin-right: 6px"></span>TX</span>
|
|
</div>
|
|
</div>
|
|
<div role="img" aria-label="Bar chart of received and transmitted traffic over the last 12 hours, sample data" style="display: flex; align-items: flex-end; gap: 6px; height: 220px; border-bottom: 1px solid #2A2F3A; background: repeating-linear-gradient(0deg, #1C2029 0px, #1C2029 1px, transparent 1px, transparent 55px)">
|
|
<sc-for list="{{bars}}" as="b" hint-placeholder-count="12">
|
|
<div style="flex: 1; display: flex; align-items: flex-end; gap: 2px; height: 100%">
|
|
<div style="flex: 1; height: {{b.rx}}; background: #02D7F2"></div>
|
|
<div style="flex: 1; height: {{b.tx}}; background: #FCEE0A"></div>
|
|
</div>
|
|
</sc-for>
|
|
</div>
|
|
<div style="display: flex; justify-content: space-between; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #8A93A3"><span>-12H</span><span>-6H</span><span>NOW</span></div>
|
|
</div>
|
|
|
|
<div style="flex: 1 1 320px; min-width: 0; background: #0E1016; border: 1px solid #2A2F3A; padding: 24px; display: flex; flex-direction: column; gap: 16px">
|
|
<h2 style="margin: 0; font-size: 24px; font-weight: 700; text-transform: uppercase">Nodes</h2>
|
|
<sc-for list="{{nodes}}" as="n" hint-placeholder-count="4">
|
|
<div style="display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid #1C2029">
|
|
<div style="display: flex; flex-direction: column">
|
|
<span style="font-weight: 700; text-transform: uppercase">{{n.name}}</span>
|
|
<span style="font-family: 'JetBrains Mono', monospace; font-size: 12px; color: #8A93A3">{{n.ip}}</span>
|
|
</div>
|
|
<span style="font-family: 'JetBrains Mono', monospace; font-size: 12px; letter-spacing: 0.12em; padding: 4px 10px; border: 1px solid {{n.color}}; color: {{n.color}}">{{n.status}}</span>
|
|
</div>
|
|
</sc-for>
|
|
<button type="button" style="min-height: 48px; background: #FCEE0A; color: #050508; border: 0; font-family: 'Rajdhani', sans-serif; font-size: 18px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; cursor: pointer; clip-path: polygon(0 0, calc(100% - 12px) 0, 100% 12px, 100% 100%, 0 100%)">Run diagnostics</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="background: #0E1016; border: 1px solid #2A2F3A; padding: 24px; display: flex; flex-direction: column; gap: 12px">
|
|
<div style="display: flex; align-items: center; gap: 12px">
|
|
<h2 style="margin: 0; font-size: 24px; font-weight: 700; text-transform: uppercase">Event log</h2>
|
|
<div style="flex: 1; height: 2px; background: #FCEE0A; max-width: 120px"></div><div style="width: 8px; height: 2px; background: #FCEE0A"></div><div style="width: 4px; height: 2px; background: #FCEE0A"></div>
|
|
</div>
|
|
<div style="overflow-x: auto">
|
|
<table style="width: 100%; min-width: 640px; border-collapse: collapse; font-family: 'JetBrains Mono', monospace; font-size: 14px">
|
|
<thead>
|
|
<tr style="text-align: left; color: #8A93A3; font-size: 12px; letter-spacing: 0.15em">
|
|
<th style="padding: 8px 12px 8px 0; font-weight: 400; border-bottom: 1px solid #2A2F3A">TIME</th>
|
|
<th style="padding: 8px 12px; font-weight: 400; border-bottom: 1px solid #2A2F3A">LEVEL</th>
|
|
<th style="padding: 8px 12px; font-weight: 400; border-bottom: 1px solid #2A2F3A">SOURCE</th>
|
|
<th style="padding: 8px 12px; font-weight: 400; border-bottom: 1px solid #2A2F3A">MESSAGE</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<sc-for list="{{logs}}" as="l" hint-placeholder-count="5">
|
|
<tr>
|
|
<td style="padding: 10px 12px 10px 0; color: #8A93A3; border-bottom: 1px solid #1C2029; white-space: nowrap">{{l.t}}</td>
|
|
<td style="padding: 10px 12px; color: {{l.color}}; border-bottom: 1px solid #1C2029; font-weight: 600">{{l.level}}</td>
|
|
<td style="padding: 10px 12px; color: #C3C8D1; border-bottom: 1px solid #1C2029">{{l.src}}</td>
|
|
<td style="padding: 10px 12px; color: #E6E8EC; border-bottom: 1px solid #1C2029">{{l.msg}}</td>
|
|
</tr>
|
|
</sc-for>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</x-dc>
|
|
<script type="text/x-dc" data-dc-script data-props='{"$preview":{"width":1440,"height":1100}}'>
|
|
class Component extends DCLogic {
|
|
renderVals() {
|
|
const meter = (n, on) => Array.from({ length: 10 }, (_, i) => (i < n ? on : '#1C2029'));
|
|
const rx = [30, 42, 38, 55, 61, 48, 72, 66, 80, 58, 64, 88];
|
|
const tx = [12, 18, 15, 22, 30, 20, 35, 28, 41, 26, 33, 46];
|
|
return {
|
|
stats: [
|
|
{ label: 'CPU LOAD', value: '42', unit: '%', color: '#E6E8EC', segs: meter(4, '#02D7F2'), note: 'NOMINAL', noteColor: '#00FF9F' },
|
|
{ label: 'MEMORY', value: '27.1', unit: 'GB', color: '#E6E8EC', segs: meter(7, '#02D7F2'), note: '68% OF 40 GB', noteColor: '#8A93A3' },
|
|
{ label: 'DISK /DEV/NVME0', value: '94', unit: '%', color: '#FF3B5C', segs: meter(9, '#FF003C'), note: '▲ ALERT // THRESHOLD 90%', noteColor: '#FF3B5C' },
|
|
{ label: 'UPTIME', value: '18', unit: 'D', color: '#FCEE0A', segs: meter(10, '#FCEE0A'), note: 'SINCE 2026-10-13', noteColor: '#8A93A3' }
|
|
],
|
|
bars: rx.map((r, i) => ({ rx: r + '%', tx: tx[i] + '%' })),
|
|
nodes: [
|
|
{ name: 'desktop', ip: '10.0.0.10', status: 'ONLINE', color: '#00FF9F' },
|
|
{ name: 'nas-01', ip: '10.0.0.20', status: 'WARN', color: '#FF3B5C' },
|
|
{ name: 'pi-dns', ip: '10.0.0.53', status: 'ONLINE', color: '#00FF9F' },
|
|
{ name: 'laptop', ip: '10.0.0.31', status: 'IDLE', color: '#8A93A3' }
|
|
],
|
|
logs: [
|
|
{ t: '22:41:07', level: 'INFO', color: '#02D7F2', src: 'pi-dns', msg: 'Blocklist refreshed' },
|
|
{ t: '22:38:52', level: 'ALERT', color: '#FF3B5C', src: 'nas-01', msg: 'Disk usage crossed 90%' },
|
|
{ t: '22:30:00', level: 'OK', color: '#00FF9F', src: 'desktop', msg: 'Nightly backup complete' },
|
|
{ t: '22:12:44', level: 'INFO', color: '#02D7F2', src: 'laptop', msg: 'Entered sleep' },
|
|
{ t: '21:58:19', level: 'ACTION', color: '#FCEE0A', src: 'desktop', msg: 'Updates ready to install' }
|
|
]
|
|
};
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|