fix(frontend): finish the token migration — raw grey classes -> theme tokens
UI_REDESIGN chunk 4 was never finished: 39 app/component files still used raw Tailwind greys, kept readable in light mode only by the !important override sheet. In dark mode text-gray-600 is ~2.3:1 on surface, and the light override maps it to #94a3b8 (~2.6:1 on white) — unreadable in both. Mechanical mapping (886 classes): gray-100/200 -> ink, 300/400 -> ink-2, 500/600/700 -> ink-muted, bg 950/900/800 -> page/surface/raised, border 800 -> line, 700/600 -> line-strong, plus hover/divide/placeholder. Alpha suffixes kept (tokens are color-mix, so /60 works). bg-gray-700, text-white and marketing pages left alone. text-[9px] -> text-[10px]. Frontend unverified: no Node on the authoring box (#207). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
3968b49b80
commit
bf206334e3
@@ -114,7 +114,7 @@ function EnrollmentTokensPanel() {
|
||||
</p>
|
||||
|
||||
<div className="flex items-start gap-2">
|
||||
<p className="flex-1 text-xs text-indigo-100 font-mono break-all bg-gray-900 rounded px-2 py-1.5">{justMinted}</p>
|
||||
<p className="flex-1 text-xs text-indigo-100 font-mono break-all bg-surface rounded px-2 py-1.5">{justMinted}</p>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigator.clipboard?.writeText(justMinted).then(() => {
|
||||
@@ -133,7 +133,7 @@ function EnrollmentTokensPanel() {
|
||||
: <>(check the broker host)</>}:
|
||||
</p>
|
||||
<div className="flex items-start gap-2">
|
||||
<pre className="flex-1 text-xs text-indigo-100 font-mono whitespace-pre-wrap break-all bg-gray-900 rounded px-2 py-1.5">{installCmd}</pre>
|
||||
<pre className="flex-1 text-xs text-indigo-100 font-mono whitespace-pre-wrap break-all bg-surface rounded px-2 py-1.5">{installCmd}</pre>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => navigator.clipboard?.writeText(installCmd).then(() => {
|
||||
@@ -163,7 +163,7 @@ function EnrollmentTokensPanel() {
|
||||
value={label}
|
||||
onChange={(e) => setLabel(e.target.value)}
|
||||
placeholder="Node ID, e.g. node-003"
|
||||
className="flex-1 min-w-[12rem] bg-gray-800 border border-gray-700 rounded-lg px-3 py-1.5 text-white text-sm focus:outline-none focus:border-indigo-500"
|
||||
className="flex-1 min-w-[12rem] bg-raised border border-line-strong rounded-lg px-3 py-1.5 text-white text-sm focus:outline-none focus:border-indigo-500"
|
||||
/>
|
||||
<Button type="submit" size="sm" disabled={minting || !label.trim()}>
|
||||
{minting ? "Minting…" : "New token"}
|
||||
@@ -176,11 +176,11 @@ function EnrollmentTokensPanel() {
|
||||
<SkeletonRow cols={1} />
|
||||
</div>
|
||||
) : tokens.length === 0 ? (
|
||||
<p className="text-gray-600 text-xs">No enrollment tokens yet.</p>
|
||||
<p className="text-ink-muted text-xs">No enrollment tokens yet.</p>
|
||||
) : (
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="text-xs text-gray-500 uppercase tracking-wider border-b border-gray-800">
|
||||
<tr className="text-xs text-ink-muted uppercase tracking-wider border-b border-line">
|
||||
<th className="py-2 text-left">Label</th>
|
||||
<th className="py-2 text-left hidden sm:table-cell">Created</th>
|
||||
<th className="py-2 text-left">Status</th>
|
||||
@@ -189,14 +189,14 @@ function EnrollmentTokensPanel() {
|
||||
</thead>
|
||||
<tbody>
|
||||
{tokens.map((t) => (
|
||||
<tr key={t.token_id} className="border-b border-gray-800 last:border-0">
|
||||
<tr key={t.token_id} className="border-b border-line last:border-0">
|
||||
<td className="py-2 text-white">{t.label}</td>
|
||||
<td className="py-2 text-gray-500 text-xs hidden sm:table-cell">
|
||||
<td className="py-2 text-ink-muted text-xs hidden sm:table-cell">
|
||||
{new Date(t.created_at).toLocaleDateString()}
|
||||
</td>
|
||||
<td className="py-2 text-xs">
|
||||
{t.revoked ? (
|
||||
<span className="text-gray-600">Revoked</span>
|
||||
<span className="text-ink-muted">Revoked</span>
|
||||
) : (
|
||||
<span className="text-green-400">Active · {t.uses} use{t.uses !== 1 ? "s" : ""}</span>
|
||||
)}
|
||||
@@ -283,7 +283,7 @@ export default function NodeOwnershipSettingsPage() {
|
||||
<EnrollmentTokensPanel />
|
||||
|
||||
<div className="space-y-4">
|
||||
<p className="text-sm text-gray-500">
|
||||
<p className="text-sm text-ink-muted">
|
||||
Assign each node to the operator responsible for it. Operators only see and manage the nodes assigned to them here.
|
||||
</p>
|
||||
|
||||
@@ -292,7 +292,7 @@ export default function NodeOwnershipSettingsPage() {
|
||||
<Card padding="none" className="overflow-hidden">
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="text-xs text-gray-500 uppercase tracking-wider border-b border-gray-800 bg-gray-900">
|
||||
<tr className="text-xs text-ink-muted uppercase tracking-wider border-b border-line bg-surface">
|
||||
<th className="px-4 py-3 text-left">Node</th>
|
||||
<th className="px-4 py-3 text-left hidden sm:table-cell">Status</th>
|
||||
<th className="px-4 py-3 text-left">Owner</th>
|
||||
@@ -302,17 +302,17 @@ export default function NodeOwnershipSettingsPage() {
|
||||
{loading ? (
|
||||
Array.from({ length: 3 }).map((_, i) => <SkeletonRow key={i} cols={3} />)
|
||||
) : nodes.length === 0 ? (
|
||||
<tr><td colSpan={3} className="px-4 py-8 text-center text-gray-600 text-sm">No nodes registered yet.</td></tr>
|
||||
<tr><td colSpan={3} className="px-4 py-8 text-center text-ink-muted text-sm">No nodes registered yet.</td></tr>
|
||||
) : (
|
||||
nodes.map((n) => {
|
||||
const owner = ownerByNode.get(n.node_id);
|
||||
return (
|
||||
<tr key={n.node_id} className="border-b border-gray-800 last:border-0">
|
||||
<tr key={n.node_id} className="border-b border-line last:border-0">
|
||||
<td className="px-4 py-3">
|
||||
<Link href={`/nodes/${n.node_id}`} className="text-white hover:text-indigo-300 transition-colors">
|
||||
{n.name}
|
||||
</Link>
|
||||
<p className="text-gray-600 text-xs font-mono">{n.node_id}</p>
|
||||
<p className="text-ink-muted text-xs font-mono">{n.node_id}</p>
|
||||
</td>
|
||||
<td className="px-4 py-3 hidden sm:table-cell"><StatusBadge status={n.status} /></td>
|
||||
<td className="px-4 py-3">
|
||||
@@ -320,7 +320,7 @@ export default function NodeOwnershipSettingsPage() {
|
||||
value={owner?.uid ?? UNASSIGNED}
|
||||
disabled={savingNodeId === n.node_id}
|
||||
onChange={(e) => reassign(n.node_id, e.target.value)}
|
||||
className="bg-gray-800 border border-gray-700 rounded-lg px-2 py-1.5 text-xs text-white focus:outline-none focus:border-indigo-500 disabled:opacity-50 max-w-[14rem]"
|
||||
className="bg-raised border border-line-strong rounded-lg px-2 py-1.5 text-xs text-white focus:outline-none focus:border-indigo-500 disabled:opacity-50 max-w-[14rem]"
|
||||
>
|
||||
<option value={UNASSIGNED}>Unassigned</option>
|
||||
{assignable.map((u) => (
|
||||
|
||||
Reference in New Issue
Block a user