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 42 counted, under 9 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 list_files, read_file 1,069 172 $0.0002 1 write_file 1,542 3,559 $0.0019 2 write_file 5,122 3,865 $0.0024 3
Output cap The provider's default 3
4 import { css } from "styled-system/css";
5 import data from "./fixture.json";
6
7 const currency = data.currency;
8
9 const formatMoney = (value: number) =>
10 new Intl.NumberFormat("en-GB", { style: "currency", currency }).format(value);
11
12 // Compare in cents to avoid floating point surprises.
13 const toCents = (value: number) => Math.round(value * 100);
14
15 type Confirmation = {
16 amount: number;
17 beneficiaryName: string;
18 accountName: string;
19 };
20
21 export default function SepaTransferPage() {
22 const [accountId, setAccountId] = useState<string>(data.defaultAccountId);
23 const [beneficiaryName, setBeneficiaryName] = useState("");
24 const [beneficiaryIban, setBeneficiaryIban] = useState("");
25 const [amountInput, setAmountInput] = useState("");
26 const [reference, setReference] = useState("");
27 const [touched, setTouched] = useState(false);
28 const [confirmation, setConfirmation] = useState<Confirmation | null>(null);
29
30 const account =
31 data.accounts.find((a) => a.id === accountId) ?? data.accounts[0];
32 const amount = Number(amountInput);
33 const amountIsNumber = amountInput.trim() !== "" && Number.isFinite(amount);
34
35 // Balance rule applies as soon as an amount is entered; the other rules
36 // only show after the first submit attempt.
37 let amountError: string | null = null;
38 if (amountInput.trim() !== "") {
39 if (!amountIsNumber || amount <= 0) {
40 amountError = "Enter an amount greater than zero.";
41 } else if (toCents(amount) > toCents(account.available)) {
42 amountError = `Amount exceeds the available balance of ${formatMoney(account.available)}.`;
43 }
44 } else if (touched) {
45 amountError = "Enter an amount.";
46 }
47
48 const nameError =
49 touched && beneficiaryName.trim() === "" ? "Enter the beneficiary name." : null;
50
51 const ibanCompact = beneficiaryIban.replace(/\s+/g, "").toUpperCase();
52 const ibanError =
53 touched && !/^[A-Z]{2}[0-9A-Z]{13,32}$/.test(ibanCompact)
54 ? "Enter a valid IBAN."
55 : null;
56
57 const hasErrors = Boolean(amountError || nameError || ibanError);
58
59 function handleSubmit(event: FormEvent<HTMLFormElement>) {
60 event.preventDefault();
61 setTouched(true);
62 if (hasErrors) return;
63 setConfirmation({
64 amount,
65 beneficiaryName: beneficiaryName.trim(),
66 accountName: account.name,
67 });
68 }
69
70 function resetForm() {
71 setBeneficiaryName("");
72 setBeneficiaryIban("");
73 setAmountInput("");
74 setReference("");
75 setTouched(false);
76 setConfirmation(null);
77 }
78
79 const pageClass = css({ maxWidth: "480px", margin: "0 auto", padding: "32px 16px" });
80
81 if (confirmation) {
82 return (
83 <main className={pageClass}>
84 <section
85 role="status"
86 className={css({
87 padding: "24px",
88 border: "1px solid",
89 borderColor: "green.600",
90 borderRadius: "8px",
91 display: "flex",
92 flexDirection: "column",
93 gap: "12px",
94 })}
95 >
96 <h1 className={css({ fontSize: "xl", fontWeight: "bold" })}>
97 Transfer submitted
98 </h1>
99 <p>
100 You sent <strong>{formatMoney(confirmation.amount)}</strong> to{" "}
101 <strong>{confirmation.beneficiaryName}</strong> from{" "}
102 {confirmation.accountName}.
103 </p>
104 <button
105 type="button"
106 onClick={resetForm}
107 className={css({
108 alignSelf: "flex-start",
109 padding: "8px 16px",
110 borderRadius: "6px",
111 border: "1px solid",
112 borderColor: "gray.400",
113 background: "white",
114 cursor: "pointer",
115 })}
116 >
117 Make another transfer
118 </button>
119 </section>
120 </main>
121 );
122 }
123
124 const fieldClass = css({ display: "flex", flexDirection: "column", gap: "4px" });
125 const inputClass = css({
126 padding: "8px 10px",
127 border: "1px solid",
128 borderColor: "gray.400",
129 borderRadius: "6px",
130 fontSize: "md",
131 });
132 const errorClass = css({ color: "red.600", fontSize: "sm" });
133
134 return (
135 <main className={pageClass}>
136 <h1 className={css({ fontSize: "2xl", fontWeight: "bold", marginBottom: "24px" })}>
137 Send a SEPA transfer
138 </h1>
139
140 <form
141 noValidate
142 onSubmit={handleSubmit}
143 className={css({ display: "flex", flexDirection: "column", gap: "20px" })}
144 >
145 <div className={fieldClass}>
146 <label htmlFor="from-account">From account</label>
147 <select
148 id="from-account"
149 name="account"
150 className={inputClass}
151 value={accountId}
152 onChange={(e) => setAccountId(e.target.value)}
153 >
154 {data.accounts.map((a) => (
155 <option key={a.id} value={a.id}>
156 {a.name} ({a.iban})
157 </option>
158 ))}
159 </select>
160 <p aria-live="polite" className={css({ fontSize: "sm", color: "gray.700" })}>
161 Available balance: <strong>{formatMoney(account.available)}</strong>
162 </p>
163 </div>
164
165 <div className={fieldClass}>
166 <label htmlFor="beneficiary-name">Beneficiary name</label>
167 <input
168 id="beneficiary-name"
169 name="beneficiaryName"
170 type="text"
171 autoComplete="off"
172 className={inputClass}
173 value={beneficiaryName}
174 onChange={(e) => setBeneficiaryName(e.target.value)}
175 aria-invalid={nameError ? true : undefined}
176 aria-describedby={nameError ? "beneficiary-name-error" : undefined}
177 />
178 {nameError && (
179 <span id="beneficiary-name-error" className={errorClass}>
180 {nameError}
181 </span>
182 )}
183 </div>
184
185 <div className={fieldClass}>
186 <label htmlFor="beneficiary-iban">Beneficiary IBAN</label>
187 <input
188 id="beneficiary-iban"
189 name="beneficiaryIban"
190 type="text"
191 autoComplete="off"
192 spellCheck={false}
193 className={inputClass}
194 value={beneficiaryIban}
195 onChange={(e) => setBeneficiaryIban(e.target.value)}
196 aria-invalid={ibanError ? true : undefined}
197 aria-describedby={ibanError ? "beneficiary-iban-error" : undefined}
198 />
199 {ibanError && (
200 <span id="beneficiary-iban-error" className={errorClass}>
201 {ibanError}
202 </span>
203 )}
204 </div>
205
206 <div className={fieldClass}>
207 <label htmlFor="amount">Amount ({currency})</label>
208 <input
209 id="amount"
210 name="amount"
211 type="number"
212 inputMode="decimal"
213 min="0"
214 step="0.01"
215 className={inputClass}
216 value={amountInput}
217 onChange={(e) => setAmountInput(e.target.value)}
218 aria-invalid={amountError ? true : undefined}
219 aria-describedby={amountError ? "amount-error" : undefined}
220 />
221 {amountError && (
222 <span id="amount-error" className={errorClass}>
223 {amountError}
224 </span>
225 )}
226 </div>
227
228 <div className={fieldClass}>
229 <label htmlFor="reference">Reference (optional)</label>
230 <input
231 id="reference"
232 name="reference"
233 type="text"
234 autoComplete="off"
235 maxLength={140}
236 className={inputClass}
237 value={reference}
238 onChange={(e) => setReference(e.target.value)}
239 />
240 </div>
241
242 <button
243 type="submit"
244 disabled={hasErrors}
245 className={css({
246 padding: "10px 16px",
247 borderRadius: "6px",
248 border: "none",
249 background: "blue.600",
250 color: "white",
251 fontWeight: "bold",
252 cursor: "pointer",
253 _disabled: { background: "gray.400", cursor: "not-allowed" },
254 })}
255 >
256 Send transfer
257 </button>
258 </form>
259 </main>
260 );
261 }
262
components/native-element 7 design-system page.tsx:104:11 · <button> `<button>` has a design-system equivalent: use `Button` from `@vektos/ds`. page.tsx:147:11 · <select> `<select>` has a design-system equivalent: use `Select` from `@vektos/ds`. page.tsx:167:11 · <input> `<input>` has a design-system equivalent: use `Input` from `@vektos/ds`. page.tsx:187:11 · <input> `<input>` has a design-system equivalent: use `Input` from `@vektos/ds`. page.tsx:208:11 · <input> `<input>` has a design-system equivalent: use `Input` from `@vektos/ds`. page.tsx:230:11 · <input> `<input>` has a design-system equivalent: use `Input` from `@vektos/ds`. page.tsx:242:9 · <button> `<button>` has a design-system equivalent: use `Button` from `@vektos/ds`. Every run that broke components/native-element token-roles/palette 7 design-system page.tsx:89:26 · green.600 `green.600` is a palette shade: it ignores the theme. Use a semantic color token. page.tsx:112:28 · gray.400 `gray.400` is a palette shade: it ignores the theme. Use a semantic color token. page.tsx:128:18 · gray.400 `gray.400` is a palette shade: it ignores the theme. Use a semantic color token. page.tsx:132:35 · red.600 `red.600` is a palette shade: it ignores the theme. Use a semantic color token. page.tsx:160:73 · gray.700 `gray.700` is a palette shade: it ignores the theme. Use a semantic color token. page.tsx:249:25 · blue.600 `blue.600` is a palette shade: it ignores the theme. Use a semantic color token. page.tsx:253:38 · gray.400 `gray.400` is a palette shade: it ignores the theme. Use a semantic color token. Every run that broke token-roles/palette typecheck/TS18048 4 quality raw-values/raw-color 2 design-system typecheck/TS2769 2 quality a11y/color-contrast 1 quality page.tsx:1:1 · <button type="submit" class="p_10px_16px bdr_6px bd_none bg_blue.600 c_white fw_bold cursor_pointer disabled:bg_gray.400 Elements must meet minimum color contrast ratio thresholds (1 element, light theme) Every run that broke a11y/color-contrast lint/jsx-a11y(prefer-tag-over-role) 1 quality