Skip to content

Commit 4d6c596

Browse files
author
Dylan Huang
committed
Refactor table components for consistency and improved styling
- Introduced a new TableContainer component to standardize table layout and styling across the application. - Replaced traditional HTML table elements in EvaluationRow, EvaluationTable, and PivotTable with the new TableContainer, TableHeader, TableCell, TableRow, and TableRowInteractive components for better maintainability and visual consistency. - Enhanced the table structure to support additional styling options and improve responsiveness.
1 parent ffee4e0 commit 4d6c596

4 files changed

Lines changed: 322 additions & 97 deletions

File tree

vite-app/src/components/EvaluationRow.tsx

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { ChatInterface } from "./ChatInterface";
44
import { MetadataSection } from "./MetadataSection";
55
import StatusIndicator from "./StatusIndicator";
66
import { state } from "../App";
7+
import { TableCell, TableRowInteractive } from "./TableContainer";
78

89
// Small, focused components following "dereference values late" principle
910
const ExpandIcon = observer(({ rolloutId }: { rolloutId?: string }) => {
@@ -204,48 +205,45 @@ export const EvaluationRow = observer(
204205
return (
205206
<>
206207
{/* Main Table Row */}
207-
<tr
208-
className="hover:bg-gray-50 cursor-pointer text-sm border-b border-gray-200"
209-
onClick={toggleExpanded}
210-
>
208+
<TableRowInteractive onClick={toggleExpanded}>
211209
{/* Expand/Collapse Icon */}
212-
<td className="px-3 py-3 w-8">
210+
<TableCell className="w-8 py-3">
213211
<ExpandIcon rolloutId={rolloutId} />
214-
</td>
212+
</TableCell>
215213

216214
{/* Name */}
217-
<td className="px-3 py-3 text-xs">
215+
<TableCell className="py-3 text-xs">
218216
<RowName name={row.eval_metadata?.name} />
219-
</td>
217+
</TableCell>
220218

221219
{/* Status */}
222-
<td className="px-3 py-3 text-xs">
220+
<TableCell className="py-3 text-xs">
223221
<RowStatus
224222
status={row.eval_metadata?.status}
225223
showSpinner={row.eval_metadata?.status === "running"}
226224
/>
227-
</td>
225+
</TableCell>
228226

229227
{/* Rollout ID */}
230-
<td className="px-3 py-3 text-xs">
228+
<TableCell className="py-3 text-xs">
231229
<RolloutId rolloutId={row.rollout_id} />
232-
</td>
230+
</TableCell>
233231

234232
{/* Model */}
235-
<td className="px-3 py-3 text-xs">
236-
<RowModel model={row.input_metadata.completion_params?.model} />
237-
</td>
233+
<TableCell className="py-3 text-xs">
234+
<RowName name={row.input_metadata.completion_params?.model} />
235+
</TableCell>
238236

239237
{/* Score */}
240-
<td className="px-3 py-3 text-xs">
238+
<TableCell className="py-3 text-xs">
241239
<RowScore score={row.evaluation_result?.score} />
242-
</td>
240+
</TableCell>
243241

244242
{/* Created */}
245-
<td className="px-3 py-3 text-xs">
243+
<TableCell className="py-3 text-xs">
246244
<RowCreated created_at={row.created_at} />
247-
</td>
248-
</tr>
245+
</TableCell>
246+
</TableRowInteractive>
249247

250248
{/* Expanded Content Row */}
251249
{isExpanded && (

vite-app/src/components/EvaluationTable.tsx

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { state } from "../App";
44
import { EvaluationRow } from "./EvaluationRow";
55
import Button from "./Button";
66
import Select from "./Select";
7+
import TableContainer, { TableHeader, TableHead } from "./TableContainer";
78

89
const TableBody = observer(
910
({ currentPage, pageSize }: { currentPage: number; pageSize: number }) => {
@@ -50,7 +51,7 @@ export const EvaluationTable = observer(() => {
5051
}, [totalRows]);
5152

5253
return (
53-
<div className="bg-white border border-gray-200 overflow-x-auto">
54+
<TableContainer>
5455
{/* Pagination Controls */}
5556
<div className="px-3 py-2 border-b border-gray-200 bg-gray-50 flex items-center justify-between">
5657
<div className="flex items-center gap-4">
@@ -112,35 +113,21 @@ export const EvaluationTable = observer(() => {
112113

113114
<table className="w-full min-w-max">
114115
{/* Table Header */}
115-
<thead className="bg-gray-50 border-b border-gray-200">
116+
<TableHead>
116117
<tr>
117-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700 w-8">
118-
{/* Expand/Collapse column */}
119-
</th>
120-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700">
121-
Name
122-
</th>
123-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700">
124-
Status
125-
</th>
126-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700">
127-
Rollout ID
128-
</th>
129-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700">
130-
Model
131-
</th>
132-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700">
133-
Score
134-
</th>
135-
<th className="px-3 py-2 text-left text-xs font-semibold text-gray-700">
136-
Created
137-
</th>
118+
<TableHeader className="w-8">&nbsp;</TableHeader>
119+
<TableHeader>Name</TableHeader>
120+
<TableHeader>Status</TableHeader>
121+
<TableHeader>Rollout ID</TableHeader>
122+
<TableHeader>Model</TableHeader>
123+
<TableHeader>Score</TableHeader>
124+
<TableHeader>Created</TableHeader>
138125
</tr>
139-
</thead>
126+
</TableHead>
140127

141128
{/* Table Body */}
142129
<TableBody currentPage={currentPage} pageSize={pageSize} />
143130
</table>
144-
</div>
131+
</TableContainer>
145132
);
146133
});

vite-app/src/components/PivotTable.tsx

Lines changed: 33 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import React from "react";
22
import { computePivot } from "../util/pivot";
3+
import TableContainer, {
4+
TableHeader,
5+
TableCell,
6+
TableHead,
7+
TableBody,
8+
TableRow,
9+
} from "./TableContainer";
310

411
/**
512
* Props for PivotTable.
@@ -93,106 +100,80 @@ export function PivotTable<T extends Record<string, unknown>>({
93100
});
94101

95102
return (
96-
<div
97-
className={`bg-white border border-gray-200 overflow-x-auto ${className}`}
98-
>
103+
<TableContainer className={className}>
99104
<table className="w-full min-w-max">
100-
<thead className="bg-gray-50 border-b border-gray-200">
105+
<TableHead>
101106
<tr>
102107
{/* Row header labels */}
103108
{rowFields.map((f) => (
104-
<th
105-
key={String(f)}
106-
className="px-3 py-2 text-left text-xs font-semibold text-gray-700"
107-
>
108-
{String(f)}
109-
</th>
109+
<TableHeader key={String(f)}>{String(f)}</TableHeader>
110110
))}
111111
{/* Column headers (flattened) */}
112112
{colKeyTuples.map((tuple, idx) => (
113-
<th
114-
key={`col-${idx}`}
115-
className="px-3 py-2 text-right text-xs font-semibold text-gray-700 whitespace-nowrap"
116-
>
113+
<TableHeader key={`col-${idx}`} align="right" nowrap>
117114
{tuple.map((v) => String(v ?? "")).join(" / ")}
118-
</th>
115+
</TableHeader>
119116
))}
120-
{showRowTotals && (
121-
<th className="px-3 py-2 text-right text-xs font-semibold text-gray-700">
122-
Total
123-
</th>
124-
)}
117+
{showRowTotals && <TableHeader align="right">Total</TableHeader>}
125118
</tr>
126-
</thead>
127-
<tbody className="divide-y divide-gray-200">
119+
</TableHead>
120+
<TableBody>
128121
{rowKeyTuples.map((rTuple, rIdx) => {
129122
const rKey = toKey(rTuple);
130123
return (
131-
<tr key={`row-${rIdx}`} className="text-xs">
124+
<TableRow key={`row-${rIdx}`} className="text-xs">
132125
{/* Row header cells */}
133126
{rTuple.map((value, i) => (
134-
<td
135-
key={`rh-${i}`}
136-
className="px-3 py-2 text-gray-900 whitespace-nowrap"
137-
>
127+
<TableCell key={`rh-${i}`} nowrap>
138128
{String(value ?? "")}
139-
</td>
129+
</TableCell>
140130
))}
141131
{/* Data cells */}
142132
{colKeyTuples.map((cTuple, cIdx) => {
143133
const cKey = toKey(cTuple);
144134
const cell = cells[rKey]?.[cKey];
145135
const content = cell ? formatter(cell.value) : emptyValue;
146136
return (
147-
<td
148-
key={`c-${cIdx}`}
149-
className="px-3 py-2 text-right text-gray-900 whitespace-nowrap"
150-
>
137+
<TableCell key={`c-${cIdx}`} align="right" nowrap>
151138
{content}
152-
</td>
139+
</TableCell>
153140
);
154141
})}
155142
{/* Row total */}
156143
{showRowTotals && (
157-
<td className="px-3 py-2 text-right text-gray-900 whitespace-nowrap font-medium">
144+
<TableCell align="right" nowrap medium>
158145
{formatter(rowTotals[rKey] ?? 0)}
159-
</td>
146+
</TableCell>
160147
)}
161-
</tr>
148+
</TableRow>
162149
);
163150
})}
164151
{showColumnTotals && (
165-
<tr className="bg-gray-50">
152+
<TableRow gray>
166153
{/* Total label spanning row header columns */}
167-
<td
168-
colSpan={Math.max(1, rowFields.length)}
169-
className="px-3 py-2 text-left text-xs font-semibold text-gray-700"
170-
>
154+
<TableCell colSpan={Math.max(1, rowFields.length)} semibold>
171155
Total
172-
</td>
156+
</TableCell>
173157
{/* Column totals */}
174158
{colKeyTuples.map((cTuple, cIdx) => {
175159
const cKey = toKey(cTuple);
176160
return (
177-
<td
178-
key={`ct-${cIdx}`}
179-
className="px-3 py-2 text-right text-gray-900 whitespace-nowrap font-medium"
180-
>
161+
<TableCell key={`ct-${cIdx}`} align="right" nowrap medium>
181162
{formatter(colTotals[cKey] ?? 0)}
182-
</td>
163+
</TableCell>
183164
);
184165
})}
185166
{/* Grand total */}
186167
{showRowTotals && (
187-
<td className="px-3 py-2 text-right text-gray-900 whitespace-nowrap font-semibold">
168+
<TableCell align="right" nowrap semibold>
188169
{formatter(grandTotal)}
189-
</td>
170+
</TableCell>
190171
)}
191-
</tr>
172+
</TableRow>
192173
)}
193-
</tbody>
174+
</TableBody>
194175
</table>
195-
</div>
176+
</TableContainer>
196177
);
197178
}
198179

0 commit comments

Comments
 (0)