From 85a479d02e01a7395547f70209dfcc310d1cc0ac Mon Sep 17 00:00:00 2001 From: Cameron Cundiff Date: Wed, 18 Feb 2026 20:06:40 -0500 Subject: [PATCH 1/2] Add sample components with accessibility violations 50+ JSX files demonstrating a wide range of WCAG accessibility failures across images, forms, ARIA, tables, headings, links, buttons, media, lists, and more. --- src/components/Accesskeys.jsx | 11 +++++++++ src/components/Accordion.jsx | 14 +++++++++++ src/components/AriaAllowed.jsx | 10 ++++++++ src/components/AriaAttrs.jsx | 13 ++++++++++ src/components/AriaChildren.jsx | 19 ++++++++++++++ src/components/AriaCommandNames.jsx | 14 +++++++++++ src/components/AriaDialogs.jsx | 16 ++++++++++++ src/components/AriaHiddenFocus.jsx | 12 +++++++++ src/components/AriaMeters.jsx | 11 +++++++++ src/components/AriaParent.jsx | 11 +++++++++ src/components/AriaProhibited.jsx | 10 ++++++++ src/components/AriaRequired.jsx | 12 +++++++++ src/components/AriaRoles.jsx | 12 +++++++++ src/components/AriaToggleFields.jsx | 12 +++++++++ src/components/AudioPlayer.jsx | 12 +++++++++ src/components/Breadcrumbs.jsx | 13 ++++++++++ src/components/CardGrid.jsx | 23 +++++++++++++++++ src/components/Carousel.jsx | 15 +++++++++++ src/components/ContactForm.jsx | 20 +++++++++++++++ src/components/DataTable.jsx | 30 ++++++++++++++++++++++ src/components/DefinitionListErrors.jsx | 19 ++++++++++++++ src/components/DeprecatedElements.jsx | 11 +++++++++ src/components/DuplicateAriaIds.jsx | 14 +++++++++++ src/components/EmptyButtons.jsx | 11 +++++++++ src/components/EmptyHeadings.jsx | 11 +++++++++ src/components/FileUpload.jsx | 11 +++++++++ src/components/FocusOrder.jsx | 12 +++++++++ src/components/Footer.jsx | 14 +++++++++++ src/components/Header.jsx | 16 ++++++++++++ src/components/HeadingOrder.jsx | 12 +++++++++ src/components/HeroSection.jsx | 14 +++++++++++ src/components/IframeEmbed.jsx | 10 ++++++++ src/components/ImageGallery.jsx | 17 +++++++++++++ src/components/ImageMap.jsx | 15 +++++++++++ src/components/InputButtons.jsx | 11 +++++++++ src/components/LabelMismatch.jsx | 10 ++++++++ src/components/ListErrors.jsx | 15 +++++++++++ src/components/LoginForm.jsx | 11 +++++++++ src/components/Modal.jsx | 15 +++++++++++ src/components/MultipleLabels.jsx | 14 +++++++++++ src/components/NestedInteractive.jsx | 15 +++++++++++ src/components/Notification.jsx | 11 +++++++++ src/components/ObjectEmbed.jsx | 9 +++++++ src/components/Pagination.jsx | 12 +++++++++ src/components/PresentationConflict.jsx | 17 +++++++++++++ src/components/PricingTable.jsx | 30 ++++++++++++++++++++++ src/components/ProfileCard.jsx | 15 +++++++++++ src/components/SearchBar.jsx | 12 +++++++++ src/components/SelectField.jsx | 19 ++++++++++++++ src/components/SettingsForm.jsx | 22 +++++++++++++++++ src/components/Sidebar.jsx | 14 +++++++++++ src/components/SignupForm.jsx | 13 ++++++++++ src/components/SummaryDetails.jsx | 15 +++++++++++ src/components/SvgIcons.jsx | 15 +++++++++++ src/components/Tabs.jsx | 16 ++++++++++++ src/components/Toolbar.jsx | 14 +++++++++++ src/components/Tooltip.jsx | 11 +++++++++ src/components/TreeView.jsx | 11 +++++++++ src/components/VideoPlayer.jsx | 12 +++++++++ src/layouts/AdminLayout.jsx | 23 +++++++++++++++++ src/layouts/MainLayout.jsx | 14 +++++++++++ src/pages/AboutPage.jsx | 25 +++++++++++++++++++ src/pages/BlogPost.jsx | 18 ++++++++++++++ src/pages/CheckoutPage.jsx | 20 +++++++++++++++ src/pages/DashboardPage.jsx | 33 +++++++++++++++++++++++++ src/pages/HomePage.jsx | 15 +++++++++++ src/pages/ProductPage.jsx | 20 +++++++++++++++ 67 files changed, 1004 insertions(+) create mode 100644 src/components/Accesskeys.jsx create mode 100644 src/components/Accordion.jsx create mode 100644 src/components/AriaAllowed.jsx create mode 100644 src/components/AriaAttrs.jsx create mode 100644 src/components/AriaChildren.jsx create mode 100644 src/components/AriaCommandNames.jsx create mode 100644 src/components/AriaDialogs.jsx create mode 100644 src/components/AriaHiddenFocus.jsx create mode 100644 src/components/AriaMeters.jsx create mode 100644 src/components/AriaParent.jsx create mode 100644 src/components/AriaProhibited.jsx create mode 100644 src/components/AriaRequired.jsx create mode 100644 src/components/AriaRoles.jsx create mode 100644 src/components/AriaToggleFields.jsx create mode 100644 src/components/AudioPlayer.jsx create mode 100644 src/components/Breadcrumbs.jsx create mode 100644 src/components/CardGrid.jsx create mode 100644 src/components/Carousel.jsx create mode 100644 src/components/ContactForm.jsx create mode 100644 src/components/DataTable.jsx create mode 100644 src/components/DefinitionListErrors.jsx create mode 100644 src/components/DeprecatedElements.jsx create mode 100644 src/components/DuplicateAriaIds.jsx create mode 100644 src/components/EmptyButtons.jsx create mode 100644 src/components/EmptyHeadings.jsx create mode 100644 src/components/FileUpload.jsx create mode 100644 src/components/FocusOrder.jsx create mode 100644 src/components/Footer.jsx create mode 100644 src/components/Header.jsx create mode 100644 src/components/HeadingOrder.jsx create mode 100644 src/components/HeroSection.jsx create mode 100644 src/components/IframeEmbed.jsx create mode 100644 src/components/ImageGallery.jsx create mode 100644 src/components/ImageMap.jsx create mode 100644 src/components/InputButtons.jsx create mode 100644 src/components/LabelMismatch.jsx create mode 100644 src/components/ListErrors.jsx create mode 100644 src/components/LoginForm.jsx create mode 100644 src/components/Modal.jsx create mode 100644 src/components/MultipleLabels.jsx create mode 100644 src/components/NestedInteractive.jsx create mode 100644 src/components/Notification.jsx create mode 100644 src/components/ObjectEmbed.jsx create mode 100644 src/components/Pagination.jsx create mode 100644 src/components/PresentationConflict.jsx create mode 100644 src/components/PricingTable.jsx create mode 100644 src/components/ProfileCard.jsx create mode 100644 src/components/SearchBar.jsx create mode 100644 src/components/SelectField.jsx create mode 100644 src/components/SettingsForm.jsx create mode 100644 src/components/Sidebar.jsx create mode 100644 src/components/SignupForm.jsx create mode 100644 src/components/SummaryDetails.jsx create mode 100644 src/components/SvgIcons.jsx create mode 100644 src/components/Tabs.jsx create mode 100644 src/components/Toolbar.jsx create mode 100644 src/components/Tooltip.jsx create mode 100644 src/components/TreeView.jsx create mode 100644 src/components/VideoPlayer.jsx create mode 100644 src/layouts/AdminLayout.jsx create mode 100644 src/layouts/MainLayout.jsx create mode 100644 src/pages/AboutPage.jsx create mode 100644 src/pages/BlogPost.jsx create mode 100644 src/pages/CheckoutPage.jsx create mode 100644 src/pages/DashboardPage.jsx create mode 100644 src/pages/HomePage.jsx create mode 100644 src/pages/ProductPage.jsx diff --git a/src/components/Accesskeys.jsx b/src/components/Accesskeys.jsx new file mode 100644 index 0000000..242e8f1 --- /dev/null +++ b/src/components/Accesskeys.jsx @@ -0,0 +1,11 @@ +// accesslint-031: Accesskeys — duplicate accesskey values +export default function Accesskeys() { + return ( + + ); +} diff --git a/src/components/Accordion.jsx b/src/components/Accordion.jsx new file mode 100644 index 0000000..b369071 --- /dev/null +++ b/src/components/Accordion.jsx @@ -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 ( +
+

+
Accordion panel 1 content.
+

+
Accordion panel 2 content.
+

+
Accordion panel 3 content.
+
+ ); +} diff --git a/src/components/AriaAllowed.jsx b/src/components/AriaAllowed.jsx new file mode 100644 index 0000000..61fdcbb --- /dev/null +++ b/src/components/AriaAllowed.jsx @@ -0,0 +1,10 @@ +// accesslint-058: ARIA Allowed Attr — ARIA attributes not allowed for role +export default function AriaAllowed() { + return ( +
+

Heading with aria-checked

+

Paragraph with aria-selected

+ Photo +
+ ); +} diff --git a/src/components/AriaAttrs.jsx b/src/components/AriaAttrs.jsx new file mode 100644 index 0000000..0e01f0c --- /dev/null +++ b/src/components/AriaAttrs.jsx @@ -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 ( +
+ + +
Option
+
Updates here
+ +
+ ); +} diff --git a/src/components/AriaChildren.jsx b/src/components/AriaChildren.jsx new file mode 100644 index 0000000..cce8c6d --- /dev/null +++ b/src/components/AriaChildren.jsx @@ -0,0 +1,19 @@ +// accesslint-060: ARIA Required Children — missing required child roles +export default function AriaChildren() { + return ( +
+ +
+ Item 1 + Item 2 +
+
+
Cell 1
+
Cell 2
+
+
+ ); +} diff --git a/src/components/AriaCommandNames.jsx b/src/components/AriaCommandNames.jsx new file mode 100644 index 0000000..9fecde7 --- /dev/null +++ b/src/components/AriaCommandNames.jsx @@ -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 ( +
+
+
+
+
+
+
+
+ ); +} diff --git a/src/components/AriaDialogs.jsx b/src/components/AriaDialogs.jsx new file mode 100644 index 0000000..ddedd7f --- /dev/null +++ b/src/components/AriaDialogs.jsx @@ -0,0 +1,16 @@ +// accesslint-069: ARIA Dialog Name — dialogs without accessible names +export default function AriaDialogs() { + return ( +
+
+

Are you sure you want to delete this?

+ + +
+
+

Session expired.

+ +
+
+ ); +} diff --git a/src/components/AriaHiddenFocus.jsx b/src/components/AriaHiddenFocus.jsx new file mode 100644 index 0000000..9bf6893 --- /dev/null +++ b/src/components/AriaHiddenFocus.jsx @@ -0,0 +1,12 @@ +// accesslint-063: ARIA Hidden Focus — focusable elements inside aria-hidden +export default function AriaHiddenFocus() { + return ( +
+ +
+ ); +} diff --git a/src/components/AriaMeters.jsx b/src/components/AriaMeters.jsx new file mode 100644 index 0000000..856e56d --- /dev/null +++ b/src/components/AriaMeters.jsx @@ -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 ( +
+
+
+
+
+ ); +} diff --git a/src/components/AriaParent.jsx b/src/components/AriaParent.jsx new file mode 100644 index 0000000..40eb9e3 --- /dev/null +++ b/src/components/AriaParent.jsx @@ -0,0 +1,11 @@ +// accesslint-061: ARIA Required Parent — roles missing required parents +export default function AriaParent() { + return ( +
+
Tab without tablist
+
Item without list
+
Option without listbox
+
Row without table/grid
+
+ ); +} diff --git a/src/components/AriaProhibited.jsx b/src/components/AriaProhibited.jsx new file mode 100644 index 0000000..60431ba --- /dev/null +++ b/src/components/AriaProhibited.jsx @@ -0,0 +1,10 @@ +// accesslint-072: ARIA Prohibited Attr — prohibited attributes for roles +export default function AriaProhibited() { + return ( +
+
Content
+
More content
+ +
+ ); +} diff --git a/src/components/AriaRequired.jsx b/src/components/AriaRequired.jsx new file mode 100644 index 0000000..36a6486 --- /dev/null +++ b/src/components/AriaRequired.jsx @@ -0,0 +1,12 @@ +// accesslint-057: ARIA Required Attr — missing required attributes +export default function AriaRequired() { + return ( +
+
Accept terms
+
Volume
+
Select option
+
Scroll
+
---
+
+ ); +} diff --git a/src/components/AriaRoles.jsx b/src/components/AriaRoles.jsx new file mode 100644 index 0000000..b36ea3f --- /dev/null +++ b/src/components/AriaRoles.jsx @@ -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 ( +
+
Click me
+
Option A
+ Title +

I agree to terms

+
+ ); +} diff --git a/src/components/AriaToggleFields.jsx b/src/components/AriaToggleFields.jsx new file mode 100644 index 0000000..18bf7a9 --- /dev/null +++ b/src/components/AriaToggleFields.jsx @@ -0,0 +1,12 @@ +// accesslint-066: ARIA Toggle Field Name — toggle fields without names +export default function AriaToggleFields() { + return ( +
+
+
+
+
+
+
+ ); +} diff --git a/src/components/AudioPlayer.jsx b/src/components/AudioPlayer.jsx new file mode 100644 index 0000000..fd9bad4 --- /dev/null +++ b/src/components/AudioPlayer.jsx @@ -0,0 +1,12 @@ +// accesslint-091: Audio Captions — audio without text alternatives +export default function AudioPlayer() { + return ( +
+ + +
+ ); +} diff --git a/src/components/Breadcrumbs.jsx b/src/components/Breadcrumbs.jsx new file mode 100644 index 0000000..c9a176a --- /dev/null +++ b/src/components/Breadcrumbs.jsx @@ -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 ( + + ); +} diff --git a/src/components/CardGrid.jsx b/src/components/CardGrid.jsx new file mode 100644 index 0000000..4fabedc --- /dev/null +++ b/src/components/CardGrid.jsx @@ -0,0 +1,23 @@ +// accesslint-011: Image Alt — card images missing alt +// accesslint-077: Link Name — empty links +export default function CardGrid() { + return ( +
+
+ +

Product One

+

Description of product one.

+
+
+ +

Product Two

+

Description of product two.

+
+
+ +

Product Three

+

Description of product three.

+
+
+ ); +} diff --git a/src/components/Carousel.jsx b/src/components/Carousel.jsx new file mode 100644 index 0000000..aec60ea --- /dev/null +++ b/src/components/Carousel.jsx @@ -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 ( +
+ +
+ + + +
+ +
+ ); +} diff --git a/src/components/ContactForm.jsx b/src/components/ContactForm.jsx new file mode 100644 index 0000000..10f3f6f --- /dev/null +++ b/src/components/ContactForm.jsx @@ -0,0 +1,20 @@ +// accesslint-020: Form Label — inputs missing labels +export default function ContactForm() { + return ( +
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+ ); +} diff --git a/src/components/DataTable.jsx b/src/components/DataTable.jsx new file mode 100644 index 0000000..4a3a983 --- /dev/null +++ b/src/components/DataTable.jsx @@ -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 ( + + + + + + + + + + + + + + + + + + + + + + + +
NameEmail
1AliceAdminalice@example.com
2BobUserbob@example.com
+ ); +} diff --git a/src/components/DefinitionListErrors.jsx b/src/components/DefinitionListErrors.jsx new file mode 100644 index 0000000..58e2f01 --- /dev/null +++ b/src/components/DefinitionListErrors.jsx @@ -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 ( +
+
+
Term 1
+
Definition 1
+

Invalid child of dl

+
+
Term 2
+
Definition 2
+
+
+
Orphaned term
+
Orphaned definition
+
+ ); +} diff --git a/src/components/DeprecatedElements.jsx b/src/components/DeprecatedElements.jsx new file mode 100644 index 0000000..0f22d4f --- /dev/null +++ b/src/components/DeprecatedElements.jsx @@ -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 ( +
+ This text blinks! + Scrolling announcement text + More scrolling text +
+ ); +} diff --git a/src/components/DuplicateAriaIds.jsx b/src/components/DuplicateAriaIds.jsx new file mode 100644 index 0000000..22dded6 --- /dev/null +++ b/src/components/DuplicateAriaIds.jsx @@ -0,0 +1,14 @@ +// accesslint-089: Duplicate ID ARIA — duplicate IDs used in ARIA references +export default function DuplicateAriaIds() { + return ( +
+
First description
+
Duplicate description
+ + +
Label text
+
Duplicate label text
+ +
+ ); +} diff --git a/src/components/EmptyButtons.jsx b/src/components/EmptyButtons.jsx new file mode 100644 index 0000000..aced56a --- /dev/null +++ b/src/components/EmptyButtons.jsx @@ -0,0 +1,11 @@ +// accesslint-075: Button Name — buttons with no discernible text +export default function EmptyButtons() { + return ( +
+ + + + +
+ ); +} diff --git a/src/components/EmptyHeadings.jsx b/src/components/EmptyHeadings.jsx new file mode 100644 index 0000000..0fbd648 --- /dev/null +++ b/src/components/EmptyHeadings.jsx @@ -0,0 +1,11 @@ +// accesslint-034: Empty Heading — headings with no text +export default function EmptyHeadings() { + return ( +
+

+

This section has an empty heading above.

+

+

This heading has only whitespace.

+
+ ); +} diff --git a/src/components/FileUpload.jsx b/src/components/FileUpload.jsx new file mode 100644 index 0000000..2210fb2 --- /dev/null +++ b/src/components/FileUpload.jsx @@ -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 ( +
+ + + +
+ ); +} diff --git a/src/components/FocusOrder.jsx b/src/components/FocusOrder.jsx new file mode 100644 index 0000000..79bd0c4 --- /dev/null +++ b/src/components/FocusOrder.jsx @@ -0,0 +1,12 @@ +// accesslint-028: Focus Order Semantics — focusable non-interactive elements +// accesslint-027: Tabindex — positive tabindex values +export default function FocusOrder() { + return ( +
+
Focusable div with high tabindex
+ Focusable span with tabindex 3 +

Focusable paragraph with tabindex 1

+
Focusable div without role
+
+ ); +} diff --git a/src/components/Footer.jsx b/src/components/Footer.jsx new file mode 100644 index 0000000..f2eb77a --- /dev/null +++ b/src/components/Footer.jsx @@ -0,0 +1,14 @@ +// accesslint-011: Image Alt — missing alt on social icons +// accesslint-077: Link Name — icon links with no text +export default function Footer() { + return ( + + ); +} diff --git a/src/components/Header.jsx b/src/components/Header.jsx new file mode 100644 index 0000000..367ad9f --- /dev/null +++ b/src/components/Header.jsx @@ -0,0 +1,16 @@ +// accesslint-011: Image Alt — missing alt on logo +// accesslint-077: Link Name — link wraps image with no alt +export default function Header() { + return ( +
+ + + + +
+ ); +} diff --git a/src/components/HeadingOrder.jsx b/src/components/HeadingOrder.jsx new file mode 100644 index 0000000..c9523ec --- /dev/null +++ b/src/components/HeadingOrder.jsx @@ -0,0 +1,12 @@ +// accesslint-033: Heading Order — skipped heading levels +export default function HeadingOrder() { + return ( +
+

Main Title

+

Skipped h2, jumped to h3

+

Some content here.

+
Skipped h4, jumped to h5
+

More content here.

+
+ ); +} diff --git a/src/components/HeroSection.jsx b/src/components/HeroSection.jsx new file mode 100644 index 0000000..7dce5c7 --- /dev/null +++ b/src/components/HeroSection.jsx @@ -0,0 +1,14 @@ +// accesslint-011: Image Alt — hero image missing alt +// accesslint-014: Image Redundant Alt — alt duplicates adjacent text +export default function HeroSection() { + return ( +
+

Welcome to Demo Corp

+ + + Our products + Our products + +
+ ); +} diff --git a/src/components/IframeEmbed.jsx b/src/components/IframeEmbed.jsx new file mode 100644 index 0000000..f293a70 --- /dev/null +++ b/src/components/IframeEmbed.jsx @@ -0,0 +1,10 @@ +// accesslint-004: Frame Title — iframes missing titles +export default function IframeEmbed() { + return ( +
+ + + +
+ ); +} diff --git a/src/components/ImageGallery.jsx b/src/components/ImageGallery.jsx new file mode 100644 index 0000000..a25f887 --- /dev/null +++ b/src/components/ImageGallery.jsx @@ -0,0 +1,17 @@ +// accesslint-011: Image Alt — multiple images missing alt +// accesslint-015: Image Alt Redundant Words — alt text with "image of" +export default function ImageGallery() { + return ( +
+

Gallery

+
+ + + + image of a sunset + picture of mountains + photo of the team +
+
+ ); +} diff --git a/src/components/ImageMap.jsx b/src/components/ImageMap.jsx new file mode 100644 index 0000000..affef49 --- /dev/null +++ b/src/components/ImageMap.jsx @@ -0,0 +1,15 @@ +// accesslint-016: Area Alt — area elements missing alt +// accesslint-019: Server-Side Image Map — server-side image map +export default function ImageMap() { + return ( +
+ Office floor plan + + + + + + Campus map +
+ ); +} diff --git a/src/components/InputButtons.jsx b/src/components/InputButtons.jsx new file mode 100644 index 0000000..4283770 --- /dev/null +++ b/src/components/InputButtons.jsx @@ -0,0 +1,11 @@ +// accesslint-013: Input Image Alt — image inputs missing alt +// accesslint-023: Input Button Name — input buttons missing text +export default function InputButtons() { + return ( +
+ + + +
+ ); +} diff --git a/src/components/LabelMismatch.jsx b/src/components/LabelMismatch.jsx new file mode 100644 index 0000000..66d146d --- /dev/null +++ b/src/components/LabelMismatch.jsx @@ -0,0 +1,10 @@ +// accesslint-025: Label Content Name Mismatch — visible text doesn't match accessible name +export default function LabelMismatch() { + return ( +
+ + Home + +
+ ); +} diff --git a/src/components/ListErrors.jsx b/src/components/ListErrors.jsx new file mode 100644 index 0000000..4eccea2 --- /dev/null +++ b/src/components/ListErrors.jsx @@ -0,0 +1,15 @@ +// accesslint-046: List — ul/ol with non-li children +// accesslint-047: List Item — li outside of ul/ol +export default function ListErrors() { + return ( +
+ +
  • Orphaned list item
  • +
  • Another orphaned item
  • +
    + ); +} diff --git a/src/components/LoginForm.jsx b/src/components/LoginForm.jsx new file mode 100644 index 0000000..6de5a62 --- /dev/null +++ b/src/components/LoginForm.jsx @@ -0,0 +1,11 @@ +// accesslint-020: Form Label — inputs missing labels +// accesslint-027: Tabindex — positive tabindex values +export default function LoginForm() { + return ( +
    + + + +
    + ); +} diff --git a/src/components/Modal.jsx b/src/components/Modal.jsx new file mode 100644 index 0000000..e5cf3da --- /dev/null +++ b/src/components/Modal.jsx @@ -0,0 +1,15 @@ +// accesslint-069: ARIA Dialog Name — modal without accessible name +// accesslint-075: Button Name — close button with no text +export default function Modal() { + return ( +
    + +

    Confirm Action

    +

    Are you sure you want to proceed?

    +
    + + +
    +
    + ); +} diff --git a/src/components/MultipleLabels.jsx b/src/components/MultipleLabels.jsx new file mode 100644 index 0000000..a2c4a4f --- /dev/null +++ b/src/components/MultipleLabels.jsx @@ -0,0 +1,14 @@ +// accesslint-021: Form Field Multiple Labels — inputs with multiple labels +export default function MultipleLabels() { + return ( +
    + + + + + + + +
    + ); +} diff --git a/src/components/NestedInteractive.jsx b/src/components/NestedInteractive.jsx new file mode 100644 index 0000000..10f4f31 --- /dev/null +++ b/src/components/NestedInteractive.jsx @@ -0,0 +1,15 @@ +// accesslint-029: Nested Interactive — interactive elements inside each other +export default function NestedInteractive() { + return ( +
    + + View profile + + + +
    + ); +} diff --git a/src/components/Notification.jsx b/src/components/Notification.jsx new file mode 100644 index 0000000..1aec7db --- /dev/null +++ b/src/components/Notification.jsx @@ -0,0 +1,11 @@ +// accesslint-075: Button Name — dismiss button without text +// accesslint-011: Image Alt — notification icon without alt +export default function Notification() { + return ( +
    + +

    Your session will expire in 5 minutes.

    + +
    + ); +} diff --git a/src/components/ObjectEmbed.jsx b/src/components/ObjectEmbed.jsx new file mode 100644 index 0000000..bf35295 --- /dev/null +++ b/src/components/ObjectEmbed.jsx @@ -0,0 +1,9 @@ +// accesslint-017: Object Alt — object elements missing alt text +export default function ObjectEmbed() { + return ( +
    + + +
    + ); +} diff --git a/src/components/Pagination.jsx b/src/components/Pagination.jsx new file mode 100644 index 0000000..1f3f71e --- /dev/null +++ b/src/components/Pagination.jsx @@ -0,0 +1,12 @@ +// accesslint-077: Link Name — pagination links with only icons, no text +export default function Pagination() { + return ( + + ); +} diff --git a/src/components/PresentationConflict.jsx b/src/components/PresentationConflict.jsx new file mode 100644 index 0000000..e62e130 --- /dev/null +++ b/src/components/PresentationConflict.jsx @@ -0,0 +1,17 @@ +// accesslint-073: Presentation Role Conflict — presentation role with focusable/aria attrs +// accesslint-074: Presentational Children Focusable — children of presentational parent focusable +export default function PresentationConflict() { + return ( +
    + + Hidden link + + + + + + +
    +
    + ); +} diff --git a/src/components/PricingTable.jsx b/src/components/PricingTable.jsx new file mode 100644 index 0000000..e490738 --- /dev/null +++ b/src/components/PricingTable.jsx @@ -0,0 +1,30 @@ +// accesslint-088: Empty Table Header — empty headers +// accesslint-087: Scope Attr Valid — invalid scope values +export default function PricingTable() { + return ( + + + + + + + + + + + + + + + + + + + + + + + +
    FreeProEnterprise
    Storage1 GB100 GBUnlimited
    Users110Unlimited
    + ); +} diff --git a/src/components/ProfileCard.jsx b/src/components/ProfileCard.jsx new file mode 100644 index 0000000..fa94045 --- /dev/null +++ b/src/components/ProfileCard.jsx @@ -0,0 +1,15 @@ +// accesslint-011: Image Alt — avatar without alt +// accesslint-077: Link Name — social icon links without text +export default function ProfileCard() { + return ( +
    + +

    Jane Smith

    +

    Software Engineer

    +
    + + +
    +
    + ); +} diff --git a/src/components/SearchBar.jsx b/src/components/SearchBar.jsx new file mode 100644 index 0000000..c00e94d --- /dev/null +++ b/src/components/SearchBar.jsx @@ -0,0 +1,12 @@ +// accesslint-020: Form Label — search input missing label +// accesslint-075: Button Name — icon button with no text +export default function SearchBar() { + return ( +
    + + +
    + ); +} diff --git a/src/components/SelectField.jsx b/src/components/SelectField.jsx new file mode 100644 index 0000000..eb27ff3 --- /dev/null +++ b/src/components/SelectField.jsx @@ -0,0 +1,19 @@ +// accesslint-022: Select Name — selects without labels +export default function SelectField() { + return ( +
    + + +
    + ); +} diff --git a/src/components/SettingsForm.jsx b/src/components/SettingsForm.jsx new file mode 100644 index 0000000..b5378c0 --- /dev/null +++ b/src/components/SettingsForm.jsx @@ -0,0 +1,22 @@ +// accesslint-020: Form Label — toggle inputs without labels +// accesslint-026: Label Title Only — using only title attribute +export default function SettingsForm() { + return ( +
    +
    + + Dark mode +
    +
    + + Notifications +
    +
    + +
    +
    + +
    +
    + ); +} diff --git a/src/components/Sidebar.jsx b/src/components/Sidebar.jsx new file mode 100644 index 0000000..c3d2057 --- /dev/null +++ b/src/components/Sidebar.jsx @@ -0,0 +1,14 @@ +// accesslint-077: Link Name — links with no discernible text +// accesslint-011: Image Alt — missing alt on images inside links +export default function Sidebar() { + return ( + + ); +} diff --git a/src/components/SignupForm.jsx b/src/components/SignupForm.jsx new file mode 100644 index 0000000..99fd86a --- /dev/null +++ b/src/components/SignupForm.jsx @@ -0,0 +1,13 @@ +// accesslint-020: Form Label — inputs missing labels +// accesslint-024: Autocomplete Valid — invalid autocomplete value +export default function SignupForm() { + return ( +
    + + + + + +
    + ); +} diff --git a/src/components/SummaryDetails.jsx b/src/components/SummaryDetails.jsx new file mode 100644 index 0000000..951d750 --- /dev/null +++ b/src/components/SummaryDetails.jsx @@ -0,0 +1,15 @@ +// accesslint-076: Summary Name — summary elements without accessible names +export default function SummaryDetails() { + return ( +
    +
    + +

    Expandable content section one.

    +
    +
    + +

    Expandable content section two.

    +
    +
    + ); +} diff --git a/src/components/SvgIcons.jsx b/src/components/SvgIcons.jsx new file mode 100644 index 0000000..67e9c0b --- /dev/null +++ b/src/components/SvgIcons.jsx @@ -0,0 +1,15 @@ +// accesslint-012: SVG Image Alt — SVGs with img role missing accessible names +// accesslint-018: Role Image Alt — role="img" elements without names +export default function SvgIcons() { + return ( +
    + + + + + + +
    +
    + ); +} diff --git a/src/components/Tabs.jsx b/src/components/Tabs.jsx new file mode 100644 index 0000000..f3c7ae5 --- /dev/null +++ b/src/components/Tabs.jsx @@ -0,0 +1,16 @@ +// accesslint-060: ARIA Required Children — tablist without tab children +// accesslint-057: ARIA Required Attr — tab without required attrs +export default function Tabs() { + return ( +
    +
    + + + +
    +
    +

    Overview content here.

    +
    +
    + ); +} diff --git a/src/components/Toolbar.jsx b/src/components/Toolbar.jsx new file mode 100644 index 0000000..bcd64fe --- /dev/null +++ b/src/components/Toolbar.jsx @@ -0,0 +1,14 @@ +// accesslint-075: Button Name — icon-only toolbar buttons without names +// accesslint-011: Image Alt — toolbar icons without alt +export default function Toolbar() { + return ( +
    + + + + + + +
    + ); +} diff --git a/src/components/Tooltip.jsx b/src/components/Tooltip.jsx new file mode 100644 index 0000000..f502f37 --- /dev/null +++ b/src/components/Tooltip.jsx @@ -0,0 +1,11 @@ +// accesslint-070: ARIA Tooltip Name — tooltips without accessible names +export default function Tooltip() { + return ( +
    + +
    + +
    +
    + ); +} diff --git a/src/components/TreeView.jsx b/src/components/TreeView.jsx new file mode 100644 index 0000000..7d17823 --- /dev/null +++ b/src/components/TreeView.jsx @@ -0,0 +1,11 @@ +// accesslint-071: ARIA Treeitem Name — treeitems without accessible names +// accesslint-061: ARIA Required Parent — treeitem outside tree +export default function TreeView() { + return ( +
    +
    +
    +
    +
    + ); +} diff --git a/src/components/VideoPlayer.jsx b/src/components/VideoPlayer.jsx new file mode 100644 index 0000000..f85230e --- /dev/null +++ b/src/components/VideoPlayer.jsx @@ -0,0 +1,12 @@ +// accesslint-090: Video Captions — videos without captions +export default function VideoPlayer() { + return ( +
    + + +
    + ); +} diff --git a/src/layouts/AdminLayout.jsx b/src/layouts/AdminLayout.jsx new file mode 100644 index 0000000..e1dac0e --- /dev/null +++ b/src/layouts/AdminLayout.jsx @@ -0,0 +1,23 @@ +// accesslint-006: Meta Viewport — disables user scaling +// accesslint-077: Link Name — nav icon links without text +// accesslint-011: Image Alt — logo without alt +export default function AdminLayout({ children }) { + return ( + + + + + +
    + + +
    +
    {children}
    + + + ); +} diff --git a/src/layouts/MainLayout.jsx b/src/layouts/MainLayout.jsx new file mode 100644 index 0000000..39de329 --- /dev/null +++ b/src/layouts/MainLayout.jsx @@ -0,0 +1,14 @@ +// accesslint-062: ARIA Hidden Body — aria-hidden on body +// accesslint-006: Meta Viewport — disables user scaling +export default function MainLayout({ children }) { + return ( + + + + + + {children} + + + ); +} diff --git a/src/pages/AboutPage.jsx b/src/pages/AboutPage.jsx new file mode 100644 index 0000000..7b64f10 --- /dev/null +++ b/src/pages/AboutPage.jsx @@ -0,0 +1,25 @@ +// accesslint-011: Image Alt — team photos missing alt +// accesslint-034: Empty Heading — empty section heading +export default function AboutPage() { + return ( +
    +

    About Us

    +
    +

    +

    We are a passionate team building accessible web tools.

    +
    + +

    Alice - CEO

    +
    +
    + +

    Bob - CTO

    +
    +
    + +

    Carol - Designer

    +
    +
    +
    + ); +} diff --git a/src/pages/BlogPost.jsx b/src/pages/BlogPost.jsx new file mode 100644 index 0000000..a0cd916 --- /dev/null +++ b/src/pages/BlogPost.jsx @@ -0,0 +1,18 @@ +// accesslint-011: Image Alt — blog images missing alt +// accesslint-004: Frame Title — embedded iframe without title +// accesslint-077: Link Name — "read more" link wrapping icon only +export default function BlogPost() { + return ( +
    +

    How to Build Accessible Forms

    + +

    Forms are one of the most common accessibility barriers on the web...

    + +

    Here is a video walkthrough:

    + +

    + +

    +
    + ); +} diff --git a/src/pages/CheckoutPage.jsx b/src/pages/CheckoutPage.jsx new file mode 100644 index 0000000..b0edd71 --- /dev/null +++ b/src/pages/CheckoutPage.jsx @@ -0,0 +1,20 @@ +// accesslint-020: Form Label — all checkout fields missing labels +// accesslint-024: Autocomplete Valid — invalid autocomplete values +export default function CheckoutPage() { + return ( +
    +

    Checkout

    +
    + + + + + + + + + +
    +
    + ); +} diff --git a/src/pages/DashboardPage.jsx b/src/pages/DashboardPage.jsx new file mode 100644 index 0000000..392ee89 --- /dev/null +++ b/src/pages/DashboardPage.jsx @@ -0,0 +1,33 @@ +// accesslint-011: Image Alt — chart images missing alt +// accesslint-088: Empty Table Header — dashboard table empty headers +// accesslint-075: Button Name — action buttons without text +export default function DashboardPage() { + return ( +
    +

    Dashboard

    +
    + + + +
    + + + + + + + + + + + + + + + + + +
    MetricValue
    1Revenue$42,000
    +
    + ); +} diff --git a/src/pages/HomePage.jsx b/src/pages/HomePage.jsx new file mode 100644 index 0000000..f9cf0a2 --- /dev/null +++ b/src/pages/HomePage.jsx @@ -0,0 +1,15 @@ +// accesslint-033: Heading Order — skipped heading levels +// accesslint-011: Image Alt — images missing alt +export default function HomePage() { + return ( +
    +

    Welcome

    + +

    Skipped h2 and h3

    +

    Some introductory content.

    + + +
    Skipped several levels
    +
    + ); +} diff --git a/src/pages/ProductPage.jsx b/src/pages/ProductPage.jsx new file mode 100644 index 0000000..94e7f87 --- /dev/null +++ b/src/pages/ProductPage.jsx @@ -0,0 +1,20 @@ +// accesslint-011: Image Alt — product images missing alt +// accesslint-020: Form Label — quantity input missing label +// accesslint-075: Button Name — add-to-cart icon button +export default function ProductPage() { + return ( +
    +

    Widget Pro

    +
    + + + +
    +

    The best widget money can buy.

    +
    + + +
    +
    + ); +} From 88cbd0c054257af6b484723fdfdddbcd1d8e62d6 Mon Sep 17 00:00:00 2001 From: Cameron Cundiff Date: Wed, 18 Feb 2026 21:32:23 -0500 Subject: [PATCH 2/2] Retrigger AccessLint