rebuild the web theme as a physical desk (walnut surface, monitor + keyboard, real rack, drive drawer, paper tags, dot-matrix report, brass plaques)
This commit is contained in:
parent
dd6aeb5486
commit
cfc256c7bd
9 changed files with 1604 additions and 869 deletions
|
|
@ -31,7 +31,7 @@ export function Reveal({
|
|||
}
|
||||
}
|
||||
},
|
||||
{ rootMargin: "0px 0px -12% 0px", threshold: 0.08 }
|
||||
{ rootMargin: "0px 0px -12% 0px", threshold: 0.06 }
|
||||
);
|
||||
|
||||
const rect = el.getBoundingClientRect();
|
||||
|
|
@ -58,51 +58,132 @@ export function Reveal({
|
|||
/* ------------------------------------------------------------- hardware */
|
||||
|
||||
export function Led({
|
||||
kind = "green",
|
||||
kind = "on",
|
||||
pulse = false,
|
||||
slow = false,
|
||||
className = "",
|
||||
title,
|
||||
style,
|
||||
}: {
|
||||
kind?: "green" | "amber" | "red" | "blue" | "off";
|
||||
kind?: "on" | "amber" | "off";
|
||||
pulse?: boolean;
|
||||
slow?: boolean;
|
||||
className?: string;
|
||||
title?: string;
|
||||
style?: CSSProperties;
|
||||
}) {
|
||||
return (
|
||||
<span
|
||||
className={`w-led w-led--${kind}${pulse ? " w-led--pulse" : ""} ${className}`}
|
||||
title={title}
|
||||
<i
|
||||
aria-hidden="true"
|
||||
className={`w-led w-led--${kind}${pulse ? (slow ? " w-led--pulse-slow" : " w-led--pulse") : ""} ${className}`}
|
||||
style={style}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Section header, mounted on the chassis. */
|
||||
export function Bay({
|
||||
id,
|
||||
index,
|
||||
label,
|
||||
title,
|
||||
children,
|
||||
}: {
|
||||
id: string;
|
||||
index: string;
|
||||
label: string;
|
||||
title: ReactNode;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
export function Screws({ count = 2, brass = false, className = "" }: { count?: number; brass?: boolean; className?: string }) {
|
||||
return (
|
||||
<section id={id} className="scroll-mt-28">
|
||||
<Reveal>
|
||||
<div className="flex flex-wrap items-center gap-x-4 gap-y-3">
|
||||
<span className="w-plate">
|
||||
{index} <span className="opacity-50">/</span> {label}
|
||||
<span className={`w-unit__screws ${className}`}>
|
||||
{Array.from({ length: count }).map((_, i) => (
|
||||
<i key={i} className={`w-screw${brass ? " w-screw--brass" : ""}`} />
|
||||
))}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
/** Section heading: a brass tab screwed to the desk + painted title. */
|
||||
export function SectionHead({ index, label, title }: { index: string; label: string; title: string }) {
|
||||
return (
|
||||
<div className="w-sechead">
|
||||
<span className="w-mt-brass w-sechead__tab">{index} · {label}</span>
|
||||
<h2 className="w-serif w-paint w-sechead__title">{title}</h2>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------- the machine */
|
||||
|
||||
export function Monitor({ children, className = "" }: { children: ReactNode; className?: string }) {
|
||||
return (
|
||||
<div className={`w-monitor ${className}`}>
|
||||
<div className="w-monitor__frame">
|
||||
<div className="w-mt-glass w-monitor__glass">{children}</div>
|
||||
<div className="w-monitor__chin">
|
||||
<Led kind="amber" />
|
||||
<span className="w-monitor__brand">DXD</span>
|
||||
<span className="w-monitor__osd" aria-hidden="true">
|
||||
<i className="w-osdkey" />
|
||||
<i className="w-osdkey" />
|
||||
<i className="w-osdkey" />
|
||||
</span>
|
||||
<h2 className="w-serif text-[1.6rem] sm:text-[2rem]">{title}</h2>
|
||||
</div>
|
||||
</Reveal>
|
||||
<div className="mt-8">{children}</div>
|
||||
</section>
|
||||
</div>
|
||||
<div className="w-monitor__stand" aria-hidden="true">
|
||||
<i className="w-monitor__neck" />
|
||||
<i className="w-monitor__base" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const KEY_ROWS = ["1234567890-=".split(""), "qwertyuiop[]".split(""), "asdfghjkl;'".split("")];
|
||||
|
||||
export function Keyboard() {
|
||||
return (
|
||||
<div className="w-keyboard" aria-hidden="true">
|
||||
<div className="w-keyboard__deck">
|
||||
{KEY_ROWS.map((row, i) => (
|
||||
<div key={i} className="w-keyboard__row">
|
||||
{row.map((k) => (
|
||||
<span key={k} className="w-key">
|
||||
{k}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
<div className="w-keyboard__row">
|
||||
<span className="w-key w-key--space" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** A small rack that sits on the desk in the hero. */
|
||||
export function MiniRack({ label = "DXD-01" }: { label?: string }) {
|
||||
return (
|
||||
<div className="w-rack w-mt-metal" aria-hidden="true">
|
||||
<div className="w-rack__top">
|
||||
<Led kind="on" pulse />
|
||||
<span className="w-engrave text-[0.62rem] tracking-[0.2em]">{label}</span>
|
||||
<span className="w-rack__vent w-vents" />
|
||||
</div>
|
||||
<div className="w-rack__grid">
|
||||
<span className="w-rails" />
|
||||
<div>
|
||||
{[0, 1, 2, 3].map((i) => (
|
||||
<div key={i} className="w-unit !min-h-[46px] !gap-[10px] !py-2">
|
||||
<span className="w-unit__grille !h-6 !w-9" />
|
||||
<Led kind="on" pulse style={{ animationDelay: `${i * 0.5}s` }} />
|
||||
<Led kind="amber" pulse slow style={{ animationDelay: `${i * 0.3}s` }} />
|
||||
<span className="ml-auto w-engrave text-[0.58rem] tracking-[0.14em]">
|
||||
{["pxe", "aio", "nas", "web"][i]}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<span className="w-rails" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** A brass plate with one number stamped into it. */
|
||||
export function Plaque({ value, label }: { value: string; label: string }) {
|
||||
return (
|
||||
<div className="w-mt-brass w-plaque relative">
|
||||
<span className="w-plaque__value">{value}</span>
|
||||
<span className="w-plaque__label">{label}</span>
|
||||
<i className="w-screw w-screw--brass w-plaque__screw" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -143,17 +224,10 @@ export function ServiceUnit({
|
|||
};
|
||||
}, [url, checkUrl, disabled]);
|
||||
|
||||
const effective = disabled ? "up" : status;
|
||||
const kind = effective === "up" ? "green" : effective === "down" ? "red" : "off";
|
||||
const statusLabel = disabled
|
||||
? "standby"
|
||||
: effective === "up"
|
||||
? "online"
|
||||
: effective === "down"
|
||||
? "offline"
|
||||
: "checking";
|
||||
const accessLabel =
|
||||
access === "public" ? "public" : access === "private" ? "private" : access === "on_request" ? "on request" : null;
|
||||
const live = disabled ? "up" : status;
|
||||
const kind = live === "up" ? "on" : live === "down" ? "off" : "amber";
|
||||
const label = disabled ? "STANDBY" : live === "up" ? "ONLINE" : live === "down" ? "OFFLINE" : "POLLING";
|
||||
const accessLabel = access === "public" ? "public" : access === "private" ? "private" : access === "on_request" ? "on request" : null;
|
||||
|
||||
const host = (() => {
|
||||
try {
|
||||
|
|
@ -165,42 +239,39 @@ export function ServiceUnit({
|
|||
|
||||
const inner = (
|
||||
<>
|
||||
<span className="w-unit__leds">
|
||||
<Led kind={kind} pulse={effective === "up"} />
|
||||
<Led kind="amber" pulse={effective === "up"} />
|
||||
</span>
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="w-unit__name block truncate">{name}</span>
|
||||
<span className="w-unit__meta block truncate">
|
||||
{host} {accessLabel ? `· ${accessLabel}` : ""}
|
||||
<span className="w-unit__grip" aria-hidden="true" />
|
||||
<span className="w-unit__grille w-grille" aria-hidden="true" />
|
||||
<span className="w-unit__id">
|
||||
<span className="w-unit__name w-engrave">{name}</span>
|
||||
<span className="w-tape mt-1">
|
||||
{host}
|
||||
{accessLabel ? ` · ${accessLabel}` : ""}
|
||||
</span>
|
||||
<span className="sr-only">{desc}</span>
|
||||
</span>
|
||||
<span className="hidden text-right sm:block">
|
||||
<span className="w-unit__meta block max-w-[26ch] truncate">{desc}</span>
|
||||
</span>
|
||||
<span className="w-plate shrink-0">
|
||||
<Led kind={kind} /> {statusLabel}
|
||||
<span className="w-unit__state">
|
||||
<Led kind={kind} pulse={live === "up"} />
|
||||
<span className="w-unit__status w-engrave">{label}</span>
|
||||
</span>
|
||||
<Screws />
|
||||
</>
|
||||
);
|
||||
|
||||
const cls = "w-unit w-metal-flat";
|
||||
|
||||
if (disabled) {
|
||||
return (
|
||||
<span className={cls} aria-disabled="true">
|
||||
<span className="w-unit" aria-disabled="true">
|
||||
{inner}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<a href={url} target="_blank" rel="noopener noreferrer" className={`${cls} w-unit--link`}>
|
||||
<a href={url} target="_blank" rel="noopener noreferrer" className="w-unit w-unit--link" title={desc}>
|
||||
{inner}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------- contributions */
|
||||
/* -------------------------------------------------------- activity report */
|
||||
|
||||
interface HeatmapPoint {
|
||||
timestamp: number;
|
||||
|
|
@ -213,7 +284,9 @@ interface Activity {
|
|||
repo?: { full_name?: string };
|
||||
}
|
||||
|
||||
export function ContributionsPanel() {
|
||||
const DOT_OPACITY = [0.07, 0.3, 0.48, 0.64, 0.82];
|
||||
|
||||
export function Report() {
|
||||
const [weeks, setWeeks] = useState<{ date: string; contribs: number; level: number }[][]>([]);
|
||||
const [total, setTotal] = useState(0);
|
||||
const [activities, setActivities] = useState<Activity[]>([]);
|
||||
|
|
@ -291,50 +364,52 @@ export function ContributionsPanel() {
|
|||
};
|
||||
}, []);
|
||||
|
||||
// level 4 = brightest LED, level 0 = off
|
||||
const levelOn = (l: number) => (l <= 0 ? "0" : String(5 - l));
|
||||
|
||||
return (
|
||||
<div className="w-dashboard w-metal">
|
||||
<div className="w-rack__head">
|
||||
<span className="w-rack__title">gitdxd.activity</span>
|
||||
<span className="ml-auto flex items-center gap-2">
|
||||
<Led kind={state === "error" ? "red" : "green"} pulse={state === "ready"} />
|
||||
<span className="w-unit__meta">{state === "error" ? "link down" : "streaming"}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-printout">
|
||||
<div className="w-mt-paper w-printout__paper">
|
||||
<span className="w-printout__perf w-printout__perf--l" aria-hidden="true" />
|
||||
<span className="w-printout__perf w-printout__perf--r" aria-hidden="true" />
|
||||
|
||||
<div className="mt-4 flex flex-wrap items-end justify-between gap-3">
|
||||
<div className="w-digits text-[2rem] leading-none sm:text-[2.5rem]">{total}</div>
|
||||
<div className="w-kicker">contributions / last year</div>
|
||||
</div>
|
||||
<p className="w-print__head">
|
||||
<span>GITDXD // ACTIVITY REPORT</span>
|
||||
<span className="ml-auto">{state === "ready" ? "PRINTED LIVE" : state === "error" ? "PRINTER OFFLINE" : "SPOOLING…"}</span>
|
||||
</p>
|
||||
|
||||
{state === "loading" ? (
|
||||
<p className="w-screen-text mt-5 opacity-70">reading matrix…</p>
|
||||
) : state === "error" ? (
|
||||
<p className="w-screen-text mt-5 opacity-70">could not reach the forge.</p>
|
||||
) : (
|
||||
<>
|
||||
<div className="w-ledgrid mt-5">
|
||||
{weeks.map((w, i) => (
|
||||
<div key={i} className="w-ledgrid__col">
|
||||
{w.map((d) => (
|
||||
<div key={d.date} className="w-ledgrid__cell" data-on={levelOn(d.level)} title={`${d.contribs} on ${d.date}`} />
|
||||
))}
|
||||
{state === "error" ? (
|
||||
<p className="w-mono mt-5 text-[0.72rem] text-[#4a4133]">could not reach the forge.</p>
|
||||
) : (
|
||||
<>
|
||||
<div className="mt-5 flex flex-wrap items-end gap-x-6 gap-y-2">
|
||||
<div>
|
||||
<p className="w-mono text-[0.62rem] tracking-[0.16em] text-[#4a4133]">TOTAL / 12 MONTHS</p>
|
||||
<p className="w-serif text-[2.6rem] leading-none text-[var(--ink)]">
|
||||
{state === "loading" ? "—" : total}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="mt-3 flex items-center justify-end gap-2">
|
||||
<span className="w-unit__meta">less</span>
|
||||
{[4, 3, 2, 1, 0].map((l) => (
|
||||
<span key={l} className="w-ledgrid__cell" data-on={levelOn(l)} />
|
||||
))}
|
||||
<span className="w-unit__meta">more</span>
|
||||
</div>
|
||||
<p className="w-mono text-[0.62rem] leading-relaxed text-[#6f6450]">
|
||||
each dot = one day
|
||||
<br />
|
||||
darkest = busiest
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{activities.length > 0 ? (
|
||||
<div className="w-panel mt-5 p-3">
|
||||
<div className="w-screen-text">
|
||||
<div className="w-dotgrid w-scroll" aria-hidden={state === "loading"}>
|
||||
{weeks.map((w, i) => (
|
||||
<span key={i} className="w-dotgrid__col">
|
||||
{w.map((d) => (
|
||||
<span
|
||||
key={d.date}
|
||||
className="w-dot"
|
||||
style={{ opacity: DOT_OPACITY[d.level] }}
|
||||
title={`${d.contribs} on ${d.date}`}
|
||||
/>
|
||||
))}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{activities.length > 0 ? (
|
||||
<div className="w-print__log">
|
||||
{activities.map((a, i) => {
|
||||
let msg = "commit";
|
||||
try {
|
||||
|
|
@ -353,15 +428,15 @@ export function ContributionsPanel() {
|
|||
}
|
||||
return (
|
||||
<p key={i} className="truncate">
|
||||
<span className="k">$</span> {a.repo?.full_name || "unknown"} — {msg}
|
||||
> {a.repo?.full_name || "unknown"} — {msg}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
) : null}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue