[
{
"No": "1",
"Category": "Accessibility",
"Issue": "Icon Button Labels",
"Keywords": "icon button aria-label",
"Platform": "Web",
"Description": "Icon-only buttons must have accessible names",
"Do": "Add aria-label to icon buttons",
"Don't": "Icon button without label",
"Code Example Good": "<button aria-label='Close'><XIcon /></button>",
"Code Example Bad": "<button><XIcon /></button>",
"Severity": "Critical"
},
{
"No": "2",
"Category": "Accessibility",
"Issue": "Form Control Labels",
"Keywords": "form input label aria",
"Platform": "Web",
"Description": "All form controls need labels or aria-label",
"Do": "Use label element or aria-label",
"Don't": "Input without accessible name",
"Code Example Good": "<label for='email'>Email</label><input id='email' />",
"Code Example Bad": "<input placeholder='Email' />",
"Severity": "Critical"
},
{
"No": "3",
"Category": "Accessibility",
"Issue": "Keyboard Handlers",
"Keywords": "keyboard onclick onkeydown",
"Platform": "Web",
"Description": "Interactive elements must support keyboard interaction",
"Do": "Add onKeyDown alongside onClick",
"Don't": "Click-only interaction",
"Code Example Good": "<div onClick={fn} onKeyDown={fn} tabIndex={0}>",
"Code Example Bad": "<div onClick={fn}>",
"Severity": "High"
},
{
"No": "4",
"Category": "Accessibility",
"Issue": "Semantic HTML",
"Keywords": "semantic button a label",
"Platform": "Web",
"Description": "Use semantic HTML before ARIA attributes",
"Do": "Use button/a/label elements",
"Don't": "Div with role attribute",
"Code Example Good": "<button onClick={fn}>Submit</button>",
"Code Example Bad": "<div role='button' onClick={fn}>Submit</div>",
"Severity": "High"
},
{
"No": "5",
"Category": "Accessibility",
"Issue": "Aria Live",
"Keywords": "aria-live polite async",
"Platform": "Web",
"Description": "Async updates need aria-live for screen readers",
"Do": "Add aria-live='polite' for dynamic content",
"Don't": "Silent async updates",
"Code Example Good": "<div aria-live='polite'>{status}</div>",
"Code Example Bad": "<div>{status}</div> // no announcement",
"Severity": "Medium"
},
{
"No": "6",
"Category": "Accessibility",
"Issue": "Decorative Icons",
"Keywords": "aria-hidden decorative icon",
"Platform": "Web",
"Description": "Decorative icons should be hidden from screen readers",
"Do": "Add aria-hidden='true' to decorative icons",
"Don't": "Decorative icon announced",
"Code Example Good": "<Icon aria-hidden='true' />",
"Code Example Bad": "<Icon /> // announced as 'image'",
"Severity": "Medium"
},
{
"No": "7",
"Category": "Focus",
"Issue": "Visible Focus States",
"Keywords": "focus-visible outline ring",
"Platform": "Web",
"Description": "All interactive elements need visible focus states",
"Do": "Use :focus-visible with ring/outline",
"Don't": "No focus indication",
"Code Example Good": "focus-visible:ring-2 focus-visible:ring-blue-500",
"Code Example Bad": "outline-none // no replacement",
"Severity": "Critical"
},
{
"No": "8",
"Category": "Focus",
"Issue": "Never Remove Outline",
"Keywords": "outline-none focus replacement",
"Platform": "Web",
"Description": "Never remove outline without providing replacement",
"Do": "Replace outline with visible alternative",
"Don't": "Remove outline completely",
"Code Example Good": "focus:outline-none focus:ring-2",
"Code Example Bad": "focus:outline-none // nothing else",
"Severity": "Critical"
},
{
"No": "9",
"Category": "Focus",
"Issue": "Checkbox Radio Hit Target",
"Keywords": "checkbox radio label target",
"Platform": "Web",
"Description": "Checkbox/radio must share hit target with label",
"Do": "Wrap input and label together",
"Don't": "Separate tiny checkbox",
"Code Example Good": "<label class='flex gap-2'><input type='checkbox' /><span>Option</span></label>",
"Code Example Bad": "<input type='checkbox' id='x' /><label for='x'>Option</label>",
"Severity": "Medium"
},
{
"No": "10",
"Category": "Forms",
"Issue": "Autocomplete Attribute",
"Keywords": "autocomplete input form",
"Platform": "Web",
"Description": "Inputs need autocomplete attribute for autofill",
"Do": "Add appropriate autocomplete value",
"Don't": "Missing autocomplete",
"Code Example Good": "<input autocomplete='email' type='email' />",
"Code Example Bad": "<input type='email' />",
"Severity": "High"
},
{
"No": "11",
"Category": "Forms",
"Issue": "Semantic Input Types",
"Keywords": "input type email tel url",
"Platform": "Web",
"Description": "Use semantic input type attributes",
"Do": "Use email/tel/url/number types",
"Don't": "text type for everything",
"Code Example Good": "<input type='email' />",
"Code Example Bad": "<input type='text' /> // for email",
"Severity": "Medium"
},
{
"No": "12",
"Category": "Forms",
"Issue": "Never Block Paste",
"Keywords": "paste onpaste password",
"Platform": "Web",
"Description": "Never prevent paste functionality",
"Do": "Allow paste on all inputs",
"Don't": "Block paste on password/code",
"Code Example Good": "<input type='password' />",
"Code Example Bad": "<input onPaste={e => e.preventDefault()} />",
"Severity": "High"
},
{
"No": "13",
"Category": "Forms",
"Issue": "Spellcheck Disable",
"Keywords": "spellcheck email code",
"Platform": "Web",
"Description": "Disable spellcheck on emails and codes",
"Do": "Set spellcheck='false' on codes",
"Don't": "Spellcheck on technical input",
"Code Example Good": "<input spellCheck='false' type='email' />",
"Code Example Bad": "<input type='email' /> // red squiggles",
"Severity": "Low"
},
{
"No": "14",
"Category": "Forms",
"Issue": "Submit Button Enabled",
"Keywords": "submit button disabled loading",
"Platform": "Web",
"Description": "Keep submit enabled and show spinner during requests",
"Do": "Show loading spinner keep enabled",
"Don't": "Disable button during submit",
"Code Example Good": "<button>{loading ? <Spinner /> : 'Submit'}</button>",
"Code Example Bad": "<button disabled={loading}>Submit</button>",
"Severity": "Medium"
},
{
"No": "15",
"Category": "Forms",
"Issue": "Inline Errors",
"Keywords": "error message inline focus",
"Platform": "Web",
"Description": "Show error messages inline near the problem field",
"Do": "Inline error with focus on first error",
"Don't": "Single error at top",
"Code Example Good": "<input /><span class='text-red-500'>{error}</span>",
"Code Example Bad": "<div class='error'>{allErrors}</div> // at top",
"Severity": "High"
},
{
"No": "16",
"Category": "Performance",
"Issue": "Virtualize Lists",
"Keywords": "virtualize list 50 items",
"Platform": "Web",
"Description": "Virtualize lists exceeding 50 items",
"Do": "Use virtual list for large datasets",
"Don't": "Render all items",
"Code Example Good": "<VirtualList items={items} />",
"Code Example Bad": "items.map(item => <Item />)",
"Severity": "High"
},
{
"No": "17",
"Category": "Performance",
"Issue": "Avoid Layout Reads",
"Keywords": "layout read render getboundingclientrect",
"Platform": "Web",
"Description": "Avoid layout reads during render phase",
"Do": "Read layout in effects or callbacks",
"Don't": "getBoundingClientRect in render",
"Code Example Good": "useEffect(() => { el.getBoundingClientRect() })",
"Code Example Bad": "const rect = el.getBoundingClientRect() // in render",
"Severity": "Medium"
},
{
"No": "18",
"Category": "Performance",
"Issue": "Batch DOM Operations",
"Keywords": "batch dom write read",
"Platform": "Web",
"Description": "Group DOM operations to minimize reflows",
"Do": "Batch writes then reads",
"Don't": "Interleave reads and writes",
"Code Example Good": "writes.forEach(w => w()); reads.forEach(r => r())",
"Code Example Bad": "write(); read(); write(); read(); // thrashing",
"Severity": "Medium"
},
{
"No": "19",
"Category": "Performance",
"Issue": "Preconnect CDN",
"Keywords": "preconnect link cdn",
"Platform": "Web",
"Description": "Add preconnect links for CDN domains",
"Do": "Preconnect to known domains",
"Don't": "<link rel='preconnect' href='https://cdn.example.com' />",
"Code Example Good": "// no preconnect hint",
"Code Example Bad": "Low"
},
{
"No": "20",
"Category": "Performance",
"Issue": "Lazy Load Images",
"Keywords": "lazy loading image below-fold",
"Platform": "Web",
"Description": "Lazy-load images below the fold",
"Do": "Use loading='lazy' for below-fold images",
"Don't": "Load all images eagerly",
"Code Example Good": "<img loading='lazy' src='...' />",
"Code Example Bad": "<img src='...' /> // above fold only",
"Severity": "Medium"
},
{
"No": "21",
"Category": "State",
"Issue": "URL Reflects State",
"Keywords": "url state query params",
"Platform": "Web",
"Description": "URL should reflect current UI state",
"Do": "Sync filters/tabs/pagination to URL",
"Don't": "State only in memory",
"Code Example Good": "?tab=settings&page=2",
"Code Example Bad": "useState only // lost on refresh",
"Severity": "High"
},
{
"No": "22",
"Category": "State",
"Issue": "Deep Linking",
"Keywords": "deep link stateful component",
"Platform": "Web",
"Description": "Stateful components should support deep-linking",
"Do": "Enable sharing current view via URL",
"Don't": "No shareable state",
"Code Example Good": "router.push({ query: { ...filters } })",
"Code Example Bad": "setFilters(f) // not in URL",
"Severity": "Medium"
},
{
"No": "23",
"Category": "State",
"Issue": "Confirm Destructive Actions",
"Keywords": "confirm destructive delete modal",
"Platform": "Web",
"Description": "Destructive actions require confirmation",
"Do": "Show confirmation dialog before delete",
"Don't": "Delete without confirmation",
"Code Example Good": "if (confirm('Delete?')) delete()",
"Code Example Bad": "onClick={delete} // no confirmation",
"Severity": "High"
},
{
"No": "24",
"Category": "Typography",
"Issue": "Proper Unicode",
"Keywords": "unicode ellipsis quotes",
"Platform": "Web",
"Description": "Use proper Unicode characters",
"Do": "Use ... curly quotes proper dashes",
"Don't": "ASCII approximations",
"Code Example Good": "'Hello...' with proper ellipsis",
"Code Example Bad": "'Hello...' with three dots",
"Severity": "Low"
},
{
"No": "25",
"Category": "Typography",
"Issue": "Text Overflow",
"Keywords": "truncate line-clamp overflow",
"Platform": "Web",
"Description": "Handle text overflow properly",
"Do": "Use truncate/line-clamp/break-words",
"Don't": "Text overflows container",
"Code Example Good": "<p class='truncate'>Long text...</p>",
"Code Example Bad": "<p>Long text...</p> // overflows",
"Severity": "Medium"
},
{
"No": "26",
"Category": "Typography",
"Issue": "Non-Breaking Spaces",
"Keywords": "nbsp unit brand",
"Platform": "Web",
"Description": "Use non-breaking spaces for units and brand names",
"Do": "Use between number and unit",
"Don't": "10 kg or Next.js 14",
"Code Example Good": "10 kg // may wrap",
"Code Example Bad": "Low"
},
{
"No": "27",
"Category": "Anti-Pattern",
"Issue": "No Zoom Disable",
"Keywords": "viewport zoom disable",
"Platform": "Web",
"Description": "Never disable zoom in viewport meta",
"Do": "Allow user zoom",
"Don't": "<meta name='viewport' content='width=device-width'>",
"Code Example Good": "<meta name='viewport' content='maximum-scale=1'>",
"Code Example Bad": "Critical"
},
{
"No": "28",
"Category": "Anti-Pattern",
"Issue": "No Transition All",
"Keywords": "transition all specific",
"Platform": "Web",
"Description": "Avoid transition: all - specify properties",
"Do": "Transition specific properties",
"Don't": "transition: all",
"Code Example Good": "transition-colors duration-200",
"Code Example Bad": "transition-all duration-200",
"Severity": "Medium"
},
{
"No": "29",
"Category": "Anti-Pattern",
"Issue": "Outline Replacement",
"Keywords": "outline-none ring focus",
"Platform": "Web",
"Description": "Never use outline-none without replacement",
"Do": "Provide visible focus replacement",
"Don't": "Remove outline with nothing",
"Code Example Good": "focus:outline-none focus:ring-2 focus:ring-blue-500",
"Code Example Bad": "focus:outline-none // alone",
"Severity": "Critical"
},
{
"No": "30",
"Category": "Anti-Pattern",
"Issue": "No Hardcoded Dates",
"Keywords": "date format intl locale",
"Platform": "Web",
"Description": "Use Intl for date/number formatting",
"Do": "Use Intl.DateTimeFormat",
"Don't": "Hardcoded date format",
"Code Example Good": "new Intl.DateTimeFormat('en').format(date)",
"Code Example Bad": "date.toLocaleDateString() // or manual format",
"Severity": "Medium"
}
]