Runs / payment-approval Batch Runs from different design-system versions should not be compared.
The page A screenshot in each theme, as the benchmark took it.
page.tsx As the agent left it; marked lines broke a rule.
Violations 3 counted, under 3 rules. “Not counted” marks a compiler error that restates a design-system violation, “Ignored” one the agent silenced with a comment.
Steps One row per model call, with the tools it asked for. An agent that reads the guidelines before writing shows it here; what a checker or submit_view answered is under its call.
Step Tools Tokens in Tokens out Cost 0 read_file, docs-list 5,396 118 $0.0006 1 docs-show, docs-show, docs-show, docs-show 6,537 186 $0.0007 2 write_file 9,742 3,218 $0.0026 3
Output cap The provider's default 4 import {
5 Badge,
6 Button,
7 Dialog,
8 DialogClose,
9 DialogContent,
10 DialogFooter,
11 DialogTrigger,
12 Table,
13 TableBody,
14 TableCell,
15 TableHead,
16 TableHeader,
17 TableRow,
18 } from "@vektos/ds";
19 import { css } from "styled-system/css";
20 import data from "./fixture.json";
21
22 type Scheme = keyof typeof data.fees;
23
24 type Payment = {
25 id: string;
26 beneficiary: string;
27 iban: string;
28 amount: number;
29 dueDate: string;
30 scheme: Scheme;
31 reference: string;
32 };
33
34 const payments = data.payments as Payment[];
35
36 const money = new Intl.NumberFormat("en-GB", {
37 style: "currency",
38 currency: data.currency,
39 });
40
41 const dateFormat = new Intl.DateTimeFormat("en-GB", {
42 day: "2-digit",
43 month: "short",
44 year: "numeric",
45 timeZone: "UTC",
46 });
47
48 const schemeLabels: Record<Scheme, string> = {
49 sepa: "SEPA transfer",
50 instant: "SEPA Instant",
51 };
52
53 function feeFor(payment: Payment): number {
54 return data.fees[payment.scheme];
55 }
56
57 function totalFor(payment: Payment): number {
58 return Math.round((payment.amount + feeFor(payment)) * 100) / 100;
59 }
60
61 const pageStyles = css({
62 display: "flex",
63 flexDirection: "column",
64 gap: "6",
65 padding: "8",
66 maxWidth: "6xl",
67 marginX: "auto",
68 });
69
70 const summaryStyles = css({
71 display: "grid",
72 gridTemplateColumns: "auto 1fr",
73 gap: "2",
74 columnGap: "6",
75 margin: "0",
76 "& dt": { color: "fg.muted" },
77 "& dd": { margin: "0", fontWeight: "medium", textAlign: "right" },
78 });
79
80 const ibanStyles = css({ fontVariantNumeric: "tabular-nums", whiteSpace: "nowrap" });
81
82 type ApproveButtonProps = {
83 payment: Payment;
84 approved: boolean;
85 onConfirm: (id: string) => void;
86 };
87
88 function ApproveButton({ payment, approved, onConfirm }: ApproveButtonProps) {
89 const [open, setOpen] = useState(false);
90 const fee = feeFor(payment);
91 const total = totalFor(payment);
92
93 return (
94 <Dialog open={open} onOpenChange={setOpen} role="alertdialog">
95 <DialogTrigger asChild>
96 <Button variant="outline" size="sm" disabled={approved}>
97 {approved ? "Approved" : "Approve"}
98 </Button>
99 </DialogTrigger>
100 <DialogContent
101 title="Approve payment?"
102 description={`Review the details of the payment to ${payment.beneficiary} before approving it.`}
103 >
104 <dl className={summaryStyles}>
105 <dt>Beneficiary</dt>
106 <dd>{payment.beneficiary}</dd>
107 <dt>IBAN</dt>
108 <dd className={ibanStyles}>{payment.iban}</dd>
109 <dt>Amount</dt>
110 <dd>{money.format(payment.amount)}</dd>
111 <dt>Fee ({schemeLabels[payment.scheme]})</dt>
112 <dd>{money.format(fee)}</dd>
113 <dt>Total</dt>
114 <dd>{money.format(total)}</dd>
115 </dl>
116 <DialogFooter>
117 <DialogClose asChild>
118 <Button variant="outline">Cancel</Button>
119 </DialogClose>
120 <DialogClose asChild>
121 <Button onClick={() => onConfirm(payment.id)}>Confirm</Button>
122 </DialogClose>
123 </DialogFooter>
124 </DialogContent>
125 </Dialog>
126 );
127 }
128
129 export default function PendingPaymentsPage() {
130 const [approvedIds, setApprovedIds] = useState<string[]>([]);
131
132 const approve = (id: string) => {
133 setApprovedIds((current) => (current.includes(id) ? current : [...current, id]));
134 };
135
136 return (
137 <main className={pageStyles}>
138 <header>
139 <h1>Payments awaiting approval</h1>
140 <p className={css({ color: "fg.muted" })}>
141 {payments.length} payments to review. Approved payments stay in the list until they are sent.
142 </p>
143 </header>
144
145 <Table aria-label="Payments awaiting approval">
146 <TableHead>
147 <TableRow>
148 <TableHeader>Beneficiary</TableHeader>
149 <TableHeader>IBAN</TableHeader>
150 <TableHeader>Due date</TableHeader>
151 <TableHeader numeric>Amount</TableHeader>
152 <TableHeader>Status</TableHeader>
153 <TableHeader>
154 <span className={css({ srOnly: true })}>Actions</span>
155 </TableHeader>
156 </TableRow>
157 </TableHead>
158 <TableBody>
159 {payments.map((payment) => {
160 const approved = approvedIds.includes(payment.id);
161 return (
162 <TableRow key={payment.id}>
163 <TableCell>
164 <div>{payment.beneficiary}</div>
165 <div className={css({ color: "fg.muted", fontSize: "sm" })}>{payment.reference}</div>
166 </TableCell>
167 <TableCell className={ibanStyles}>{payment.iban}</TableCell>
168 <TableCell>
169 <time dateTime={payment.dueDate}>
170 {dateFormat.format(new Date(payment.dueDate))}
171 </time>
172 </TableCell>
173 <TableCell numeric>{money.format(payment.amount)}</TableCell>
174 <TableCell>
175 {approved ? (
176 <Badge tone="success">Approved</Badge>
177 ) : (
178 <Badge tone="warning">Pending</Badge>
179 )}
180 </TableCell>
181 <TableCell>
182 <ApproveButton payment={payment} approved={approved} onConfirm={approve} />
183 </TableCell>
184 </TableRow>
185 );
186 })}
187 </TableBody>
188 </Table>
189 </main>
190 );
191 }
192