{"slug": "what-to-check-when-reviewing-ai-generated-ui", "title": "What to Check When Reviewing AI-Generated UI", "summary": "A developer outlines key accessibility and usability checkpoints for reviewing AI-generated user interfaces, emphasizing proper label-input associations, unique IDs, accessible names for icon buttons, explicit button types, and semantic HTML elements. The guidance applies to hand-written code as well and includes React-specific examples using useId and htmlFor.", "body_md": "AI can help us build a form, a modal, or a dashboard quickly.\n\nThe result may look good. The inputs accept text. The buttons respond. The layout fits the screen.\n\nBut before merging the code, there is another question to ask:\n\n**Does the UI work well beyond the happy path?**\n\nSome details are easy to miss during a visual review. A label may not be connected to its input. An icon button may have no accessible name. A secondary button may submit a form by accident.\n\nThese are review checkpoints, not claims that every AI tool makes these mistakes. They apply to code we write ourselves too.\n\nThe examples below use React, but most of the ideas come from HTML and apply across frameworks. The snippets focus on individual details rather than a complete application.\n\nThis looks reasonable:\n\n```\n<label>Email address</label>\n<input type=\"email\" />\n```\n\nThe text is visible, but the label and input are not connected. In JSX, use `htmlFor` with a matching input `id`:\n\n```\n<label htmlFor=\"email\">Email address</label>\n<input id=\"email\" name=\"email\" type=\"email\" />\n```\n\nThis gives the input an accessible name. Clicking the label also focuses the input. In plain HTML, the attribute is `for`; React uses `htmlFor`.\n\nWrapping an input inside its label is another valid approach. The point is to create the association, not to add `htmlFor` everywhere.\n\nAlso, remember that a placeholder is a hint. It should never replace a visible label.\n\nA hardcoded `id=\"email\"` can work for one field. But what happens when the same component appears twice on the same screen?\n\nDuplicate IDs break label associations and assistive technology references. For reusable React components, React's `useId` hook ensures instance-level uniqueness:\n\n``` js\nimport { useId } from \"react\";\n\nfunction EmailField() {\n  const id = useId();\n\n  return (\n    <div>\n      <label htmlFor={id}>Email address</label>\n      <input\n        id={id}\n        name=\"email\"\n        type=\"email\"\n        autoComplete=\"email\"\n      />\n    </div>\n  );\n}\n```\n\nEach instance gets its own unique ID for the label connection.\n\n**Rule of thumb:** `useId` is for accessibility relationships. List keys should come from your underlying data.\n\nA magnifying glass icon may clearly mean “Search” to someone looking at the screen. Make sure the button also provides a programmatic name for screen readers, as well as a visual cue for sighted users who might find the icon ambiguous:\n\n```\n<button type=\"button\" aria-label=\"Search\" title=\"Search\">\n  <svg aria-hidden=\"true\" viewBox=\"0 0 24 24\">\n    <circle cx=\"10\" cy=\"10\" r=\"6\" fill=\"none\" stroke=\"currentColor\" />\n    <path d=\"m15 15 6 6\" stroke=\"currentColor\" />\n  </svg>\n</button>\n```\n\nHere, `aria-label` supplies the accessible name, while `aria-hidden=\"true\"` hides the decorative SVG to avoid redundant announcements. Adding `title` or a tooltip gives sighted mouse and keyboard users clarity on hover and focus.\n\nIf a button already contains visible text:\n\n```\n<button type=\"submit\">Save changes</button>\n```\n\nIt does not need an additional `aria-label`. Prefer visible text whenever the design allows.\n\nInside a `<form>`, an ordinary `<button>` without an explicit `type` defaults to `type=\"submit\"`.\n\nThat becomes an immediate issue when its purpose is “Cancel” or “Show password.” Make the intention explicit on every button:\n\n```\n<button type=\"button\" onClick={onCancel}>\n  Cancel\n</button>\n\n<button type=\"submit\">\n  Create account\n</button>\n```\n\nReview every secondary button inside a form. A single missing `type=\"button\"` attribute can trigger accidental form submissions.\n\nA clickable `<div>` can look identical to a button:\n\n```\n<div onClick={openSettings}>Settings</div>\n```\n\nHowever, a `<div>` does not provide native button keyboard handling, focusability, or form integration. Adding `role=\"button\"` without implementing `Enter` and `Space` key handlers still leaves keyboard users stranded.\n\nUse native semantic elements:\n\n```\n{/* For an action */}\n<button type=\"button\" onClick={openSettings}>\n  Settings\n</button>\n\n{/* For navigation */}\n<a href=\"/settings\">Settings</a>\n```\n\nNative HTML elements give you focus management, accessibility traits, and keyboard operability for free before you write a single line of extra script.\n\nSet your mouse aside and test the page using only `Tab`, `Shift + Tab`, `Enter`, `Space`, and `Escape`:\n\nWhen styling focus states in CSS, prefer `:focus-visible` over `:focus`:\n\n```\n/* Better: Shows strong outline only during keyboard navigation */\nbutton:focus-visible {\n  outline: 2px solid #2563eb;\n  outline-offset: 2px;\n}\n```\n\nNever set `outline: none` without providing a prominent, high-contrast `:focus-visible` replacement.\n\nA red border alone does not explain the issue to users. An error message should identify what went wrong and be programmatically tied to the field:\n\n``` js\nimport { useId } from \"react\";\n\nfunction UsernameField({ error }) {\n  const id = useId();\n  const errorId = `${id}-error`;\n\n  return (\n    <div>\n      <label htmlFor={id}>Username</label>\n      <input\n        id={id}\n        name=\"username\"\n        aria-invalid={error ? true : undefined}\n        aria-describedby={error ? errorId : undefined}\n      />\n      {error && (\n        <p id={errorId} role=\"alert\">\n          {error}\n        </p>\n      )}\n    </div>\n  );\n}\n```\n\n`aria-invalid` flags the field's state to assistive technology.`aria-describedby` associates the error text with the input so it reads aloud when the field receives focus.`role=\"alert\"` or using `aria-live=\"polite\"` ensures dynamically rendered client-side errors are announced immediately, even if the input is already focused.\nReview more than just the successful response.\n\nAsk:\n\nWhen indicating submission progress:\n\n```\n<button type=\"submit\" disabled={isSubmitting} aria-busy={isSubmitting}>\n  {isSubmitting ? \"Saving…\" : \"Save changes\"}\n</button>\n```\n\n**Note on disabled buttons:** Adding `disabled` directly to a focused button can cause screen readers to immediately drop focus back to the top of the `<body>`. For critical flows, consider keeping the button focusable with `aria-disabled=\"true\"` while ignoring pointer and click events in your handler.\n\nAI prompts and sample mocks often feature convenient, short text. Real production data is messy:\n\n`alt` text, while decorative illustrations use `alt=\"\"` to avoid cluttering screen readers.\nUse this checklist during code review:\n\n`htmlFor` / `useId`).` aria-label`) and visual tooltips.` type=\"button\"` or `type=\"submit\"`.`<button>`, while navigation uses `<a>`.`:focus-visible` indicators.\nThis checklist does not have to remain a manual reference. You can also include it in your coding agent’s review instructions.\n\nAsk the agent to check generated UI for:\n\nAn agent can catch many code-level problems before a pull request reaches manual review. However, it cannot fully reproduce how the interface feels with a keyboard, screen reader, browser zoom, or real production content. Use agent review as an additional review layer, then verify the important interactions manually.", "url": "https://wpnews.pro/news/what-to-check-when-reviewing-ai-generated-ui", "canonical_source": "https://dev.to/janarthanan_soundararajan/what-to-check-when-reviewing-ai-generated-ui-h28", "published_at": "2026-09-09 06:05:57+00:00", "updated_at": "2026-09-09 06:28:06.850371+00:00", "lang": "en", "topics": ["developer-tools", "ai-products"], "entities": ["React"], "alternates": {"html": "https://wpnews.pro/news/what-to-check-when-reviewing-ai-generated-ui", "markdown": "https://wpnews.pro/news/what-to-check-when-reviewing-ai-generated-ui.md", "text": "https://wpnews.pro/news/what-to-check-when-reviewing-ai-generated-ui.txt", "jsonld": "https://wpnews.pro/news/what-to-check-when-reviewing-ai-generated-ui.jsonld"}}