-
Notifications
You must be signed in to change notification settings - Fork 0
Accessibility violations #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-031: Accesskeys — duplicate accesskey values | ||
| export default function Accesskeys() { | ||
| return ( | ||
| <nav> | ||
| <a href="/home" accessKey="h">Home</a> | ||
| <a href="/help" accessKey="h">Help</a> | ||
| <a href="/search" accessKey="s">Search</a> | ||
| <a href="/settings" accessKey="s">Settings</a> | ||
| </nav> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // accesslint-034: Empty Heading — heading used as accordion trigger with no text | ||
| // accesslint-075: Button Name — empty button | ||
| export default function Accordion() { | ||
| return ( | ||
| <div> | ||
| <h3><button></button></h3> | ||
| <div>Accordion panel 1 content.</div> | ||
| <h3><button></button></h3> | ||
| <div>Accordion panel 2 content.</div> | ||
| <h3><button></button></h3> | ||
| <div>Accordion panel 3 content.</div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // accesslint-058: ARIA Allowed Attr — ARIA attributes not allowed for role | ||
| export default function AriaAllowed() { | ||
| return ( | ||
| <div> | ||
| <h2 aria-checked="true">Heading with aria-checked</h2> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: ARIA attribute "aria-checked" is not allowed on role "heading". ARIA attributes must be allowed for the element's role. DetailsAttribute: aria-checked="true", role: heading, allowed role-specific attributes: aria-level Each ARIA role supports specific attributes. Using unsupported attributes creates confusion for assistive technologies. Check the ARIA specification for which attributes are valid for each role, or remove the attribute if it's not needed. Also on line 7. |
||
| <p aria-selected="true">Paragraph with aria-selected</p> | ||
| <img src="/photo.jpg" alt="Photo" aria-expanded="true" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best Practice: Alt text "Photo" contains redundant word(s): photo. Image alt text should not contain words like 'image', 'photo', or 'picture' — screen readers already announce the element type. DetailsCurrent alt: "Photo", redundant word(s): photo Screen readers already announce 'image' or 'graphic' before reading alt text, so phrases like 'image of', 'photo of', or 'picture of' are redundant. Remove these words and describe what the image shows. For example, change 'image of a dog' to 'golden retriever playing fetch'. WCAG 4.1.2: ARIA attribute "aria-checked" is not allowed on role "heading". |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // accesslint-055: ARIA Valid Attr — misspelled ARIA attributes | ||
| // accesslint-056: ARIA Valid Attr Value — invalid ARIA attribute values | ||
| export default function AriaAttrs() { | ||
| return ( | ||
| <div> | ||
| <button aria-expandd="true">Toggle</button> | ||
| <input type="text" aria-requird="true" /> | ||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Invalid ARIA attribute "aria-expandd". ARIA attributes must be valid (correctly spelled). DetailsMisspelled ARIA attributes are ignored by assistive technologies. Check the spelling against the WAI-ARIA specification. Common mistakes: aria-labeledby (should be aria-labelledby), aria-role (should be role), aria-description (valid in ARIA 1.3+). WCAG 4.1.2: ARIA attribute "aria-expandd" is not allowed on role "button". ARIA attributes must be allowed for the element's role. DetailsAttribute: aria-expandd="true", role: button, allowed role-specific attributes: aria-disabled, aria-expanded, aria-haspopup, aria-pressed Each ARIA role supports specific attributes. Using unsupported attributes creates confusion for assistive technologies. Check the ARIA specification for which attributes are valid for each role, or remove the attribute if it's not needed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. Form elements must have labels. Use , aria-label, or aria-labelledby. Detailstype: text Every form input needs an accessible label so users understand what information to enter. Use a element with a for attribute matching the input's id, wrap the input in a , or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing. |
||
| <div role="checkbox" aria-checked="maybe">Option</div> | ||
| <div aria-live="aggressive">Updates here</div> | ||
| <button aria-pressed="none">Like</button> | ||
|
Comment on lines
+8
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: aria-checked must be "true", "false", or "mixed", got "maybe". ARIA attributes must have valid values. DetailsEach ARIA attribute accepts specific value types. Boolean attributes (aria-hidden, aria-disabled) accept only 'true' or 'false'. Tristate attributes (aria-checked, aria-pressed) also accept 'mixed'. Token attributes (aria-live, aria-autocomplete) accept predefined values. ID reference attributes (aria-labelledby, aria-describedby) must reference existing element IDs. |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // accesslint-060: ARIA Required Children — missing required child roles | ||
| export default function AriaChildren() { | ||
| return ( | ||
| <div> | ||
| <ul role="tablist"> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "tablist" requires children with role: tab. Certain ARIA roles require specific child roles to be present. DetailsSome ARIA roles represent containers that must contain specific child roles for proper semantics. For example, a list must contain listitems, a menu must contain menuitems. Add the required child elements with appropriate roles, or use native HTML elements that provide these semantics implicitly (e.g.,
|
||
| <li>Tab 1</li> | ||
| <li>Tab 2</li> | ||
| </ul> | ||
| <div role="list"> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "tablist" requires children with role: tab. |
||
| <span>Item 1</span> | ||
| <span>Item 2</span> | ||
| </div> | ||
| <div role="grid"> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "tablist" requires children with role: tab. |
||
| <div>Cell 1</div> | ||
| <div>Cell 2</div> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // accesslint-064: ARIA Command Name — command roles without names | ||
| // accesslint-065: ARIA Input Field Name — input roles without names | ||
| export default function AriaCommandNames() { | ||
| return ( | ||
| <div> | ||
| <div role="button"></div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Button has no discernible text. Buttons must have discernible text. DetailsScreen reader users need to know what a button does. Add visible text content, aria-label, or aria-labelledby. For icon buttons, use aria-label describing the action (e.g., aria-label='Close'). If the button contains an image, ensure the image has alt text describing the button's action. |
||
| <div role="link"></div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 2.4.4, WCAG 4.1.2: Link has no discernible text. Links must have discernible text via content, aria-label, or aria-labelledby. DetailsScreen reader users need to know where a link goes. Add descriptive text content, aria-label, or use aria-labelledby. For image links, ensure the image has alt text describing the link destination. Avoid generic text like 'click here' or 'read more'—link text should make sense out of context. |
||
| <div role="menuitem"></div> | ||
|
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: ARIA command has no accessible name. ARIA commands must have an accessible name. DetailsInteractive ARIA command roles (button, link, menuitem) must have accessible names so users know what action they perform. Add visible text content, aria-label, or aria-labelledby to provide a name. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "menuitem" must be contained within: menu, menubar, group. Certain ARIA roles must be contained within specific parent roles. DetailsSome ARIA roles represent items that must exist within specific container roles. For example, a listitem must be within a list, a tab must be within a tablist. Wrap the element in the appropriate parent, or use native HTML elements that provide this structure (e.g.,
|
||
| <div role="textbox"></div> | ||
| <div role="searchbox"></div> | ||
| <div role="spinbutton"></div> | ||
|
Comment on lines
+9
to
+11
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. Form elements must have labels. Use , aria-label, or aria-labelledby. Detailsrole: textbox Every form input needs an accessible label so users understand what information to enter. Use a element with a for attribute matching the input's id, wrap the input in a , or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing. WCAG 4.1.2: ARIA input field has no accessible name. ARIA input fields must have an accessible name. DetailsARIA input widgets (combobox, listbox, searchbox, slider, spinbutton, textbox) must have accessible names so users understand what data to enter. Add a visible label with aria-labelledby, or use aria-label if a visible label is not possible. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Role "spinbutton" requires attribute "aria-valuenow". Elements with ARIA roles must have all required ARIA attributes. DetailsSome ARIA roles require specific attributes to function correctly. For example, checkbox requires aria-checked, slider requires aria-valuenow, heading requires aria-level. Without these attributes, assistive technologies cannot convey the element's state or value to users. Add the missing required attribute with an appropriate value. |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| // accesslint-069: ARIA Dialog Name — dialogs without accessible names | ||
| export default function AriaDialogs() { | ||
| return ( | ||
| <div> | ||
| <div role="dialog"> | ||
| <p>Are you sure you want to delete this?</p> | ||
| <button>Yes</button> | ||
| <button>No</button> | ||
| </div> | ||
| <div role="alertdialog"> | ||
| <p>Session expired.</p> | ||
| <button>OK</button> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // accesslint-063: ARIA Hidden Focus — focusable elements inside aria-hidden | ||
| export default function AriaHiddenFocus() { | ||
| return ( | ||
| <div> | ||
| <div aria-hidden="true"> | ||
| <button>Hidden but focusable button</button> | ||
| <a href="/secret">Hidden but focusable link</a> | ||
| <input type="text" placeholder="Hidden but focusable input" /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-067: ARIA Meter Name — meters without accessible names | ||
| // accesslint-068: ARIA Progressbar Name — progressbars without names | ||
| export default function AriaMeters() { | ||
| return ( | ||
| <div> | ||
| <div role="meter" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Meter has no accessible name. ARIA meter elements must have an accessible name. DetailsMeter elements display a value within a known range (like disk usage or password strength). They must have accessible names so screen reader users understand what is being measured. Use aria-label or aria-labelledby to provide context. Also on line 8. |
||
| <div role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"></div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Progressbar has no accessible name. ARIA progressbar elements must have an accessible name. DetailsProgress indicators must have accessible names so screen reader users understand what process is being tracked. Use aria-label (e.g., 'File upload progress') or aria-labelledby to reference a visible heading or label. |
||
| <div role="meter" aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"></div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Meter has no accessible name. |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-061: ARIA Required Parent — roles missing required parents | ||
| export default function AriaParent() { | ||
| return ( | ||
| <div> | ||
| <div role="tab">Tab without tablist</div> | ||
| <div role="listitem">Item without list</div> | ||
| <div role="option">Option without listbox</div> | ||
| <div role="row">Row without table/grid</div> | ||
|
Comment on lines
+5
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "tab" must be contained within: tablist. Certain ARIA roles must be contained within specific parent roles. DetailsSome ARIA roles represent items that must exist within specific container roles. For example, a listitem must be within a list, a tab must be within a tablist. Wrap the element in the appropriate parent, or use native HTML elements that provide this structure (e.g.,
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "row" requires children with role: cell or columnheader or gridcell or rowheader. Certain ARIA roles require specific child roles to be present. DetailsSome ARIA roles represent containers that must contain specific child roles for proper semantics. For example, a list must contain listitems, a menu must contain menuitems. Add the required child elements with appropriate roles, or use native HTML elements that provide these semantics implicitly (e.g.,
|
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| // accesslint-072: ARIA Prohibited Attr — prohibited attributes for roles | ||
| export default function AriaProhibited() { | ||
| return ( | ||
| <div> | ||
| <div role="presentation" aria-label="Decorative section">Content</div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: aria-label and aria-labelledby are prohibited on role "presentation". ARIA attributes must not be prohibited for the element's role. DetailsSome ARIA roles prohibit certain attributes. For example, roles like 'none', 'presentation', 'generic', and text-level roles (code, emphasis, strong) prohibit aria-label and aria-labelledby because naming is not supported for these roles. Remove the prohibited attributes or change the role. Also on line 7. |
||
| <div role="none" aria-describedby="desc1">More content</div> | ||
| <img role="presentation" aria-label="Decorative image" src="/bg.png" /> | ||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Presentation role conflicts with: has accessible name. The role will be ignored. Elements with role='presentation' or role='none' must not be focusable or have global ARIA attributes. DetailsWhen an element has role='presentation' or role='none', it's marked as decorative and removed from the accessibility tree. However, if the element is focusable or has certain ARIA attributes, the presentation role is ignored and the element remains accessible. This creates confusion. Either remove the presentation role, or remove the focusability/ARIA attributes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: aria-label and aria-labelledby are prohibited on role "presentation". |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // accesslint-057: ARIA Required Attr — missing required attributes | ||
| export default function AriaRequired() { | ||
| return ( | ||
| <div> | ||
| <div role="checkbox">Accept terms</div> | ||
| <div role="slider">Volume</div> | ||
| <div role="combobox">Select option</div> | ||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. Form elements must have labels. Use , aria-label, or aria-labelledby. Detailsrole: slider Every form input needs an accessible label so users understand what information to enter. Use a element with a for attribute matching the input's id, wrap the input in a , or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing. |
||
| <div role="scrollbar">Scroll</div> | ||
|
Comment on lines
+5
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Role "checkbox" requires attribute "aria-checked". Elements with ARIA roles must have all required ARIA attributes. DetailsSome ARIA roles require specific attributes to function correctly. For example, checkbox requires aria-checked, slider requires aria-valuenow, heading requires aria-level. Without these attributes, assistive technologies cannot convey the element's state or value to users. Add the missing required attribute with an appropriate value. |
||
| <div role="separator" tabIndex="0">---</div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // accesslint-054: ARIA Roles — invalid role values | ||
| // accesslint-059: ARIA Allowed Role — inappropriate roles for elements | ||
| export default function AriaRoles() { | ||
| return ( | ||
| <div> | ||
| <div role="buttn">Click me</div> | ||
| <div role="chckbox">Option A</div> | ||
| <span role="headin" aria-level="2">Title</span> | ||
|
Comment on lines
+6
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Invalid ARIA role "buttn". ARIA role values must be valid. DetailsInvalid role values are ignored by assistive technologies, meaning the element will not have the intended semantics. Check the spelling and use only roles defined in the WAI-ARIA specification. Common roles include: button, link, navigation, main, dialog, alert, tab, tabpanel, menu, menuitem. |
||
| <p role="checkbox">I agree to terms</p> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Role "checkbox" requires attribute "aria-checked". Elements with ARIA roles must have all required ARIA attributes. DetailsSome ARIA roles require specific attributes to function correctly. For example, checkbox requires aria-checked, slider requires aria-valuenow, heading requires aria-level. Without these attributes, assistive technologies cannot convey the element's state or value to users. Add the missing required attribute with an appropriate value. |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // accesslint-066: ARIA Toggle Field Name — toggle fields without names | ||
| export default function AriaToggleFields() { | ||
| return ( | ||
| <div> | ||
| <div role="checkbox" aria-checked="false"></div> | ||
| <div role="switch" aria-checked="true"></div> | ||
| <div role="radio" aria-checked="false"></div> | ||
| <div role="menuitemcheckbox" aria-checked="false"></div> | ||
| <div role="menuitemradio" aria-checked="false"></div> | ||
|
Comment on lines
+5
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. Form elements must have labels. Use , aria-label, or aria-labelledby. Detailsrole: checkbox Every form input needs an accessible label so users understand what information to enter. Use a element with a for attribute matching the input's id, wrap the input in a , or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing. WCAG 4.1.2: ARIA toggle field has no accessible name. ARIA toggle fields must have an accessible name. DetailsARIA toggle controls (checkbox, switch, radio, menuitemcheckbox, menuitemradio) must have accessible names so users understand what option they're selecting. Add visible text content, aria-label, or use aria-labelledby to reference a visible label.
Comment on lines
+8
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Role "menuitemcheckbox" must be contained within: menu, menubar, group. Certain ARIA roles must be contained within specific parent roles. DetailsSome ARIA roles represent items that must exist within specific container roles. For example, a listitem must be within a list, a tab must be within a tablist. Wrap the element in the appropriate parent, or use native HTML elements that provide this structure (e.g.,
|
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| // accesslint-091: Audio Captions — audio without text alternatives | ||
| export default function AudioPlayer() { | ||
| return ( | ||
| <div> | ||
| <audio src="/podcast-ep1.mp3" controls></audio> | ||
| <audio controls> | ||
| <source src="/podcast-ep2.ogg" type="audio/ogg" /> | ||
| <source src="/podcast-ep2.mp3" type="audio/mpeg" /> | ||
| </audio> | ||
| </div> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // accesslint-077: Link Name — empty breadcrumb separator links | ||
| // accesslint-011: Image Alt — separator images without alt | ||
| export default function Breadcrumbs() { | ||
| return ( | ||
| <nav> | ||
| <a href="/"><img src="/home-icon.svg" /></a> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 2.4.4, WCAG 4.1.2: Link has no discernible text. Links must have discernible text via content, aria-label, or aria-labelledby. Detailshref: / Screen reader users need to know where a link goes. Add descriptive text content, aria-label, or use aria-labelledby. For image links, ensure the image has alt text describing the link destination. Avoid generic text like 'click here' or 'read more'—link text should make sense out of context. |
||
| <img src="/chevron.svg" /> | ||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. Images must have alternate text. Add an alt attribute to DetailsLink href: / Every image needs an alt attribute. For informative images, describe the content or function concisely. For decorative images (backgrounds, spacers, purely visual flourishes), use alt='' to hide them from screen readers. Never omit alt entirely—screen readers may read the filename instead. |
||
| <a href="/products">Products</a> | ||
| <img src="/chevron.svg" /> | ||
| <a href="/products/widgets">Widgets</a> | ||
| </nav> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // accesslint-011: Image Alt — card images missing alt | ||
| // accesslint-077: Link Name — empty links | ||
| export default function CardGrid() { | ||
| return ( | ||
| <div> | ||
| <div className="card"> | ||
| <a href="/product/1"><img src="/product-1.jpg" /></a> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. Images must have alternate text. Add an alt attribute to DetailsLink href: /product/1 Every image needs an alt attribute. For informative images, describe the content or function concisely. For decorative images (backgrounds, spacers, purely visual flourishes), use alt='' to hide them from screen readers. Never omit alt entirely—screen readers may read the filename instead. WCAG 2.4.4, WCAG 4.1.2: Link has no discernible text. Links must have discernible text via content, aria-label, or aria-labelledby. Detailshref: /product/1 Screen reader users need to know where a link goes. Add descriptive text content, aria-label, or use aria-labelledby. For image links, ensure the image has alt text describing the link destination. Avoid generic text like 'click here' or 'read more'—link text should make sense out of context. |
||
| <h3>Product One</h3> | ||
| <p>Description of product one.</p> | ||
| </div> | ||
| <div className="card"> | ||
| <a href="/product/2"><img src="/product-2.jpg" /></a> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. WCAG 2.4.4, WCAG 4.1.2: Link has no discernible text. |
||
| <h3>Product Two</h3> | ||
| <p>Description of product two.</p> | ||
| </div> | ||
| <div className="card"> | ||
| <a href="/product/3"><img src="/product-3.jpg" /></a> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. WCAG 2.4.4, WCAG 4.1.2: Link has no discernible text. |
||
| <h3>Product Three</h3> | ||
| <p>Description of product three.</p> | ||
| </div> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| // accesslint-011: Image Alt — carousel images without alt | ||
| // accesslint-075: Button Name — prev/next buttons without text | ||
| export default function Carousel() { | ||
| return ( | ||
| <div> | ||
| <button><img src="/arrow-left.svg" /></button> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. Images must have alternate text. Add an alt attribute to DetailsEvery image needs an alt attribute. For informative images, describe the content or function concisely. For decorative images (backgrounds, spacers, purely visual flourishes), use alt='' to hide them from screen readers. Never omit alt entirely—screen readers may read the filename instead. WCAG 4.1.2: Button has no discernible text. Buttons must have discernible text. DetailsScreen reader users need to know what a button does. Add visible text content, aria-label, or aria-labelledby. For icon buttons, use aria-label describing the action (e.g., aria-label='Close'). If the button contains an image, ensure the image has alt text describing the button's action. |
||
| <div> | ||
| <img src="/slide-1.jpg" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. |
||
| <img src="/slide-2.jpg" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. |
||
| <img src="/slide-3.jpg" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. |
||
| </div> | ||
| <button><img src="/arrow-right.svg" /></button> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| // accesslint-020: Form Label — inputs missing labels | ||
| export default function ContactForm() { | ||
| return ( | ||
| <form> | ||
| <div> | ||
| <input type="text" placeholder="Your name" /> | ||
| </div> | ||
| <div> | ||
| <input type="email" placeholder="Email address" /> | ||
| </div> | ||
| <div> | ||
| <input type="tel" placeholder="Phone number" /> | ||
| </div> | ||
| <div> | ||
| <textarea placeholder="Message"></textarea> | ||
| </div> | ||
| <button type="submit">Send</button> | ||
| </form> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| // accesslint-088: Empty Table Header — table headers with no text | ||
| // accesslint-084: Table Headers Attr — invalid header references | ||
| export default function DataTable() { | ||
| return ( | ||
| <table> | ||
| <thead> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best Practice: Table header cell is empty. Add text or use aria-label. Table header cells should have visible text. DetailsEmpty table headers provide no information to screen reader users. Either add descriptive text to the header, or if the header is intentionally empty (like a corner cell), consider using a td element instead or adding a visually hidden label. |
||
| <tr> | ||
| <th></th> | ||
| <th>Name</th> | ||
| <th></th> | ||
| <th>Email</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td headers="nonexistent">1</td> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Headers attribute references non-existent ID "nonexistent". All cells in a table using headers attribute must reference valid header IDs. DetailsThe headers attribute on table cells must reference IDs of header cells (th or td) within the same table. This creates explicit associations for screen readers. Verify all referenced IDs exist and spell them correctly. For simple tables, consider using scope on th elements instead. |
||
| <td>Alice</td> | ||
| <td>Admin</td> | ||
| <td>alice@example.com</td> | ||
| </tr> | ||
| <tr> | ||
| <td headers="also-missing">2</td> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.3.1: Headers attribute references non-existent ID "nonexistent". |
||
| <td>Bob</td> | ||
| <td>User</td> | ||
| <td>bob@example.com</td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // accesslint-048: Definition List Item — dt/dd outside dl | ||
| // accesslint-049: Definition List — dl with invalid children | ||
| export default function DefinitionListErrors() { | ||
| return ( | ||
| <div> | ||
| <dl> | ||
| <dt>Term 1</dt> | ||
| <dd>Definition 1</dd> | ||
|
Comment on lines
+7
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| <p>Invalid child of dl</p> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
.
|
||
| <div> | ||
| <dt>Term 2</dt> | ||
| <dd>Definition 2</dd> | ||
| </div> | ||
| </dl> | ||
| <dt>Orphaned term</dt> | ||
| <dd>Orphaned definition</dd> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-009: Blink Element — blink must not be used | ||
| // accesslint-010: Marquee Element — marquee must not be used | ||
| export default function DeprecatedElements() { | ||
| return ( | ||
| <div> | ||
| <blink>This text blinks!</blink> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 2.2.2: The element causes accessibility issues. Remove it entirely. The element must not be used. DetailsBlinking content can cause seizures in users with photosensitive epilepsy and is distracting for users with attention disorders. The element is deprecated and should never be used. If you need to draw attention to content, use less intrusive methods like color, borders, or icons. |
||
| <marquee>Scrolling announcement text</marquee> | ||
| <marquee direction="right">More scrolling text</marquee> | ||
|
Comment on lines
+7
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 2.2.2: The element causes accessibility issues. Replace with static content. The element must not be used. DetailsScrolling or moving content is difficult for many users to read, especially those with cognitive or visual disabilities. The element is deprecated. Replace scrolling text with static content. If content must scroll, provide pause/stop controls and ensure it stops after 5 seconds. |
||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // accesslint-089: Duplicate ID ARIA — duplicate IDs used in ARIA references | ||
| export default function DuplicateAriaIds() { | ||
| return ( | ||
| <div> | ||
| <div id="desc1">First description</div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Duplicate ID "desc1" referenced by aria-describedby. IDs used in ARIA and label associations must be unique to avoid broken references. DetailsFirst element: First description Referenced by: aria-describedby When aria-labelledby, aria-describedby, aria-controls, or label[for] reference a duplicate ID, only the first matching element is used. This breaks the intended relationship and may leave controls unnamed or descriptions missing. Ensure IDs referenced by ARIA attributes and label associations are unique throughout the document. |
||
| <div id="desc1">Duplicate description</div> | ||
| <input type="text" aria-describedby="desc1" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. Form elements must have labels. Use , aria-label, or aria-labelledby. Detailstype: text Every form input needs an accessible label so users understand what information to enter. Use a element with a for attribute matching the input's id, wrap the input in a , or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing. |
||
|
|
||
| <div id="label1">Label text</div> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Duplicate ID "desc1" referenced by aria-describedby. |
||
| <div id="label1">Duplicate label text</div> | ||
| <input type="text" aria-labelledby="label1" /> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-075: Button Name — buttons with no discernible text | ||
| export default function EmptyButtons() { | ||
| return ( | ||
| <div> | ||
| <button></button> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Button has no discernible text. Buttons must have discernible text. DetailsScreen reader users need to know what a button does. Add visible text content, aria-label, or aria-labelledby. For icon buttons, use aria-label describing the action (e.g., aria-label='Close'). If the button contains an image, ensure the image has alt text describing the button's action. |
||
| <button><img src="/icon-edit.svg" /></button> | ||
| <button><img src="/icon-delete.svg" /></button> | ||
|
Comment on lines
+6
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. Images must have alternate text. Add an alt attribute to DetailsEvery image needs an alt attribute. For informative images, describe the content or function concisely. For decorative images (backgrounds, spacers, purely visual flourishes), use alt='' to hide them from screen readers. Never omit alt entirely—screen readers may read the filename instead. |
||
| <button><i className="fa fa-cog"></i></button> | ||
| </div> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-034: Empty Heading — headings with no text | ||
| export default function EmptyHeadings() { | ||
| return ( | ||
| <section> | ||
| <h2></h2> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best Practice: Heading is empty. Add text content or remove the heading element. Headings must have discernible text. DetailsFollowing content: "This section has an empty heading above." Screen reader users navigate pages by headings, so empty headings create confusing navigation points. Ensure all headings contain visible text or accessible names. If a heading is used purely for visual styling, use CSS instead of heading elements. |
||
| <p>This section has an empty heading above.</p> | ||
| <h3> </h3> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Best Practice: Heading is empty. Add text content or remove the heading element. |
||
| <p>This heading has only whitespace.</p> | ||
| </section> | ||
| ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| // accesslint-020: Form Label — file input without label | ||
| // accesslint-075: Button Name — upload button with only icon | ||
| export default function FileUpload() { | ||
| return ( | ||
| <div> | ||
| <input type="file" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. Form elements must have labels. Use , aria-label, or aria-labelledby. Detailstype: file Every form input needs an accessible label so users understand what information to enter. Use a element with a for attribute matching the input's id, wrap the input in a , or use aria-label/aria-labelledby for custom components. Placeholders are not sufficient as labels since they disappear when typing. |
||
| <button><img src="/upload.svg" /></button> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 1.1.1: Image element missing alt attribute. Images must have alternate text. Add an alt attribute to DetailsEvery image needs an alt attribute. For informative images, describe the content or function concisely. For decorative images (backgrounds, spacers, purely visual flourishes), use alt='' to hide them from screen readers. Never omit alt entirely—screen readers may read the filename instead. WCAG 4.1.2: Button has no discernible text. Buttons must have discernible text. DetailsScreen reader users need to know what a button does. Add visible text content, aria-label, or aria-labelledby. For icon buttons, use aria-label describing the action (e.g., aria-label='Close'). If the button contains an image, ensure the image has alt text describing the button's action. |
||
| <input type="file" accept="image/*" /> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WCAG 4.1.2: Form element has no accessible label. |
||
| </div> | ||
| ); | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best Practice: Heading is empty. Add text content or remove the heading element.
Headings must have discernible text.
Details
Following content: "Accordion panel 1 content."
Screen reader users navigate pages by headings, so empty headings create confusing navigation points. Ensure all headings contain visible text or accessible names. If a heading is used purely for visual styling, use CSS instead of heading elements.
WCAG 4.1.2: Button has no discernible text.
Buttons must have discernible text.
Details
Screen reader users need to know what a button does. Add visible text content, aria-label, or aria-labelledby. For icon buttons, use aria-label describing the action (e.g., aria-label='Close'). If the button contains an image, ensure the image has alt text describing the button's action.