diff --git a/decnet_web/src/components/MazeNET/MazeNET.css b/decnet_web/src/components/MazeNET/MazeNET.css index a8c98492..1f21e5a5 100644 --- a/decnet_web/src/components/MazeNET/MazeNET.css +++ b/decnet_web/src/components/MazeNET/MazeNET.css @@ -199,6 +199,21 @@ body.maze-fullscreen .maze-shell { opacity: 0.42; filter: grayscale(0.7); border-style: dotted; } .maze-net-box.inactive .maze-net-box-head { color: rgba(255, 255, 255, 0.5); } +/* Optimistic placeholder for an enqueued LAN-add. Amber tint matches + * the REAP button voice — clearly "in-flight, not committed" without + * collapsing into the dimmed-out 'inactive' style which means the + * opposite (no traffic on a deployed LAN). */ +.maze-net-box.pending { + border-color: var(--warn, #e0a040); + background: rgba(224, 160, 64, 0.04); + border-style: dashed; + filter: none; opacity: 1; +} +.maze-net-box.pending .maze-net-box-head { + color: var(--warn, #e0a040); + border-bottom-color: rgba(224, 160, 64, 0.45); +} +.maze-net-box.pending .cidr { color: rgba(224, 160, 64, 0.7); } .maze-net-box-head { position: absolute; top: 0; left: 0; right: 0; padding: 6px 12px; border-bottom: 1px dashed var(--border); diff --git a/decnet_web/src/components/MazeNET/MazeNET.tsx b/decnet_web/src/components/MazeNET/MazeNET.tsx index 13dedb99..f2f4d080 100644 --- a/decnet_web/src/components/MazeNET/MazeNET.tsx +++ b/decnet_web/src/components/MazeNET/MazeNET.tsx @@ -138,7 +138,7 @@ const MazeNET: React.FC = () => { setNets((p) => [...p, { id: tempId, name, label: name.toUpperCase(), cidr: subnet ?? '', kind: isDmz ? 'dmz' : 'subnet', - x, y, w, h, + x, y, w, h, pending: true, }]); return; } diff --git a/decnet_web/src/components/MazeNET/NetBox.tsx b/decnet_web/src/components/MazeNET/NetBox.tsx index c8787398..666bb837 100644 --- a/decnet_web/src/components/MazeNET/NetBox.tsx +++ b/decnet_web/src/components/MazeNET/NetBox.tsx @@ -27,6 +27,7 @@ const NetBox: React.FC = ({ dropTarget ? 'drop-target' : '', inactive ? 'inactive' : '', deployed ? 'deployed' : '', + net.pending ? 'pending' : '', ].filter(Boolean).join(' '); const Icon = net.kind === 'internet' ? Globe : net.kind === 'dmz' ? ShieldAlert : GitMerge; @@ -53,12 +54,20 @@ const NetBox: React.FC = ({
{net.label} - {inactive && ( + {inactive && !net.pending && ( INACTIVE )} + {net.pending && ( + + PENDING + + )}
{net.cidr} diff --git a/decnet_web/src/components/MazeNET/types.ts b/decnet_web/src/components/MazeNET/types.ts index c113d238..a25d9e76 100644 --- a/decnet_web/src/components/MazeNET/types.ts +++ b/decnet_web/src/components/MazeNET/types.ts @@ -15,6 +15,11 @@ export interface Net { y: number; w: number; h: number; + /** Optimistic placeholder for an enqueued mutation on a live + * topology. Replaced on next refetch when the mutator emits the + * applied event. Rendered with an amber tint so the user can tell + * it's a queued add, not a regular non-deployed LAN. */ + pending?: boolean; } export type NodeKind = 'decky' | 'observed';