diff --git a/frontend/src/expr/JsonTree.test.tsx b/frontend/src/expr/JsonTree.test.tsx index b0aec2c..3b69d7e 100644 --- a/frontend/src/expr/JsonTree.test.tsx +++ b/frontend/src/expr/JsonTree.test.tsx @@ -65,4 +65,19 @@ describe("JsonTree", () => { render(); expect(screen.getByText(/no data/i)).toBeInTheDocument(); }); + + it("renders a bare string root as a visible quoted value", () => { + render(); + expect(screen.getByText("hello")).toBeInTheDocument(); + }); + + it("renders a bare number root", () => { + render(); + expect(screen.getByText("42")).toBeInTheDocument(); + }); + + it("renders a bare boolean root", () => { + render(); + expect(screen.getByText("true")).toBeInTheDocument(); + }); }); diff --git a/frontend/src/expr/JsonTree.tsx b/frontend/src/expr/JsonTree.tsx index 9e0f43b..e4753e2 100644 --- a/frontend/src/expr/JsonTree.tsx +++ b/frontend/src/expr/JsonTree.tsx @@ -33,6 +33,27 @@ interface NodeProps { function Node({ label, value, path, depth, pickable, onPick }: NodeProps) { // Root — render children as top-level rows without a wrapping expando. if (depth === 0) { + // Scalar root (string/number/bool): render as a single labelless leaf so + // e.g. `output = "hello"` shows the value. Without this branch, scalar + // roots would render as an empty
    because renderChildren only handles + // arrays and objects. + if (!Array.isArray(value) && !(value !== null && typeof value === "object")) { + return ( +
      +
    • + {typeof value === "string" ? ( + <> + " + {value} + " + + ) : ( + {leafPreview(value)} + )} +
    • +
    + ); + } return (
      {renderChildren(value, path, depth, pickable, onPick)}