UI Design Agents
By the Syncfusion DevTutorials team · Last updated
How a UI design agent turns a design task into a layout using only design tokens, and fixes accessibility problems before handing over.
Think about decorating a room in a shop that follows a strict style guide.
The shop gives you a style card with approved paint colours, fonts, and spacing values. You can arrange things however you like, but you must use only the approved styles. This helps every shop look like part of the same brand.
There are also safety rules. Signs must be easy to read, and every door must be clearly marked.
A UI design agent works in the same way. The style card is the design system, and the safety rules are accessibility checks.
The main idea: A UI design agent turns a design task into a page layout. It uses only values from the design system and does not hand the design over until the accessibility checks pass.
A Real-World Example
The planning agent from Lesson 17 created the task: "Design the export status panel: 4 states and a Retry button."
The UI design agent:
- Reads the feature request to understand what the panel must display.
- Reads
design/tokens.json, which contains the team's colours and spacing values. - Creates the first draft in
web/export-panel.html. - Runs
check_a11yandcheck_tokens. - Fixes any reported problems and runs the checks again.
The first draft contains 3 accessibility issues. That is normal. What matters is that the agent finds and fixes them before the frontend agent starts building from the design.
In simple words: Create the design using the design system, check accessibility, fix the problems, check again, and then hand the design over.
What You Will Learn
In this lesson, you will learn:
- What a wireframe is and how an agent creates one.
- How layouts use spacing values from the design system.
- What design tokens are and why the agent must use only approved tokens.
- The three accessibility checks covered in this lesson: alt text, button names, and contrast.
The UI design agent has four tools: read_file, write_file, check_a11y, and check_tokens. It may only modify files in web/. Open the Files tab after a run to view web/export-panel.html.
The UI design agent's loop: read the inputs, create a draft, run checks, fix issues, and run the checks again before handing the design over.
Wireframes
A wireframe is a simple sketch of a page that shows where things go, without visual styling. For an agent, a wireframe is often a short list of page elements in order, or simple HTML with very little styling.
The export status panel contains four parts: a heading, a progress image, the status text, and a Retry button. Each of the four statuses displays a slightly different version.
A wireframe as data: what each status shows
const states = {
queued: ["heading", "status text"],
running: ["heading", "progress image", "status text"],
done: ["heading", "status text with row count"],
failed: ["heading", "status text", "Retry button"],
};
for (const [status, parts] of Object.entries(states)) {
console.log(status.padEnd(8) + "| " + parts.join(" | "));
}
Expected output:
queued | heading | status text
running | heading | progress image | status text
done | heading | status text with row count
failed | heading | status text | Retry button
Writing every state down prevents the agent from designing only the happy path. The Failed state is the one most often forgotten, and it is often the one users need most.
Layout
Layout determines where each part appears and how much space surrounds it. A design system provides a small set of approved spacing values, such as 4px, 8px, and 16px. Using only those values keeps the design consistent across the whole application.
Snap a spacing value to the nearest token
const space = { s: 4, m: 8, l: 16 };
function nearestToken(px) {
let best = "s";
for (const [name, value] of Object.entries(space)) {
if (Math.abs(value - px) < Math.abs(space[best] - px)) best = name;
}
return best + " (" + space[best] + "px)";
}
for (const px of [5, 10, 15, 30]) console.log(px + "px -> " + nearestToken(px));
Expected output:
5px -> s (4px)
10px -> m (8px)
15px -> l (16px)
30px -> l (16px)
A designer who chooses "15px" is close to the 16px design token, but it is still not the approved value. Small differences like that add up over time, and the page gradually stops matching the rest of the product.
Design Systems
A design system is the team's shared collection of colours, spacing values, fonts, and reusable components. These values are stored as design tokens: named values such as "subtle": "#5f6b7a".
The agent should use only values from the design tokens. The check_tokens tool enforces this rule. Every colour and spacing value used in the HTML must exist in design/tokens.json.
Find colours that are not design tokens
const tokens = { text: "#1b1f24", subtle: "#5f6b7a", muted: "#9aa3ad", accent: "#0056d2" };
const html = '<h2 style="color: #222222">Export</h2><p style="color: #5f6b7a">Running</p><button style="color: #0077cc">Retry</button>';
const used = html.match(/#[0-9a-f]{6}/gi);
const allowed = Object.values(tokens);
for (const c of used) console.log(c + ": " + (allowed.includes(c) ? "token" : "NOT a token"));
Expected output:
#222222: NOT a token
#5f6b7a: token
#0077cc: NOT a token
#222222 looks very similar to the text token. However, a value that is only similar still breaks the design system. If the team changes the text token later, this heading will not update with the rest of the product.
UI design agent with no design system
This agent never read tokens.json, so it guessed the values. The token check finds 4 values that do not match any design token.
One of the guessed grey colours also fails the contrast check. The agent must read the tokens and create a new draft.
Accessibility Checks
Accessibility (often written as a11y) means that everyone can use the page, including people who use screen readers, keyboards, or zoom features. The check_a11y tool checks three rules.
Images Need Alt Text
A screen reader cannot see an image. alt="Export in progress" tells the screen reader what to read aloud.
Buttons Need a Name
A button that shows only an icon, such as ⟳, has no visible text for a screen reader to announce. aria-label="Retry the export" gives the button a readable name.
Find images with no alt and buttons with no name
const html = [
'<img src="spinner.svg">',
'<img src="chart.png" alt="Rows exported per day">',
"<button>⟳</button>",
'<button aria-label="Retry the export">⟳</button>',
"<button>Retry</button>",
];
for (const tag of html) {
let problem = "ok";
if (tag.startsWith("<img") && !tag.includes("alt=")) problem = "image has no alt text";
const inside = tag.replace(/<[^>]+>/g, "");
if (tag.startsWith("<button") && !tag.includes("aria-label=") && !/[A-Za-z]/.test(inside)) problem = "button has no name";
console.log(problem.padEnd(22) + tag);
}
Expected output:
image has no alt text <img src="spinner.svg">
ok <img src="chart.png" alt="Rows exported per day">
button has no name <button>⟳</button>
ok <button aria-label="Retry the export">⟳</button>
ok <button>Retry</button>
A button that already contains the word "Retry" has a name that a screen reader can read. Only buttons that use an icon without text need an aria-label.
Text Needs Enough Contrast
Contrast measures how clearly text stands out from its background. For normal text, the WCAG guideline requires a contrast ratio of at least 4.5 to 1. Light grey text on a white background often fails this requirement.
Contrast ratio against a white background
function contrastOnWhite(hex) {
const ch = [1, 3, 5].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255)
.map((v) => (v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4));
const lum = 0.2126 * ch[0] + 0.7152 * ch[1] + 0.0722 * ch[2];
return 1.05 / (lum + 0.05);
}
for (const [name, hex] of [["text", "#1b1f24"], ["subtle", "#5f6b7a"], ["muted", "#9aa3ad"], ["guess", "#777777"]]) {
const r = contrastOnWhite(hex);
console.log(name.padEnd(7) + r.toFixed(2) + ":1 " + (r >= 4.5 ? "pass" : "FAIL"));
}
Expected output:
text 16.56:1 pass
subtle 5.43:1 pass
muted 2.56:1 FAIL
guess 4.48:1 FAIL
The muted token exists for things like disabled borders, not for text that people need to read. And #777777 misses the requirement by a very small amount: 4.48 is still not 4.5.
UI Design Agent with the Design System
The draft uses token-based colours, so the token check passes. However, the accessibility check finds 3 problems: the image is missing alt text, the small text uses the muted token, and the ⟳ button has no accessible name. The agent fixes all three issues, runs both checks again, and hands the design over after 9 steps.
Open the Preview tab and select export-panel.html to view the panel in a browser-like view. Enable Show the files before the agent ran to compare the result. Before the run, the page does not exist.
Easy Way to Remember: tokens for looks, checks for people. The design system keeps pages consistent. Accessibility checks keep them usable.
A design that looks good can still fail accessibility requirements. Never skip the accessibility check just because the page looks fine on your own screen.
Common Mistakes
| Mistake | Wrong idea | Correct idea | What goes wrong |
|---|---|---|---|
| No tokens in context | "The agent knows good colours." | Read tokens.json first. | Near-match colours break the design system. |
| Light grey text | "It looks elegant." | Check contrast: 4.5:1 or higher. | People cannot read the status text. |
| Icon-only button | "Everyone knows ⟳ means retry." | Add an aria-label. | Screen readers announce only "button" and nothing more. |
| Only the happy state | "Done is the main case." | Design all 4 states. | The Failed state does not include a Retry button. |
| Checking only once | "The draft passed earlier." | Run checks after the final change. | A later fix introduces a new problem. |
Exercises
Each exercise ends with a value on the last line. Press Check to compare it with the expected answer.
What to Remember
- Draft using the design system, run the checks, fix the issues, run the checks again, and only then hand the design over.
- A wireframe should include every state, not just the happy path.
- Use only design tokens for colours and spacing values.
- The three accessibility checks in this lesson are alt text, button names, and text contrast of at least 4.5:1.
- Hand the design over only after both the accessibility check and the token check pass following the final change.
Next: Frontend Development Agents, the agent that turns the design into a working component.