+ );
+}
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 (
+
+
+
+
+
Name
+
+
Email
+
+
+
+
+
1
+
Alice
+
Admin
+
alice@example.com
+
+
+
2
+
Bob
+
User
+
bob@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 (
+
+
+
+
+
+ );
+}
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 (
+
+
+ );
+}
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 (
+
+ );
+}
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
+
+
+
+
+
+
+
+
+
+
Metric
+
Value
+
+
+
+
+
+
1
+
Revenue
+
$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 (
+
+