59 lines
2.0 KiB
TypeScript
59 lines
2.0 KiB
TypeScript
import Link from "next/link";
|
|
import clsx from "clsx";
|
|
import type { ReactNode } from "react";
|
|
|
|
const TONE = {
|
|
expired: "border-l-expired text-expired",
|
|
warn: "border-l-warn text-warn",
|
|
accent: "border-l-accent text-accent",
|
|
} as const;
|
|
|
|
export function Queue({
|
|
title,
|
|
count,
|
|
tone,
|
|
items,
|
|
}: {
|
|
title: string;
|
|
count: number;
|
|
tone: keyof typeof TONE;
|
|
/* `meta` is a node rather than a string so a queue about time can carry the
|
|
* term measurement itself. A tier name told the reader what the instance
|
|
* was; the queue is sorted by how soon it lapses, and that was the one
|
|
* figure the row did not show. */
|
|
items: { label: string; href: string; meta: ReactNode }[];
|
|
}) {
|
|
return (
|
|
<section
|
|
className={clsx(
|
|
"grid gap-2 rounded border border-l-4 border-rule bg-panel p-4",
|
|
TONE[tone],
|
|
)}
|
|
>
|
|
<h2 className="font-mono text-[0.72rem] font-normal uppercase tracking-[0.1em] text-ink-3">
|
|
{title}
|
|
</h2>
|
|
<p className="text-3xl font-extrabold leading-none tabular-nums tracking-[-0.03em]">
|
|
{count}
|
|
</p>
|
|
{items.length === 0 ? (
|
|
<p className="text-[0.72rem] text-ink-3">Nothing to do here.</p>
|
|
) : (
|
|
<ul className="grid gap-1">
|
|
{items.map((i) => (
|
|
<li
|
|
key={i.href}
|
|
className="flex items-center justify-between gap-2 font-mono text-[0.72rem] text-ink-2"
|
|
>
|
|
<Link href={i.href} className="truncate text-accent underline">
|
|
{i.label}
|
|
</Link>
|
|
<span className="shrink-0 tabular-nums">{i.meta}</span>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</section>
|
|
);
|
|
}
|