replay ui fix (#56)

* refactor: rename inspect to replay across the codebase

Renames inspect-ui/ to replay-ui/, internal/inspect/ to internal/replay/,
the CLI subcommand from `sanderling inspect` to `sanderling replay`, and
updates all references in docs, Makefile, README, and Go comments.

* feat(replay-ui): show spec filename with full path on hover

RunList and RunDetail now render the basename of spec_path (e.g.
login.spec.ts) with the full path available as a title tooltip.
This commit is contained in:
pj authored and GitHub committed 2026-06-03 16:17:26 +05:30
1 parent a6f43e15b2
commit b44077afde
71 files changed
+104 -92

No files matched your search

+88
View File
@@ -0,0 +1,88 @@
import type { ResidualNode } from "../types";
import "./ResidualNode.css";
export interface ResidualNodeProps {
node: ResidualNode;
}
function OperatorLabel({ children }: { children: string }) {
return <span className="op-label">{children}</span>;
}
function Wrapped({ node }: { node: ResidualNode }) {
return (
<span className="residual-group">
(<ResidualNodeView node={node} />)
</span>
);
}
function ResidualNodeView({ node }: ResidualNodeProps) {
switch (node.op) {
case "true":
return <span className="residual-leaf">true</span>;
case "false":
return <span className="residual-leaf">false</span>;
case "predicate":
return (
<span className="residual-leaf">
<OperatorLabel>pred</OperatorLabel>
{node.name ? <>({node.name})</> : null}
</span>
);
case "error":
return (
<span className="residual-error" role="status">
<OperatorLabel>error</OperatorLabel>
<span className="residual-error-message">{node.message}</span>
</span>
);
case "always":
case "now":
case "next":
case "not":
return (
<span className="residual-unary">
<OperatorLabel>{node.op}</OperatorLabel>
<Wrapped node={node.arg} />
</span>
);
case "eventually":
return (
<span className="residual-unary">
<OperatorLabel>eventually</OperatorLabel>
{node.within ? (
<span className="residual-bound">
within {node.within.amount} {node.within.unit}
</span>
) : null}
<Wrapped node={node.arg} />
</span>
);
case "and":
case "or":
return (
<span className="residual-binary">
<Wrapped node={node.left} />
<OperatorLabel>{node.op}</OperatorLabel>
<Wrapped node={node.right} />
</span>
);
case "implies":
return (
<span className="residual-binary">
<Wrapped node={node.left} />
<OperatorLabel>{"=>"}</OperatorLabel>
<Wrapped node={node.right} />
</span>
);
}
}
export default function ResidualNodeRoot({ node }: ResidualNodeProps) {
return (
<span className="residual">
<ResidualNodeView node={node} />
</span>
);
}