Runs / transfer-form 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 36 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 docs-list 3,370 164 $0.0084 1 list_files 976 34 $0.0029 2 read_file, docs-show, docs-show, docs-show, docs-show, docs-show, docs-show, docs-show, docs-show 82 344 $0.0044
Output cap The provider's default 4 import {
5 Badge,
6 Button,
7 Card,
8 CardBody,
9 CardDescription,
10 CardFooter,
11 CardHeader,
12 CardTitle,
13 FormField,
14 Input,
15 Select,
16 } from "@vektos/ds";
17 import { css } from "styled-system/css";
18 import data from "./fixture.json";
19
20 const currencyFormatter = new Intl.NumberFormat("en-IE", {
21 style: "currency",
22 currency: data.currency,
23 minimumFractionDigits: 2,
24 maximumFractionDigits: 2,
25 });
26
27 function formatCurrency(value: number) {
28 return currencyFormatter.format(value);
29 }
30
31 function parseAmount(value: string): number | null {
32 const normalized = value.trim().replace(/\s/g, "").replace(",", ".");
33
34 if (!/^(?:\d+(?:\.\d{0,2})?|\.\d{1,2})$/.test(normalized)) {
35 return null;
36 }
37
38 const amount = Number(normalized);
39 return Number.isFinite(amount) && amount > 0 ? amount : null;
40 }
41
42 function normalizeIban(value: string) {
43 return value.replace(/\s/g, "").toUpperCase();
44 }
45
46 function isValidIban(value: string) {
47 return /^[A-Z]{2}\d{2}[A-Z0-9]{11,30}$/.test(normalizeIban(value));
48 }
49
50 function formatIban(value: string) {
51 return normalizeIban(value).replace(/(.{4})/g, "$1 ").trim();
52 }
53
54 type Confirmation = {
55 amount: number;
56 beneficiary: string;
57 beneficiaryIban: string;
58 accountName: string;
59 reference: string;
60 };
61
62 export default function SepaTransferPage() {
63 const [accountId, setAccountId] = useState(data.defaultAccountId);
64 const [beneficiaryName, setBeneficiaryName] = useState("");
65 const [beneficiaryIban, setBeneficiaryIban] = useState("");
66 const [amount, setAmount] = useState("");
67 const [reference, setReference] = useState("");
68 const [submitted, setSubmitted] = useState(false);
69 const [amountTouched, setAmountTouched] = useState(false);
70 const [confirmation, setConfirmation] = useState<Confirmation | null>(null);
71
72 const selectedAccount =
73 data.accounts.find((account) => account.id === accountId) ?? data.accounts[0]!;
74 const parsedAmount = parseAmount(amount);
75 const exceedsBalance =
76 parsedAmount !== null && parsedAmount > selectedAccount.available;
77
78 let amountError: string | undefined;
79 if (exceedsBalance) {
80 amountError = `The amount exceeds the available balance of ${formatCurrency(
81 selectedAccount.available,
82 )}.`;
83 } else if (submitted || amountTouched) {
84 if (!amount.trim()) {
85 amountError = "Enter an amount.";
86 } else if (parsedAmount === null) {
87 amountError = "Enter an amount greater than zero, using up to two decimal places.";
88 }
89 }
90
91 const nameError =
92 submitted && !beneficiaryName.trim()
93 ? "Enter the beneficiary’s name."
94 : undefined;
95 const ibanError =
96 submitted && !isValidIban(beneficiaryIban)
97 ? "Enter a valid IBAN."
98 : undefined;
99
100 function handleSubmit(event: FormEvent<HTMLFormElement>) {
101 event.preventDefault();
102 setSubmitted(true);
103
104 const submittedAmount = parseAmount(amount);
105 const cleanName = beneficiaryName.trim();
106
107 if (
108 !cleanName ||
109 !isValidIban(beneficiaryIban) ||
110 submittedAmount === null ||
111 submittedAmount > selectedAccount.available
112 ) {
113 return;
114 }
115
116 setConfirmation({
117 amount: submittedAmount,
118 beneficiary: cleanName,
119 beneficiaryIban: normalizeIban(beneficiaryIban),
120 accountName: selectedAccount.name,
121 reference: reference.trim(),
122 });
123 }
124
125 function startAnotherTransfer() {
126 setBeneficiaryName("");
127 setBeneficiaryIban("");
128 setAmount("");
129 setReference("");
130 setSubmitted(false);
131 setAmountTouched(false);
132 setConfirmation(null);
133 }
134
135 return (
136 <main
137 className={`vektos ${css({
138 minHeight: "100vh",
139 bg: "bg.canvas",
140 color: "fg.default",
141 px: { base: "4", md: "8" },
142 py: { base: "6", md: "10" },
143 })}`}
144 >
145 <header
146 className={css({
147 maxWidth: "6xl",
148 mx: "auto",
149 mb: { base: "10", md: "14" },
150 display: "flex",
151 alignItems: "center",
152 justifyContent: "space-between",
153 gap: "4",
154 })}
155 >
156 <div>
157 <p
158 className={css({
159 fontSize: "xl",
160 fontWeight: "bold",
161 letterSpacing: "tight",
162 lineHeight: "shorter",
163 })}
164 >
165 vektos<span className={css({ color: "accent.default" })}>.</span>
166 </p>
167 <p className={css({ color: "fg.muted", fontSize: "xs", mt: "1" })}>
168 Business banking
169 </p>
170 </div>
171 <p className={css({ color: "fg.muted", fontSize: "sm" })}>
172 SEPA payments
173 </p>
174 </header>
175
176 {confirmation ? (
177 <section
178 className={css({ maxWidth: "2xl", mx: "auto" })}
179 aria-live="polite"
180 >
181 <Card>
182 <CardHeader>
183 <div className={css({ mb: "4" })}>
184 <Badge tone="success">Transfer sent</Badge>
185 </div>
186 <CardTitle asChild>
187 <h1>{formatCurrency(confirmation.amount)} sent</h1>
188 </CardTitle>
189 <CardDescription>
190 Your SEPA transfer to {confirmation.beneficiary} was successful.
191 </CardDescription>
192 </CardHeader>
193 <CardBody>
194 <dl
195 className={css({
196 display: "grid",
197 gap: "4",
198 m: "0",
199 bg: "bg.canvas",
200 rounded: "md",
201 p: "5",
202 })}
203 >
204 <div
205 className={css({
206 display: "flex",
207 justifyContent: "space-between",
208 gap: "4",
209 })}
210 >
211 <dt className={css({ color: "fg.muted" })}>Beneficiary</dt>
212 <dd className={css({ m: "0", fontWeight: "medium", textAlign: "right" })}>
213 {confirmation.beneficiary}
214 </dd>
215 </div>
216 <div
217 className={css({
218 display: "flex",
219 justifyContent: "space-between",
220 gap: "4",
221 })}
222 >
223 <dt className={css({ color: "fg.muted" })}>IBAN</dt>
224 <dd
225 className={css({
226 m: "0",
227 textAlign: "right",
228 fontFamily: "mono",
229 fontSize: "sm",
230 overflowWrap: "anywhere",
231 })}
232 >
233 {formatIban(confirmation.beneficiaryIban)}
234 </dd>
235 </div>
236 <div
237 className={css({
238 display: "flex",
239 justifyContent: "space-between",
240 gap: "4",
241 })}
242 >
243 <dt className={css({ color: "fg.muted" })}>Paid from</dt>
244 <dd className={css({ m: "0", textAlign: "right" })}>
245 {confirmation.accountName}
246 </dd>
247 </div>
248 {confirmation.reference && (
249 <div
250 className={css({
251 display: "flex",
252 justifyContent: "space-between",
253 gap: "4",
254 })}
255 >
256 <dt className={css({ color: "fg.muted" })}>Reference</dt>
257 <dd
258 className={css({
259 m: "0",
260 textAlign: "right",
261 overflowWrap: "anywhere",
262 })}
263 >
264 {confirmation.reference}
265 </dd>
266 </div>
267 )}
268 </dl>
269 </CardBody>
270 <CardFooter>
271 <Button variant="outline" type="button" onClick={startAnotherTransfer}>
272 Make another transfer
273 </Button>
274 </CardFooter>
275 </Card>
276 </section>
277 ) : (
278 <div className={css({ maxWidth: "6xl", mx: "auto" })}>
279 <div className={css({ mb: "8" })}>
280 <p
281 className={css({
282 color: "accent.default",
283 fontSize: "xs",
284 fontWeight: "semibold",
285 letterSpacing: "widest",
286 textTransform: "uppercase",
287 mb: "3",
288 })}
289 >
290 Payments
291 </p>
292 <h1
293 className={css({
294 fontSize: { base: "3xl", md: "4xl" },
295 fontWeight: "bold",
296 letterSpacing: "tight",
297 lineHeight: "shorter",
298 })}
299 >
300 Send a SEPA transfer
301 </h1>
302 <p
303 className={css({
304 color: "fg.muted",
305 fontSize: "md",
306 lineHeight: "relaxed",
307 mt: "3",
308 maxWidth: "2xl",
309 })}
310 >
311 Send euros to a beneficiary within the SEPA zone. Check their details
312 carefully before submitting.
313 </p>
314 </div>
315
316 <div
317 className={css({
318 display: "flex",
319 flexDirection: { base: "column", lg: "row" },
320 alignItems: "flex-start",
321 gap: "6",
322 })}
323 >
324 <form
325 className={css({ flex: "1", minWidth: "0", width: "full" })}
326 onSubmit={handleSubmit}
327 noValidate
328 >
329 <Card>
330 <CardHeader>
331 <CardTitle asChild>
332 <h2>Transfer details</h2>
333 </CardTitle>
334 <CardDescription>
335 Choose an account and enter the beneficiary’s payment details.
336 </CardDescription>
337 </CardHeader>
338 <CardBody className={css({ display: "grid", gap: "6" })}>
339 <FormField label="Pay from" required>
340 <Select
341 name="accountId"
342 value={accountId}
343 onValueChange={(value) => {
344 setAccountId(value);
345 setAmountTouched(false);
346 }}
347 options={data.accounts.map((account) => ({
348 value: account.id,
349 label: `${account.name} · ${formatCurrency(account.available)}`,
350 }))}
351 />
352 </FormField>
353
354 <div
355 className={css({
356 display: "flex",
357 alignItems: "center",
358 justifyContent: "space-between",
359 flexWrap: "wrap",
360 gap: "5",
361 bg: "bg.canvas",
362 rounded: "md",
363 p: "5",
364 })}
365 >
366 <div>
367 <p className={css({ color: "fg.muted", fontSize: "sm" })}>
368 Available balance
369 </p>
370 <p
371 className={css({
372 fontSize: "2xl",
373 fontWeight: "semibold",
374 fontVariantNumeric: "tabular-nums",
375 mt: "1",
376 })}
377 >
378 {formatCurrency(selectedAccount.available)}
379 </p>
380 </div>
381 <div>
382 <p className={css({ color: "fg.muted", fontSize: "xs" })}>
383 {selectedAccount.name} IBAN
384 </p>
385 <p
386 className={css({
387 fontFamily: "mono",
388 fontSize: "sm",
389 mt: "1",
390 overflowWrap: "anywhere",
391 })}
392 >
393 {selectedAccount.iban}
394 </p>
395 </div>
396 </div>
397
398 <FormField label="Beneficiary name" error={nameError} required>
399 <Input
400 name="beneficiaryName"
401 value={beneficiaryName}
402 onChange={(event) => setBeneficiaryName(event.target.value)}
403 placeholder="e.g. Alice Martin"
404 autoComplete="off"
405 maxLength={70}
406 required
407 />
408 </FormField>
409
410 <FormField
411 label="Beneficiary IBAN"
412 helperText="You can enter the IBAN with or without spaces."
413 error={ibanError}
414 required
415 >
416 <Input
417 name="beneficiaryIban"
418 value={beneficiaryIban}
419 onChange={(event) =>
420 setBeneficiaryIban(event.target.value.toUpperCase())
421 }
422 placeholder="DE89 3704 0044 0532 0130 00"
423 autoComplete="off"
424 autoCapitalize="characters"
425 autoCorrect="off"
426 spellCheck={false}
427 maxLength={42}
428 required
429 />
430 </FormField>
431
432 <FormField
433 label="Amount (EUR)"
434 helperText="Enter an amount greater than zero, using up to two decimal places."
435 error={amountError}
436 required
437 >
438 <Input
439 name="amount"
440 value={amount}
441 onChange={(event) => setAmount(event.target.value)}
442 onBlur={() => setAmountTouched(true)}
443 inputMode="decimal"
444 placeholder="0.00"
445 autoComplete="off"
446 required
447 />
448 </FormField>
449
450 <FormField
451 label="Reference (optional)"
452 helperText={`${reference.length}/140 characters`}
453 >
454 <Input
455 name="reference"
456 value={reference}
457 onChange={(event) => setReference(event.target.value)}
458 placeholder="e.g. Invoice 2026-114"
459 maxLength={140}
460 />
461 </FormField>
462 </CardBody>
463 <CardFooter>
464 <Button
465 type="submit"
466 disabled={exceedsBalance}
467 className={css({ width: { base: "full", sm: "auto" } })}
468 >
469 Send transfer
470 </Button>
471 </CardFooter>
472 </Card>
473 </form>
474
475 <aside
476 className={css({
477 width: { base: "full", lg: "xs" },
478 flexShrink: "0",
479 })}
480 >
481 <Card>
482 <CardHeader>
483 <CardTitle asChild>
484 <h2>Transfer overview</h2>
485 </CardTitle>
486 <CardDescription>A quick summary before you send.</CardDescription>
487 </CardHeader>
488 <CardBody>
489 <dl className={css({ display: "grid", gap: "5", m: "0" })}>
490 <div>
491 <dt className={css({ color: "fg.muted", fontSize: "sm" })}>
492 From
493 </dt>
494 <dd className={css({ m: "0", mt: "1", fontWeight: "medium" })}>
495 {selectedAccount.name}
496 </dd>
497 </div>
498 <div>
499 <dt className={css({ color: "fg.muted", fontSize: "sm" })}>
500 Beneficiary
501 </dt>
502 <dd
503 className={css({
504 m: "0",
505 mt: "1",
506 fontWeight: "medium",
507 overflowWrap: "anywhere",
508 })}
509 >
510 {beneficiaryName.trim() || "Not added yet"}
511 </dd>
512 </div>
513 <div>
514 <dt className={css({ color: "fg.muted", fontSize: "sm" })}>
515 Amount
516 </dt>
517 <dd
518 className={css({
519 m: "0",
520 mt: "1",
521 fontSize: "xl",
522 fontWeight: "semibold",
523 fontVariantNumeric: "tabular-nums",
524 })}
525 >
526 {parsedAmount === null ? "—" : formatCurrency(parsedAmount)}
527 </dd>
528 </div>
529 </dl>
530 <p
531 className={css({
532 color: "fg.muted",
533 fontSize: "sm",
534 lineHeight: "relaxed",
535 mt: "6",
536 })}
537 >
538 The available balance is checked when you submit. Transfers over
539 the available balance cannot be sent.
540 </p>
541 </CardBody>
542 </Card>
543 </aside>
544 </div>
545 </div>
546 )}
547 </main>
548 );
549 }
550
No overload matches this call.
lint/@pandacss(no-physical-properties) 12 quality page.tsx:149:11 Use the logical property "marginBlockEnd" instead of the physical "marginBottom". page.tsx:167:66 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:183:37 Use the logical property "marginBlockEnd" instead of the physical "marginBottom". page.tsx:279:33 Use the logical property "marginBlockEnd" instead of the physical "marginBottom". page.tsx:287:17 Use the logical property "marginBlockEnd" instead of the physical "marginBottom". page.tsx:307:17 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:375:27 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:389:27 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:494:52 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:505:27 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:520:27 Use the logical property "marginBlockStart" instead of the physical "marginTop". page.tsx:535:23 Use the logical property "marginBlockStart" instead of the physical "marginTop". Every run that broke lint/@pandacss(no-physical-properties) raw-values/raw-length 1 design-system