Skip to content

Commit 223cf46

Browse files
committed
feat: add viz type tab strip for user override of LLM chart choice
Renders Table/Bar/Line/Pie/KPI buttons above query results. Defaults to the LLM's chosen vizType and resets on each new query, so users can switch views without re-running the query.
1 parent 9cbaea0 commit 223cf46

File tree

1 file changed

+24
-2
lines changed

1 file changed

+24
-2
lines changed

codebenders-dashboard/components/analysis-result.tsx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import { useState, useEffect } from "react"
12
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
3+
import { Button } from "@/components/ui/button"
24
import {
35
LineChart,
46
Line,
@@ -55,6 +57,13 @@ function formatCellValue(col: string, val: unknown): string {
5557
}
5658

5759
export function AnalysisResult({ result, plan }: AnalysisResultProps) {
60+
const [activeVizType, setActiveVizType] = useState<QueryPlan["vizType"]>(plan.vizType)
61+
62+
// Reset to LLM's choice whenever a new query arrives
63+
useEffect(() => {
64+
setActiveVizType(plan.vizType)
65+
}, [plan.vizType])
66+
5867
const renderDataTable = () => {
5968
if (!result.data || result.data.length === 0) return null
6069
const columns = Object.keys(result.data[0] || {})
@@ -98,7 +107,7 @@ export function AnalysisResult({ result, plan }: AnalysisResultProps) {
98107
const groupByKey = plan.groupBy || dataKeys[0]
99108
const metricKey = plan.metric || dataKeys.find(key => key !== groupByKey && typeof result.data[0][key] === 'number') || dataKeys[1] || 'count'
100109

101-
switch (plan.vizType) {
110+
switch (activeVizType) {
102111
case "line":
103112
return (
104113
<div className="overflow-visible">
@@ -258,8 +267,21 @@ export function AnalysisResult({ result, plan }: AnalysisResultProps) {
258267
</CardDescription>
259268
</CardHeader>
260269
<CardContent>
270+
<div className="flex gap-1 mb-3 border-b border-border pb-2">
271+
{(["table", "bar", "line", "pie", "kpi"] as const).map((type) => (
272+
<Button
273+
key={type}
274+
variant={activeVizType === type ? "secondary" : "ghost"}
275+
size="sm"
276+
onClick={() => setActiveVizType(type)}
277+
disabled={!result.data?.length && type !== "table"}
278+
>
279+
{({ table: "Table", bar: "Bar", line: "Line", pie: "Pie", kpi: "KPI" } as const)[type]}
280+
</Button>
281+
))}
282+
</div>
261283
{renderVisualization()}
262-
{plan.vizType !== "table" && result.data && result.data.length > 0 && (
284+
{activeVizType !== "table" && result.data && result.data.length > 0 && (
263285
<div className="mt-4">
264286
<p className="text-xs text-muted-foreground mb-2">Raw data ({result.rowCount} rows)</p>
265287
<div className="max-h-64 overflow-y-auto rounded-md border border-border">

0 commit comments

Comments
 (0)