@wazir-dev/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +111 -0
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/assets/composition-engine.mmd +34 -0
- package/assets/demo-script.sh +17 -0
- package/assets/logo-dark.svg +14 -0
- package/assets/logo.svg +14 -0
- package/assets/pipeline.mmd +39 -0
- package/assets/record-demo.sh +51 -0
- package/docs/README.md +51 -0
- package/docs/adapters/context-mode.md +60 -0
- package/docs/concepts/architecture.md +87 -0
- package/docs/concepts/artifact-model.md +60 -0
- package/docs/concepts/composition-engine.md +36 -0
- package/docs/concepts/indexing-and-recall.md +160 -0
- package/docs/concepts/observability.md +41 -0
- package/docs/concepts/roles-and-workflows.md +59 -0
- package/docs/concepts/terminology-policy.md +27 -0
- package/docs/getting-started/01-installation.md +78 -0
- package/docs/getting-started/02-first-run.md +102 -0
- package/docs/getting-started/03-adding-to-project.md +15 -0
- package/docs/getting-started/04-host-setup.md +15 -0
- package/docs/guides/ci-integration.md +15 -0
- package/docs/guides/creating-skills.md +15 -0
- package/docs/guides/expertise-module-authoring.md +15 -0
- package/docs/guides/hook-development.md +15 -0
- package/docs/guides/memory-and-learnings.md +34 -0
- package/docs/guides/multi-host-export.md +15 -0
- package/docs/guides/troubleshooting.md +101 -0
- package/docs/guides/writing-custom-roles.md +15 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
- package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
- package/docs/readmes/INDEX.md +99 -0
- package/docs/readmes/features/expertise/README.md +171 -0
- package/docs/readmes/features/exports/README.md +222 -0
- package/docs/readmes/features/hooks/README.md +103 -0
- package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
- package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
- package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
- package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
- package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
- package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
- package/docs/readmes/features/hooks/session-start.md +119 -0
- package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
- package/docs/readmes/features/roles/README.md +157 -0
- package/docs/readmes/features/roles/clarifier.md +152 -0
- package/docs/readmes/features/roles/content-author.md +190 -0
- package/docs/readmes/features/roles/designer.md +193 -0
- package/docs/readmes/features/roles/executor.md +184 -0
- package/docs/readmes/features/roles/learner.md +210 -0
- package/docs/readmes/features/roles/planner.md +182 -0
- package/docs/readmes/features/roles/researcher.md +164 -0
- package/docs/readmes/features/roles/reviewer.md +184 -0
- package/docs/readmes/features/roles/specifier.md +162 -0
- package/docs/readmes/features/roles/verifier.md +215 -0
- package/docs/readmes/features/schemas/README.md +178 -0
- package/docs/readmes/features/skills/README.md +63 -0
- package/docs/readmes/features/skills/brainstorming.md +96 -0
- package/docs/readmes/features/skills/debugging.md +148 -0
- package/docs/readmes/features/skills/design.md +120 -0
- package/docs/readmes/features/skills/prepare-next.md +109 -0
- package/docs/readmes/features/skills/run-audit.md +159 -0
- package/docs/readmes/features/skills/scan-project.md +109 -0
- package/docs/readmes/features/skills/self-audit.md +176 -0
- package/docs/readmes/features/skills/tdd.md +137 -0
- package/docs/readmes/features/skills/using-skills.md +92 -0
- package/docs/readmes/features/skills/verification.md +120 -0
- package/docs/readmes/features/skills/writing-plans.md +104 -0
- package/docs/readmes/features/tooling/README.md +320 -0
- package/docs/readmes/features/workflows/README.md +186 -0
- package/docs/readmes/features/workflows/author.md +181 -0
- package/docs/readmes/features/workflows/clarify.md +154 -0
- package/docs/readmes/features/workflows/design-review.md +171 -0
- package/docs/readmes/features/workflows/design.md +169 -0
- package/docs/readmes/features/workflows/discover.md +162 -0
- package/docs/readmes/features/workflows/execute.md +173 -0
- package/docs/readmes/features/workflows/learn.md +167 -0
- package/docs/readmes/features/workflows/plan-review.md +165 -0
- package/docs/readmes/features/workflows/plan.md +170 -0
- package/docs/readmes/features/workflows/prepare-next.md +167 -0
- package/docs/readmes/features/workflows/review.md +169 -0
- package/docs/readmes/features/workflows/run-audit.md +191 -0
- package/docs/readmes/features/workflows/spec-challenge.md +159 -0
- package/docs/readmes/features/workflows/specify.md +160 -0
- package/docs/readmes/features/workflows/verify.md +177 -0
- package/docs/readmes/packages/README.md +50 -0
- package/docs/readmes/packages/ajv.md +117 -0
- package/docs/readmes/packages/context-mode.md +118 -0
- package/docs/readmes/packages/gray-matter.md +116 -0
- package/docs/readmes/packages/node-test.md +137 -0
- package/docs/readmes/packages/yaml.md +112 -0
- package/docs/reference/configuration-reference.md +159 -0
- package/docs/reference/expertise-index.md +52 -0
- package/docs/reference/git-flow.md +43 -0
- package/docs/reference/hooks.md +87 -0
- package/docs/reference/host-exports.md +50 -0
- package/docs/reference/launch-checklist.md +172 -0
- package/docs/reference/marketplace-listings.md +76 -0
- package/docs/reference/release-process.md +34 -0
- package/docs/reference/roles-reference.md +77 -0
- package/docs/reference/skills.md +33 -0
- package/docs/reference/templates.md +29 -0
- package/docs/reference/tooling-cli.md +94 -0
- package/docs/truth-claims.yaml +222 -0
- package/expertise/PROGRESS.md +63 -0
- package/expertise/README.md +18 -0
- package/expertise/antipatterns/PROGRESS.md +56 -0
- package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
- package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
- package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
- package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
- package/expertise/antipatterns/backend/index.md +24 -0
- package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
- package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
- package/expertise/antipatterns/code/async-antipatterns.md +622 -0
- package/expertise/antipatterns/code/code-smells.md +1186 -0
- package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
- package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
- package/expertise/antipatterns/code/index.md +27 -0
- package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
- package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
- package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
- package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
- package/expertise/antipatterns/design/dark-patterns.md +1121 -0
- package/expertise/antipatterns/design/index.md +22 -0
- package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
- package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
- package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
- package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
- package/expertise/antipatterns/frontend/index.md +23 -0
- package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
- package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
- package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
- package/expertise/antipatterns/index.md +31 -0
- package/expertise/antipatterns/performance/index.md +20 -0
- package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
- package/expertise/antipatterns/performance/premature-optimization.md +623 -0
- package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
- package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
- package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
- package/expertise/antipatterns/process/index.md +23 -0
- package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
- package/expertise/antipatterns/security/index.md +20 -0
- package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
- package/expertise/antipatterns/security/security-theater.md +843 -0
- package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
- package/expertise/architecture/PROGRESS.md +70 -0
- package/expertise/architecture/data/caching-architecture.md +671 -0
- package/expertise/architecture/data/data-consistency.md +574 -0
- package/expertise/architecture/data/data-modeling.md +536 -0
- package/expertise/architecture/data/event-streams-and-queues.md +634 -0
- package/expertise/architecture/data/index.md +25 -0
- package/expertise/architecture/data/search-architecture.md +663 -0
- package/expertise/architecture/data/sql-vs-nosql.md +708 -0
- package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
- package/expertise/architecture/decisions/build-vs-buy.md +616 -0
- package/expertise/architecture/decisions/index.md +23 -0
- package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
- package/expertise/architecture/decisions/technology-selection.md +616 -0
- package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
- package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
- package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
- package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
- package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
- package/expertise/architecture/distributed/index.md +25 -0
- package/expertise/architecture/distributed/saga-pattern.md +797 -0
- package/expertise/architecture/foundations/architectural-thinking.md +460 -0
- package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
- package/expertise/architecture/foundations/design-principles-solid.md +649 -0
- package/expertise/architecture/foundations/domain-driven-design.md +719 -0
- package/expertise/architecture/foundations/index.md +25 -0
- package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
- package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
- package/expertise/architecture/index.md +34 -0
- package/expertise/architecture/integration/api-design-graphql.md +638 -0
- package/expertise/architecture/integration/api-design-grpc.md +804 -0
- package/expertise/architecture/integration/api-design-rest.md +892 -0
- package/expertise/architecture/integration/index.md +25 -0
- package/expertise/architecture/integration/third-party-integration.md +795 -0
- package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
- package/expertise/architecture/integration/websockets-realtime.md +791 -0
- package/expertise/architecture/mobile-architecture/index.md +22 -0
- package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
- package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
- package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
- package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
- package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
- package/expertise/architecture/patterns/event-driven.md +797 -0
- package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
- package/expertise/architecture/patterns/index.md +27 -0
- package/expertise/architecture/patterns/layered-architecture.md +736 -0
- package/expertise/architecture/patterns/microservices.md +753 -0
- package/expertise/architecture/patterns/modular-monolith.md +692 -0
- package/expertise/architecture/patterns/monolith.md +626 -0
- package/expertise/architecture/patterns/plugin-architecture.md +735 -0
- package/expertise/architecture/patterns/serverless.md +780 -0
- package/expertise/architecture/scaling/database-scaling.md +615 -0
- package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
- package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
- package/expertise/architecture/scaling/index.md +24 -0
- package/expertise/architecture/scaling/multi-tenancy.md +800 -0
- package/expertise/architecture/scaling/stateless-design.md +787 -0
- package/expertise/backend/embedded-firmware.md +625 -0
- package/expertise/backend/go.md +853 -0
- package/expertise/backend/index.md +24 -0
- package/expertise/backend/java-spring.md +448 -0
- package/expertise/backend/node-typescript.md +625 -0
- package/expertise/backend/python-fastapi.md +724 -0
- package/expertise/backend/rust.md +458 -0
- package/expertise/backend/solidity.md +711 -0
- package/expertise/composition-map.yaml +443 -0
- package/expertise/content/foundations/content-modeling.md +395 -0
- package/expertise/content/foundations/editorial-standards.md +449 -0
- package/expertise/content/foundations/index.md +24 -0
- package/expertise/content/foundations/microcopy.md +455 -0
- package/expertise/content/foundations/terminology-governance.md +509 -0
- package/expertise/content/index.md +34 -0
- package/expertise/content/patterns/accessibility-copy.md +518 -0
- package/expertise/content/patterns/index.md +24 -0
- package/expertise/content/patterns/notification-content.md +433 -0
- package/expertise/content/patterns/sample-content.md +486 -0
- package/expertise/content/patterns/state-copy.md +439 -0
- package/expertise/design/PROGRESS.md +58 -0
- package/expertise/design/disciplines/dark-mode-theming.md +577 -0
- package/expertise/design/disciplines/design-systems.md +595 -0
- package/expertise/design/disciplines/index.md +25 -0
- package/expertise/design/disciplines/information-architecture.md +800 -0
- package/expertise/design/disciplines/interaction-design.md +788 -0
- package/expertise/design/disciplines/responsive-design.md +552 -0
- package/expertise/design/disciplines/usability-testing.md +516 -0
- package/expertise/design/disciplines/user-research.md +792 -0
- package/expertise/design/foundations/accessibility-design.md +796 -0
- package/expertise/design/foundations/color-theory.md +797 -0
- package/expertise/design/foundations/iconography.md +795 -0
- package/expertise/design/foundations/index.md +26 -0
- package/expertise/design/foundations/motion-and-animation.md +653 -0
- package/expertise/design/foundations/rtl-design.md +585 -0
- package/expertise/design/foundations/spacing-and-layout.md +607 -0
- package/expertise/design/foundations/typography.md +800 -0
- package/expertise/design/foundations/visual-hierarchy.md +761 -0
- package/expertise/design/index.md +32 -0
- package/expertise/design/patterns/authentication-flows.md +474 -0
- package/expertise/design/patterns/content-consumption.md +789 -0
- package/expertise/design/patterns/data-display.md +618 -0
- package/expertise/design/patterns/e-commerce.md +1494 -0
- package/expertise/design/patterns/feedback-and-states.md +642 -0
- package/expertise/design/patterns/forms-and-input.md +819 -0
- package/expertise/design/patterns/gamification.md +801 -0
- package/expertise/design/patterns/index.md +31 -0
- package/expertise/design/patterns/microinteractions.md +449 -0
- package/expertise/design/patterns/navigation.md +800 -0
- package/expertise/design/patterns/notifications.md +705 -0
- package/expertise/design/patterns/onboarding.md +700 -0
- package/expertise/design/patterns/search-and-filter.md +601 -0
- package/expertise/design/patterns/settings-and-preferences.md +768 -0
- package/expertise/design/patterns/social-and-community.md +748 -0
- package/expertise/design/platforms/desktop-native.md +612 -0
- package/expertise/design/platforms/index.md +25 -0
- package/expertise/design/platforms/mobile-android.md +825 -0
- package/expertise/design/platforms/mobile-cross-platform.md +983 -0
- package/expertise/design/platforms/mobile-ios.md +699 -0
- package/expertise/design/platforms/tablet.md +794 -0
- package/expertise/design/platforms/web-dashboard.md +790 -0
- package/expertise/design/platforms/web-responsive.md +550 -0
- package/expertise/design/psychology/behavioral-nudges.md +449 -0
- package/expertise/design/psychology/cognitive-load.md +1191 -0
- package/expertise/design/psychology/error-psychology.md +778 -0
- package/expertise/design/psychology/index.md +22 -0
- package/expertise/design/psychology/persuasive-design.md +736 -0
- package/expertise/design/psychology/user-mental-models.md +623 -0
- package/expertise/design/tooling/open-pencil.md +266 -0
- package/expertise/frontend/angular.md +1073 -0
- package/expertise/frontend/desktop-electron.md +546 -0
- package/expertise/frontend/flutter.md +782 -0
- package/expertise/frontend/index.md +27 -0
- package/expertise/frontend/native-android.md +409 -0
- package/expertise/frontend/native-ios.md +490 -0
- package/expertise/frontend/react-native.md +1160 -0
- package/expertise/frontend/react.md +808 -0
- package/expertise/frontend/vue.md +1089 -0
- package/expertise/humanize/domain-rules-code.md +79 -0
- package/expertise/humanize/domain-rules-content.md +67 -0
- package/expertise/humanize/domain-rules-technical-docs.md +56 -0
- package/expertise/humanize/index.md +35 -0
- package/expertise/humanize/self-audit-checklist.md +87 -0
- package/expertise/humanize/sentence-patterns.md +218 -0
- package/expertise/humanize/vocabulary-blacklist.md +105 -0
- package/expertise/i18n/PROGRESS.md +65 -0
- package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
- package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
- package/expertise/i18n/advanced/complex-scripts.md +30 -0
- package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
- package/expertise/i18n/advanced/testing-i18n.md +28 -0
- package/expertise/i18n/content/content-adaptation.md +23 -0
- package/expertise/i18n/content/locale-specific-formatting.md +23 -0
- package/expertise/i18n/content/machine-translation-integration.md +28 -0
- package/expertise/i18n/content/translation-management.md +29 -0
- package/expertise/i18n/foundations/date-time-calendars.md +67 -0
- package/expertise/i18n/foundations/i18n-architecture.md +272 -0
- package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
- package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
- package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
- package/expertise/i18n/foundations/string-externalization.md +236 -0
- package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
- package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
- package/expertise/i18n/index.md +38 -0
- package/expertise/i18n/platform/backend-i18n.md +31 -0
- package/expertise/i18n/platform/flutter-i18n.md +148 -0
- package/expertise/i18n/platform/native-android-i18n.md +36 -0
- package/expertise/i18n/platform/native-ios-i18n.md +36 -0
- package/expertise/i18n/platform/react-i18n.md +103 -0
- package/expertise/i18n/platform/web-css-i18n.md +81 -0
- package/expertise/i18n/rtl/arabic-specific.md +175 -0
- package/expertise/i18n/rtl/hebrew-specific.md +149 -0
- package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
- package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
- package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
- package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
- package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
- package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
- package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
- package/expertise/i18n/rtl/rtl-typography.md +160 -0
- package/expertise/index.md +113 -0
- package/expertise/index.yaml +216 -0
- package/expertise/infrastructure/cloud-aws.md +597 -0
- package/expertise/infrastructure/cloud-gcp.md +599 -0
- package/expertise/infrastructure/cybersecurity.md +816 -0
- package/expertise/infrastructure/database-mongodb.md +447 -0
- package/expertise/infrastructure/database-postgres.md +400 -0
- package/expertise/infrastructure/devops-cicd.md +787 -0
- package/expertise/infrastructure/index.md +27 -0
- package/expertise/performance/PROGRESS.md +50 -0
- package/expertise/performance/backend/api-latency.md +1204 -0
- package/expertise/performance/backend/background-jobs.md +506 -0
- package/expertise/performance/backend/connection-pooling.md +1209 -0
- package/expertise/performance/backend/database-query-optimization.md +515 -0
- package/expertise/performance/backend/index.md +23 -0
- package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
- package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
- package/expertise/performance/foundations/caching-strategies.md +489 -0
- package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
- package/expertise/performance/foundations/index.md +24 -0
- package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
- package/expertise/performance/foundations/memory-management.md +964 -0
- package/expertise/performance/foundations/performance-budgets.md +1314 -0
- package/expertise/performance/index.md +31 -0
- package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
- package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
- package/expertise/performance/infrastructure/index.md +22 -0
- package/expertise/performance/infrastructure/load-balancing.md +1081 -0
- package/expertise/performance/infrastructure/observability.md +1079 -0
- package/expertise/performance/mobile/index.md +23 -0
- package/expertise/performance/mobile/mobile-animations.md +544 -0
- package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
- package/expertise/performance/mobile/mobile-network.md +452 -0
- package/expertise/performance/mobile/mobile-rendering.md +599 -0
- package/expertise/performance/mobile/mobile-startup-time.md +505 -0
- package/expertise/performance/platform-specific/flutter-performance.md +647 -0
- package/expertise/performance/platform-specific/index.md +22 -0
- package/expertise/performance/platform-specific/node-performance.md +1307 -0
- package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
- package/expertise/performance/platform-specific/react-performance.md +1403 -0
- package/expertise/performance/web/bundle-optimization.md +1239 -0
- package/expertise/performance/web/image-and-media.md +636 -0
- package/expertise/performance/web/index.md +24 -0
- package/expertise/performance/web/network-optimization.md +1133 -0
- package/expertise/performance/web/rendering-performance.md +1098 -0
- package/expertise/performance/web/ssr-and-hydration.md +918 -0
- package/expertise/performance/web/web-vitals.md +1374 -0
- package/expertise/quality/accessibility.md +985 -0
- package/expertise/quality/evidence-based-verification.md +499 -0
- package/expertise/quality/index.md +24 -0
- package/expertise/quality/ml-model-audit.md +614 -0
- package/expertise/quality/performance.md +600 -0
- package/expertise/quality/testing-api.md +891 -0
- package/expertise/quality/testing-mobile.md +496 -0
- package/expertise/quality/testing-web.md +849 -0
- package/expertise/security/PROGRESS.md +54 -0
- package/expertise/security/agentic-identity.md +540 -0
- package/expertise/security/compliance-frameworks.md +601 -0
- package/expertise/security/data/data-encryption.md +364 -0
- package/expertise/security/data/data-privacy-gdpr.md +692 -0
- package/expertise/security/data/database-security.md +1171 -0
- package/expertise/security/data/index.md +22 -0
- package/expertise/security/data/pii-handling.md +531 -0
- package/expertise/security/foundations/authentication.md +1041 -0
- package/expertise/security/foundations/authorization.md +603 -0
- package/expertise/security/foundations/cryptography.md +1001 -0
- package/expertise/security/foundations/index.md +25 -0
- package/expertise/security/foundations/owasp-top-10.md +1354 -0
- package/expertise/security/foundations/secrets-management.md +1217 -0
- package/expertise/security/foundations/secure-sdlc.md +700 -0
- package/expertise/security/foundations/supply-chain-security.md +698 -0
- package/expertise/security/index.md +31 -0
- package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
- package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
- package/expertise/security/infrastructure/container-security.md +721 -0
- package/expertise/security/infrastructure/incident-response.md +1295 -0
- package/expertise/security/infrastructure/index.md +24 -0
- package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
- package/expertise/security/infrastructure/network-security.md +1337 -0
- package/expertise/security/mobile/index.md +23 -0
- package/expertise/security/mobile/mobile-android-security.md +1218 -0
- package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
- package/expertise/security/mobile/mobile-data-storage.md +1265 -0
- package/expertise/security/mobile/mobile-ios-security.md +1401 -0
- package/expertise/security/mobile/mobile-network-security.md +1520 -0
- package/expertise/security/smart-contract-security.md +594 -0
- package/expertise/security/testing/index.md +22 -0
- package/expertise/security/testing/penetration-testing.md +1258 -0
- package/expertise/security/testing/security-code-review.md +1765 -0
- package/expertise/security/testing/threat-modeling.md +1074 -0
- package/expertise/security/testing/vulnerability-scanning.md +1062 -0
- package/expertise/security/web/api-security.md +586 -0
- package/expertise/security/web/cors-and-headers.md +433 -0
- package/expertise/security/web/csrf.md +562 -0
- package/expertise/security/web/file-upload.md +1477 -0
- package/expertise/security/web/index.md +25 -0
- package/expertise/security/web/injection.md +1375 -0
- package/expertise/security/web/session-management.md +1101 -0
- package/expertise/security/web/xss.md +1158 -0
- package/exports/README.md +17 -0
- package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
- package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
- package/exports/hosts/claude/.claude/agents/designer.md +55 -0
- package/exports/hosts/claude/.claude/agents/executor.md +55 -0
- package/exports/hosts/claude/.claude/agents/learner.md +51 -0
- package/exports/hosts/claude/.claude/agents/planner.md +53 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
- package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
- package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
- package/exports/hosts/claude/.claude/commands/author.md +42 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
- package/exports/hosts/claude/.claude/commands/design.md +44 -0
- package/exports/hosts/claude/.claude/commands/discover.md +37 -0
- package/exports/hosts/claude/.claude/commands/execute.md +48 -0
- package/exports/hosts/claude/.claude/commands/learn.md +38 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
- package/exports/hosts/claude/.claude/commands/plan.md +39 -0
- package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
- package/exports/hosts/claude/.claude/commands/review.md +40 -0
- package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
- package/exports/hosts/claude/.claude/commands/specify.md +38 -0
- package/exports/hosts/claude/.claude/commands/verify.md +37 -0
- package/exports/hosts/claude/.claude/settings.json +34 -0
- package/exports/hosts/claude/CLAUDE.md +19 -0
- package/exports/hosts/claude/export.manifest.json +38 -0
- package/exports/hosts/claude/host-package.json +67 -0
- package/exports/hosts/codex/AGENTS.md +19 -0
- package/exports/hosts/codex/export.manifest.json +38 -0
- package/exports/hosts/codex/host-package.json +41 -0
- package/exports/hosts/cursor/.cursor/hooks.json +16 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
- package/exports/hosts/cursor/export.manifest.json +38 -0
- package/exports/hosts/cursor/host-package.json +42 -0
- package/exports/hosts/gemini/GEMINI.md +19 -0
- package/exports/hosts/gemini/export.manifest.json +38 -0
- package/exports/hosts/gemini/host-package.json +41 -0
- package/hooks/README.md +18 -0
- package/hooks/definitions/loop_cap_guard.yaml +21 -0
- package/hooks/definitions/post_tool_capture.yaml +24 -0
- package/hooks/definitions/pre_compact_summary.yaml +19 -0
- package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
- package/hooks/definitions/protected_path_write_guard.yaml +19 -0
- package/hooks/definitions/session_start.yaml +19 -0
- package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
- package/hooks/loop-cap-guard +17 -0
- package/hooks/post-tool-lint +36 -0
- package/hooks/protected-path-write-guard +17 -0
- package/hooks/session-start +41 -0
- package/llms-full.txt +2355 -0
- package/llms.txt +43 -0
- package/package.json +79 -0
- package/roles/README.md +20 -0
- package/roles/clarifier.md +42 -0
- package/roles/content-author.md +63 -0
- package/roles/designer.md +55 -0
- package/roles/executor.md +55 -0
- package/roles/learner.md +51 -0
- package/roles/planner.md +53 -0
- package/roles/researcher.md +43 -0
- package/roles/reviewer.md +54 -0
- package/roles/specifier.md +47 -0
- package/roles/verifier.md +71 -0
- package/schemas/README.md +24 -0
- package/schemas/accepted-learning.schema.json +20 -0
- package/schemas/author-artifact.schema.json +156 -0
- package/schemas/clarification.schema.json +19 -0
- package/schemas/design-artifact.schema.json +80 -0
- package/schemas/docs-claim.schema.json +18 -0
- package/schemas/export-manifest.schema.json +20 -0
- package/schemas/hook.schema.json +67 -0
- package/schemas/host-export-package.schema.json +18 -0
- package/schemas/implementation-plan.schema.json +19 -0
- package/schemas/proposed-learning.schema.json +19 -0
- package/schemas/research.schema.json +18 -0
- package/schemas/review.schema.json +29 -0
- package/schemas/run-manifest.schema.json +18 -0
- package/schemas/spec-challenge.schema.json +18 -0
- package/schemas/spec.schema.json +20 -0
- package/schemas/usage.schema.json +102 -0
- package/schemas/verification-proof.schema.json +29 -0
- package/schemas/wazir-manifest.schema.json +173 -0
- package/skills/README.md +40 -0
- package/skills/brainstorming/SKILL.md +77 -0
- package/skills/debugging/SKILL.md +50 -0
- package/skills/design/SKILL.md +61 -0
- package/skills/dispatching-parallel-agents/SKILL.md +128 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +169 -0
- package/skills/humanize/SKILL.md +123 -0
- package/skills/init-pipeline/SKILL.md +124 -0
- package/skills/prepare-next/SKILL.md +20 -0
- package/skills/receiving-code-review/SKILL.md +123 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +108 -0
- package/skills/run-audit/SKILL.md +197 -0
- package/skills/scan-project/SKILL.md +41 -0
- package/skills/self-audit/SKILL.md +153 -0
- package/skills/subagent-driven-development/SKILL.md +154 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +102 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tdd/SKILL.md +23 -0
- package/skills/using-git-worktrees/SKILL.md +163 -0
- package/skills/using-skills/SKILL.md +95 -0
- package/skills/verification/SKILL.md +22 -0
- package/skills/wazir/SKILL.md +463 -0
- package/skills/writing-plans/SKILL.md +30 -0
- package/skills/writing-skills/SKILL.md +157 -0
- package/skills/writing-skills/anthropic-best-practices.md +122 -0
- package/skills/writing-skills/persuasion-principles.md +50 -0
- package/templates/README.md +20 -0
- package/templates/artifacts/README.md +10 -0
- package/templates/artifacts/accepted-learning.md +19 -0
- package/templates/artifacts/accepted-learning.template.json +12 -0
- package/templates/artifacts/author.md +74 -0
- package/templates/artifacts/author.template.json +19 -0
- package/templates/artifacts/clarification.md +21 -0
- package/templates/artifacts/clarification.template.json +12 -0
- package/templates/artifacts/execute-notes.md +19 -0
- package/templates/artifacts/implementation-plan.md +21 -0
- package/templates/artifacts/implementation-plan.template.json +11 -0
- package/templates/artifacts/learning-proposal.md +19 -0
- package/templates/artifacts/next-run-handoff.md +21 -0
- package/templates/artifacts/plan-review.md +19 -0
- package/templates/artifacts/proposed-learning.template.json +12 -0
- package/templates/artifacts/research.md +21 -0
- package/templates/artifacts/research.template.json +12 -0
- package/templates/artifacts/review-findings.md +19 -0
- package/templates/artifacts/review.template.json +11 -0
- package/templates/artifacts/run-manifest.template.json +8 -0
- package/templates/artifacts/spec-challenge.md +19 -0
- package/templates/artifacts/spec-challenge.template.json +11 -0
- package/templates/artifacts/spec.md +21 -0
- package/templates/artifacts/spec.template.json +12 -0
- package/templates/artifacts/verification-proof.md +19 -0
- package/templates/artifacts/verification-proof.template.json +11 -0
- package/templates/examples/accepted-learning.example.json +14 -0
- package/templates/examples/author.example.json +152 -0
- package/templates/examples/clarification.example.json +15 -0
- package/templates/examples/docs-claim.example.json +8 -0
- package/templates/examples/export-manifest.example.json +7 -0
- package/templates/examples/host-export-package.example.json +11 -0
- package/templates/examples/implementation-plan.example.json +17 -0
- package/templates/examples/proposed-learning.example.json +13 -0
- package/templates/examples/research.example.json +15 -0
- package/templates/examples/research.example.md +6 -0
- package/templates/examples/review.example.json +17 -0
- package/templates/examples/run-manifest.example.json +9 -0
- package/templates/examples/spec-challenge.example.json +14 -0
- package/templates/examples/spec.example.json +21 -0
- package/templates/examples/verification-proof.example.json +21 -0
- package/templates/examples/wazir-manifest.example.yaml +65 -0
- package/templates/task-definition-schema.md +99 -0
- package/tooling/README.md +20 -0
- package/tooling/src/adapters/context-mode.js +50 -0
- package/tooling/src/capture/command.js +376 -0
- package/tooling/src/capture/store.js +99 -0
- package/tooling/src/capture/usage.js +270 -0
- package/tooling/src/checks/branches.js +50 -0
- package/tooling/src/checks/brand-truth.js +110 -0
- package/tooling/src/checks/changelog.js +231 -0
- package/tooling/src/checks/command-registry.js +36 -0
- package/tooling/src/checks/commits.js +102 -0
- package/tooling/src/checks/docs-drift.js +103 -0
- package/tooling/src/checks/docs-truth.js +201 -0
- package/tooling/src/checks/runtime-surface.js +156 -0
- package/tooling/src/cli.js +116 -0
- package/tooling/src/command-options.js +56 -0
- package/tooling/src/commands/validate.js +320 -0
- package/tooling/src/doctor/command.js +91 -0
- package/tooling/src/export/command.js +77 -0
- package/tooling/src/export/compiler.js +498 -0
- package/tooling/src/guards/loop-cap-guard.js +52 -0
- package/tooling/src/guards/protected-path-write-guard.js +67 -0
- package/tooling/src/index/command.js +152 -0
- package/tooling/src/index/storage.js +1061 -0
- package/tooling/src/index/summarizers.js +261 -0
- package/tooling/src/loaders.js +18 -0
- package/tooling/src/project-root.js +22 -0
- package/tooling/src/recall/command.js +225 -0
- package/tooling/src/schema-validator.js +30 -0
- package/tooling/src/state-root.js +40 -0
- package/tooling/src/status/command.js +71 -0
- package/wazir.manifest.yaml +135 -0
- package/workflows/README.md +19 -0
- package/workflows/author.md +42 -0
- package/workflows/clarify.md +38 -0
- package/workflows/design-review.md +46 -0
- package/workflows/design.md +44 -0
- package/workflows/discover.md +37 -0
- package/workflows/execute.md +48 -0
- package/workflows/learn.md +38 -0
- package/workflows/plan-review.md +42 -0
- package/workflows/plan.md +39 -0
- package/workflows/prepare-next.md +37 -0
- package/workflows/review.md +40 -0
- package/workflows/run-audit.md +41 -0
- package/workflows/spec-challenge.md +41 -0
- package/workflows/specify.md +38 -0
- package/workflows/verify.md +37 -0
|
@@ -0,0 +1,985 @@
|
|
|
1
|
+
# Accessibility (a11y) — Expertise Module
|
|
2
|
+
|
|
3
|
+
> An accessibility specialist ensures that web and mobile applications are perceivable, operable, understandable, and robust for all users, including those with visual, auditory, motor, cognitive, and neurological disabilities. The scope spans semantic markup, assistive technology compatibility, WCAG conformance, automated and manual testing, legal compliance (ADA, EAA, Section 508), and organizational accessibility culture.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Core Patterns & Conventions
|
|
8
|
+
|
|
9
|
+
### WCAG 2.2 Conformance Levels
|
|
10
|
+
|
|
11
|
+
WCAG 2.2 (W3C Recommendation, October 2023) defines three conformance levels. Each higher level includes all criteria from the levels below it.
|
|
12
|
+
|
|
13
|
+
**Level A — Minimum Accessibility (30 criteria)**
|
|
14
|
+
Bare-minimum requirements. Failure here means many users are completely blocked.
|
|
15
|
+
- SC 1.1.1: Non-text content has text alternatives
|
|
16
|
+
- SC 1.3.1: Information and relationships are programmatically determinable
|
|
17
|
+
- SC 2.1.1: All functionality available from a keyboard
|
|
18
|
+
- SC 2.4.1: Skip repetitive blocks of content (skip links)
|
|
19
|
+
- SC 4.1.2: Name, role, value for all UI components
|
|
20
|
+
|
|
21
|
+
**Level AA — Standard Compliance Target (20 additional criteria)**
|
|
22
|
+
The legal standard referenced by ADA case law, Section 508, EAA/EN 301 549, and most organizational policies.
|
|
23
|
+
- SC 1.4.3: Contrast ratio at least 4.5:1 for normal text, 3:1 for large text
|
|
24
|
+
- SC 1.4.4: Text resizable up to 200% without loss of content
|
|
25
|
+
- SC 1.4.11: Non-text contrast — UI components and graphical objects at 3:1 ratio
|
|
26
|
+
- SC 2.4.7: Focus indicator is visible
|
|
27
|
+
- SC 1.4.13: Content on hover or focus is dismissible, hoverable, persistent
|
|
28
|
+
|
|
29
|
+
WCAG 2.2 added six Level AA criteria:
|
|
30
|
+
- SC 2.4.11: Focus Not Obscured (Minimum) — focused element not fully hidden by other content
|
|
31
|
+
- SC 2.4.13: Focus Appearance — visible focus indicator meets minimum area and contrast
|
|
32
|
+
- SC 2.5.7: Dragging Movements — single-pointer alternative for every drag operation
|
|
33
|
+
- SC 2.5.8: Target Size (Minimum) — interactive targets at least 24x24 CSS pixels
|
|
34
|
+
- SC 3.2.6: Consistent Help — help mechanisms appear in same relative order across pages
|
|
35
|
+
- SC 3.3.7: Redundant Entry — previously entered data auto-populated or selectable
|
|
36
|
+
- SC 3.3.8: Accessible Authentication (Minimum) — no cognitive function test required for login
|
|
37
|
+
|
|
38
|
+
And three Level AAA criteria:
|
|
39
|
+
- SC 2.4.12: Focus Not Obscured (Enhanced) — focused element fully visible
|
|
40
|
+
- SC 2.4.13: Focus Appearance — enhanced focus indicator requirements
|
|
41
|
+
- SC 3.3.9: Accessible Authentication (Enhanced) — no object or personal content recognition
|
|
42
|
+
|
|
43
|
+
**Level AAA — Enhanced Accessibility (28 additional criteria)**
|
|
44
|
+
Aspirational; not typically required by law. Apply selectively where feasible.
|
|
45
|
+
- SC 1.4.6: Enhanced contrast ratio 7:1 for normal text, 4.5:1 for large text
|
|
46
|
+
- SC 2.2.3: No timing — no time limits unless essential
|
|
47
|
+
- SC 2.5.5: Target Size (Enhanced) — targets at least 44x44 CSS pixels
|
|
48
|
+
- SC 1.4.8: Visual presentation preferences (line spacing, width, colors)
|
|
49
|
+
|
|
50
|
+
### Semantic HTML Patterns
|
|
51
|
+
|
|
52
|
+
Semantic HTML is the foundation of accessibility. Native elements carry implicit ARIA roles, keyboard behavior, and screen reader announcements without additional code.
|
|
53
|
+
|
|
54
|
+
**Landmark Regions:**
|
|
55
|
+
```html
|
|
56
|
+
<header> <!-- banner landmark -->
|
|
57
|
+
<nav> <!-- navigation landmark -->
|
|
58
|
+
<main> <!-- main landmark (one per page) -->
|
|
59
|
+
<aside> <!-- complementary landmark -->
|
|
60
|
+
<footer> <!-- contentinfo landmark -->
|
|
61
|
+
<section> <!-- region landmark (when labeled) -->
|
|
62
|
+
<form> <!-- form landmark (when labeled) -->
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Heading Hierarchy:**
|
|
66
|
+
- Use exactly one `<h1>` per page matching the document title
|
|
67
|
+
- Never skip heading levels (h1 -> h3 is invalid)
|
|
68
|
+
- Headings create a document outline that screen reader users navigate by (JAWS: `H` key, NVDA: `H` key)
|
|
69
|
+
- 67.5% of screen reader users navigate by headings as their primary strategy (WebAIM Survey 2024)
|
|
70
|
+
|
|
71
|
+
**Lists:**
|
|
72
|
+
- Use `<ul>` for unordered lists, `<ol>` for ordered lists, `<dl>` for definition/description lists
|
|
73
|
+
- Screen readers announce "list, 5 items" — this count gives users orientation
|
|
74
|
+
- Navigation menus should use `<nav>` containing `<ul>` with `<li>` items
|
|
75
|
+
|
|
76
|
+
**Tables:**
|
|
77
|
+
- Use `<table>` only for tabular data, never for layout
|
|
78
|
+
- Always include `<caption>`, `<thead>`, `<th scope="col|row">`
|
|
79
|
+
- Complex tables need `headers` attribute on `<td>` elements referencing `<th>` IDs
|
|
80
|
+
|
|
81
|
+
### ARIA Patterns
|
|
82
|
+
|
|
83
|
+
**The Five Rules of ARIA (W3C):**
|
|
84
|
+
|
|
85
|
+
1. **First Rule**: If you can use a native HTML element with the semantics and behavior you need already built in, do so instead of adding ARIA. No ARIA is better than bad ARIA.
|
|
86
|
+
2. **Second Rule**: Do not change native semantics unless absolutely necessary. Do not add `role="heading"` to a `<h2>`.
|
|
87
|
+
3. **Third Rule**: All interactive ARIA controls must be operable with a keyboard.
|
|
88
|
+
4. **Fourth Rule**: Do not use `role="presentation"` or `aria-hidden="true"` on a focusable element.
|
|
89
|
+
5. **Fifth Rule**: All interactive elements must have an accessible name.
|
|
90
|
+
|
|
91
|
+
**When ARIA IS appropriate:**
|
|
92
|
+
- Custom widgets with no native HTML equivalent (tabs, tree views, comboboxes)
|
|
93
|
+
- Dynamic content updates (`aria-live` regions)
|
|
94
|
+
- Relationships that cannot be expressed in HTML (`aria-controls`, `aria-owns`)
|
|
95
|
+
- State communication (`aria-expanded`, `aria-selected`, `aria-pressed`)
|
|
96
|
+
- Supplementary descriptions (`aria-describedby`, `aria-description`)
|
|
97
|
+
|
|
98
|
+
**When ARIA is NOT appropriate:**
|
|
99
|
+
- Adding `role="button"` to a `<div>` — use `<button>` instead
|
|
100
|
+
- Adding `role="link"` to a `<span>` — use `<a href>` instead
|
|
101
|
+
- Adding `aria-label` to a `<div>` with no interactive role — non-interactive elements ignore accessible names in most screen readers
|
|
102
|
+
- Using `aria-label` when visible text already serves as the label
|
|
103
|
+
|
|
104
|
+
**Key statistic**: WebAIM's 2025 Million analysis found that pages WITH ARIA present averaged 41% more detected accessibility errors than those without, because ARIA is frequently misused.
|
|
105
|
+
|
|
106
|
+
### Keyboard Navigation Patterns
|
|
107
|
+
|
|
108
|
+
**Tab Order:**
|
|
109
|
+
- Interactive elements must follow a logical reading order via the natural DOM sequence
|
|
110
|
+
- Never use positive `tabindex` values (`tabindex="1"`, `tabindex="5"`) — they break the natural flow
|
|
111
|
+
- `tabindex="0"` adds an element to the tab order; `tabindex="-1"` makes it programmatically focusable but removes it from tab order
|
|
112
|
+
|
|
113
|
+
**Focus Management:**
|
|
114
|
+
- On route/page change in SPAs: move focus to the new page heading or main content area
|
|
115
|
+
- After opening a modal: move focus to the first focusable element or the dialog itself
|
|
116
|
+
- After closing a modal: return focus to the triggering element
|
|
117
|
+
- After deleting an item from a list: move focus to the next item or the list container
|
|
118
|
+
- After expanding a disclosure: keep focus on the trigger button
|
|
119
|
+
|
|
120
|
+
**Skip Links:**
|
|
121
|
+
- First focusable element on the page: `<a href="#main-content" class="skip-link">Skip to main content</a>`
|
|
122
|
+
- Should become visible on focus for sighted keyboard users
|
|
123
|
+
- Required by SC 2.4.1 (Level A) — bypassing blocks of repeated content
|
|
124
|
+
|
|
125
|
+
**Focus Indicators:**
|
|
126
|
+
- Default browser outline must NOT be removed without a visible replacement (SC 2.4.7, Level AA)
|
|
127
|
+
- WCAG 2.2 SC 2.4.13 requires: focus indicator area >= 2px perimeter, 3:1 contrast ratio against adjacent colors
|
|
128
|
+
- CSS: `outline: 2px solid #005fcc; outline-offset: 2px;` is a safe baseline
|
|
129
|
+
|
|
130
|
+
### Color Contrast Requirements
|
|
131
|
+
|
|
132
|
+
| Element Type | Minimum Ratio (AA) | Enhanced Ratio (AAA) | WCAG SC |
|
|
133
|
+
|---|---|---|---|
|
|
134
|
+
| Normal text (<18pt / <14pt bold) | 4.5:1 | 7:1 | 1.4.3 / 1.4.6 |
|
|
135
|
+
| Large text (>=18pt / >=14pt bold) | 3:1 | 4.5:1 | 1.4.3 / 1.4.6 |
|
|
136
|
+
| UI components & graphical objects | 3:1 | N/A | 1.4.11 |
|
|
137
|
+
| Focus indicators | 3:1 | N/A | 2.4.13 |
|
|
138
|
+
|
|
139
|
+
- Never use color alone to convey information (SC 1.4.1, Level A) — add text, patterns, or icons
|
|
140
|
+
- Test with browser tools: Chrome DevTools contrast checker, Firefox Accessibility Inspector
|
|
141
|
+
- Tools: WebAIM Contrast Checker, Polypane, Stark (Figma plugin)
|
|
142
|
+
|
|
143
|
+
### Form Accessibility
|
|
144
|
+
|
|
145
|
+
**Labels:**
|
|
146
|
+
- Every form input MUST have a programmatically associated label via `<label for="id">` or wrapping `<label>` element
|
|
147
|
+
- Use `aria-labelledby` for complex labels composed from multiple text sources
|
|
148
|
+
- Placeholder text is NOT a substitute for a label — it disappears on input, fails contrast in most browsers, and is not consistently announced by screen readers
|
|
149
|
+
|
|
150
|
+
**Error Messages:**
|
|
151
|
+
- Connect errors to inputs with `aria-describedby` pointing to the error element
|
|
152
|
+
- Set `aria-invalid="true"` on the invalid field
|
|
153
|
+
- Use `aria-live="assertive"` or `role="alert"` on error containers for immediate announcement
|
|
154
|
+
- Group related fields with `<fieldset>` and `<legend>` (radio buttons, checkboxes, address groups)
|
|
155
|
+
- On form submission errors, either move focus to the first invalid field or display an error summary at the top with links to each invalid field
|
|
156
|
+
|
|
157
|
+
**Required Fields:**
|
|
158
|
+
- Mark required fields with `aria-required="true"` or HTML `required` attribute
|
|
159
|
+
- Indicate required fields visually (asterisk with legend explaining meaning) — not color alone
|
|
160
|
+
|
|
161
|
+
### Mobile Accessibility
|
|
162
|
+
|
|
163
|
+
**Touch Target Size:**
|
|
164
|
+
- WCAG 2.2 SC 2.5.8 (Level AA): minimum 24x24 CSS pixels
|
|
165
|
+
- WCAG 2.2 SC 2.5.5 (Level AAA): minimum 44x44 CSS pixels
|
|
166
|
+
- Apple HIG: minimum 44x44 pt — matches AAA
|
|
167
|
+
- Material Design (Android): minimum 48x48 dp
|
|
168
|
+
- Spacing between targets counts: adequate spacing can compensate for smaller targets
|
|
169
|
+
|
|
170
|
+
**Gesture Alternatives (SC 2.5.1, Level A):**
|
|
171
|
+
- Every multipoint or path-based gesture (pinch, swipe, drag) must have a single-pointer alternative
|
|
172
|
+
- Example: swipe-to-delete must also offer a delete button
|
|
173
|
+
- Example: pinch-to-zoom must also offer zoom +/- buttons
|
|
174
|
+
- Drag-and-drop (SC 2.5.7, Level AA) must provide an alternative single-point mechanism
|
|
175
|
+
|
|
176
|
+
**Screen Reader Behavior on Mobile:**
|
|
177
|
+
- VoiceOver (iOS): swipe left/right to navigate elements, double-tap to activate
|
|
178
|
+
- TalkBack (Android): swipe left/right to navigate, double-tap to activate
|
|
179
|
+
- Both override standard touch gestures when enabled — custom gestures must not conflict
|
|
180
|
+
- Test with both screen readers on real devices, not just simulators
|
|
181
|
+
|
|
182
|
+
**Orientation:** Do not restrict content to a single orientation (SC 1.3.4, Level AA) unless essential (e.g., a piano app).
|
|
183
|
+
|
|
184
|
+
### Dynamic Content
|
|
185
|
+
|
|
186
|
+
**Live Regions:**
|
|
187
|
+
- `aria-live="polite"` — announces after current speech finishes (status updates, new messages)
|
|
188
|
+
- `aria-live="assertive"` — interrupts current speech (errors, urgent alerts)
|
|
189
|
+
- `role="status"` — implicit `aria-live="polite"` (search result counts, progress)
|
|
190
|
+
- `role="alert"` — implicit `aria-live="assertive"` (form errors, time warnings)
|
|
191
|
+
- Live regions must exist in the DOM before content is injected — dynamically adding `aria-live` is unreliable in many screen readers
|
|
192
|
+
- Keep announcements concise — screen readers read the entire live region content on each change
|
|
193
|
+
|
|
194
|
+
**SPA Route Changes:**
|
|
195
|
+
- Manage focus on navigation: move focus to `<h1>` or `<main>` of the new view
|
|
196
|
+
- Update `document.title` to reflect the current view
|
|
197
|
+
- Announce navigation programmatically via a visually hidden live region
|
|
198
|
+
- React: use `@reach/router` or React Router v6+ with focus management; or implement a custom `useAnnounce` hook
|
|
199
|
+
- Angular: `@angular/cdk/a11y` `LiveAnnouncer` service
|
|
200
|
+
- Vue: `vue-announcer` or custom composable
|
|
201
|
+
|
|
202
|
+
**Loading States:**
|
|
203
|
+
- Use `aria-busy="true"` on the container being updated; screen readers will wait to re-read it
|
|
204
|
+
- Announce loading start and completion via a live region
|
|
205
|
+
- Provide a loading indicator that is visible AND announced to screen readers
|
|
206
|
+
- Avoid removing content from the DOM during loading — keep a placeholder
|
|
207
|
+
|
|
208
|
+
### Media Accessibility
|
|
209
|
+
|
|
210
|
+
**Video:**
|
|
211
|
+
- Captions (SC 1.2.2, Level A) — synchronized text for speech and meaningful sounds
|
|
212
|
+
- Audio descriptions (SC 1.2.3, Level A for prerecorded; SC 1.2.5, Level AA) — narration of visual-only content
|
|
213
|
+
- Transcript (SC 1.2.1, Level A for audio-only) — full text alternative
|
|
214
|
+
|
|
215
|
+
**Audio:**
|
|
216
|
+
- Transcript is required for prerecorded audio (SC 1.2.1, Level A)
|
|
217
|
+
- Auto-playing audio that lasts >3 seconds must have a mechanism to pause/stop/mute (SC 1.4.2, Level A)
|
|
218
|
+
|
|
219
|
+
**Images:**
|
|
220
|
+
- Informative images: `alt` text describing content and purpose
|
|
221
|
+
- Decorative images: `alt=""` (empty alt) or CSS background-image
|
|
222
|
+
- Complex images (charts, diagrams): brief `alt` + long description via `aria-describedby` or linked page
|
|
223
|
+
- Images of text: avoid when possible (SC 1.4.5, Level AA) — use real text styled with CSS
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Anti-Patterns & Pitfalls
|
|
228
|
+
|
|
229
|
+
### 1. Missing or Inadequate Alt Text
|
|
230
|
+
**Problem**: Images without `alt` attributes cause screen readers to read the filename ("DSC_0042.jpg") or URL.
|
|
231
|
+
**Who it impacts**: Blind and low-vision users relying on screen readers.
|
|
232
|
+
**Fix**: Every `<img>` needs `alt`. Decorative images get `alt=""`. Informative images get concise, descriptive text.
|
|
233
|
+
**Prevalence**: Found on 55.5% of homepages (WebAIM Million 2025).
|
|
234
|
+
|
|
235
|
+
### 2. Low Color Contrast
|
|
236
|
+
**Problem**: Text that does not meet 4.5:1 (normal) or 3:1 (large) contrast ratios is unreadable in many conditions.
|
|
237
|
+
**Who it impacts**: Low-vision users, colorblind users, anyone in bright sunlight or on low-quality displays.
|
|
238
|
+
**Fix**: Test all text and UI component colors against WCAG contrast ratios.
|
|
239
|
+
**Prevalence**: Found on 79% of homepages — the most common WCAG failure (WebAIM Million 2025).
|
|
240
|
+
|
|
241
|
+
### 3. Missing Form Labels
|
|
242
|
+
**Problem**: Form inputs without programmatic labels leave screen reader users guessing what to enter.
|
|
243
|
+
**Who it impacts**: Blind users, voice control users (who activate fields by label name).
|
|
244
|
+
**Fix**: Use `<label for="id">` or wrap inputs in `<label>`. Never rely on placeholder alone.
|
|
245
|
+
**Prevalence**: 34.2% of form inputs lack proper labels (WebAIM Million 2025).
|
|
246
|
+
|
|
247
|
+
### 4. Empty Links and Buttons
|
|
248
|
+
**Problem**: Links or buttons with no text content (`<a href="..."><i class="icon-arrow"></i></a>`) have no accessible name.
|
|
249
|
+
**Who it impacts**: Screen reader users hear "link" or "button" with no description; voice control users cannot target them.
|
|
250
|
+
**Fix**: Add visually hidden text, `aria-label`, or meaningful text content inside the element.
|
|
251
|
+
|
|
252
|
+
### 5. Removing Focus Outlines Without Replacement
|
|
253
|
+
**Problem**: `outline: none` or `outline: 0` in CSS removes the only indicator keyboard users have to know which element is focused.
|
|
254
|
+
**Who it impacts**: Keyboard-only users, motor-impaired users who cannot use a mouse.
|
|
255
|
+
**Fix**: Replace the default outline with a custom, high-contrast focus indicator. Never use `:focus { outline: none }` without a `:focus-visible` alternative.
|
|
256
|
+
|
|
257
|
+
### 6. Div and Span Buttons
|
|
258
|
+
**Problem**: Using `<div onclick="...">` instead of `<button>` strips keyboard accessibility (`Enter`/`Space` activation), screen reader role announcements, and focus management.
|
|
259
|
+
**Who it impacts**: Keyboard users, screen reader users, voice control users.
|
|
260
|
+
**Fix**: Use native `<button>` or `<a href>`. If custom elements are unavoidable, add `role="button"`, `tabindex="0"`, and `keydown` handlers for `Enter` and `Space`.
|
|
261
|
+
|
|
262
|
+
### 7. Misusing ARIA (No ARIA Is Better Than Bad ARIA)
|
|
263
|
+
**Problem**: Adding ARIA roles, states, or properties incorrectly creates a worse experience than no ARIA at all — conflicting roles, invalid states, or missing required attributes.
|
|
264
|
+
**Who it impacts**: Screen reader users who receive incorrect or contradictory information.
|
|
265
|
+
**Fix**: Prefer native HTML. When ARIA is necessary, follow the WAI-ARIA Authoring Practices Guide (APG) patterns exactly.
|
|
266
|
+
|
|
267
|
+
### 8. Auto-Playing Media
|
|
268
|
+
**Problem**: Audio or video that plays automatically distracts users, interferes with screen readers, and triggers vestibular disorders.
|
|
269
|
+
**Who it impacts**: Screen reader users (audio overlaps speech output), users with attention disorders, vestibular disorder sufferers.
|
|
270
|
+
**Fix**: Never auto-play media with sound. If auto-play is essential, provide pause/stop/mute within 3 seconds (SC 1.4.2).
|
|
271
|
+
|
|
272
|
+
### 9. Missing Document Language
|
|
273
|
+
**Problem**: Without `<html lang="en">`, screen readers may use the wrong pronunciation engine, making content unintelligible.
|
|
274
|
+
**Who it impacts**: Screen reader users, especially multilingual users.
|
|
275
|
+
**Fix**: Always set the `lang` attribute on `<html>`. Use `lang` attribute on inline elements for foreign-language phrases.
|
|
276
|
+
**Prevalence**: Found on 17.1% of homepages (WebAIM Million 2025).
|
|
277
|
+
|
|
278
|
+
### 10. Keyboard Traps
|
|
279
|
+
**Problem**: Custom widgets (modals, date pickers, rich text editors) that capture focus and provide no keyboard escape mechanism.
|
|
280
|
+
**Who it impacts**: Keyboard-only users who are literally trapped and cannot interact with the rest of the page.
|
|
281
|
+
**Fix**: Ensure `Escape` closes overlays. Tab cycling within modals must be intentional with a clear exit. Test every custom widget with keyboard alone (SC 2.1.2, Level A).
|
|
282
|
+
|
|
283
|
+
### 11. Motion and Animation Without Reduced-Motion Support
|
|
284
|
+
**Problem**: Parallax scrolling, sliding transitions, and spinning animations trigger vestibular disorders (dizziness, nausea, migraine).
|
|
285
|
+
**Who it impacts**: Users with vestibular disorders, epilepsy, migraine, and ADHD.
|
|
286
|
+
**Fix**: Respect `prefers-reduced-motion: reduce` — provide static alternatives. Use fade/dissolve instead of slide/zoom.
|
|
287
|
+
|
|
288
|
+
### 12. Inaccessible CAPTCHAs
|
|
289
|
+
**Problem**: Image-based CAPTCHAs block blind users; audio CAPTCHAs block deaf users; puzzle CAPTCHAs block motor-impaired users; cognitive CAPTCHAs block users with learning disabilities.
|
|
290
|
+
**Who it impacts**: Nearly every disability category.
|
|
291
|
+
**Fix**: Use invisible/behavioral CAPTCHAs (Cloudflare Turnstile, proof-of-work solutions like ALTCHA), or provide multiple CAPTCHA types. SC 3.3.8 (WCAG 2.2) prohibits cognitive function tests for authentication.
|
|
292
|
+
|
|
293
|
+
### 13. Using `tabindex` Values Greater Than Zero
|
|
294
|
+
**Problem**: Positive `tabindex` values (`tabindex="1"`, `tabindex="99"`) override the natural DOM order, creating unpredictable tab sequences that confuse keyboard users.
|
|
295
|
+
**Who it impacts**: Keyboard-only users, screen reader users.
|
|
296
|
+
**Fix**: Use only `tabindex="0"` (add to tab order) and `tabindex="-1"` (programmatic focus only). Fix tab order by fixing DOM order.
|
|
297
|
+
|
|
298
|
+
### 14. Tooltips Without Keyboard Access
|
|
299
|
+
**Problem**: Tooltips that appear only on hover are invisible to keyboard users and often not announced by screen readers.
|
|
300
|
+
**Who it impacts**: Keyboard users, screen reader users, touch device users.
|
|
301
|
+
**Fix**: Show tooltips on both hover AND focus. Use `aria-describedby` to associate tooltip content. Ensure tooltips are dismissible with `Escape` and hoverable (SC 1.4.13, Level AA).
|
|
302
|
+
|
|
303
|
+
### 15. Relying Solely on Automated Testing
|
|
304
|
+
**Problem**: Automated tools catch only 30-40% of WCAG issues. They cannot evaluate content quality of alt text, logical reading order, or screen reader experience.
|
|
305
|
+
**Who it impacts**: All users with disabilities — issues that automated tools miss are often the most impactful.
|
|
306
|
+
**Fix**: Use automated tools as a baseline, then supplement with manual keyboard testing, screen reader testing, and testing with disabled users.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
## Testing Strategy
|
|
311
|
+
|
|
312
|
+
### Automated Testing Tools
|
|
313
|
+
|
|
314
|
+
| Tool | Type | Coverage | Best For |
|
|
315
|
+
|---|---|---|---|
|
|
316
|
+
| axe-core (Deque) | Library | ~57 WCAG rules | CI/CD integration, component tests |
|
|
317
|
+
| Lighthouse | Browser tool | Subset of axe rules | Quick audits, performance + a11y |
|
|
318
|
+
| WAVE | Browser extension | Visual overlay | Designer/developer quick checks |
|
|
319
|
+
| Pa11y | CLI/CI | HTML CodeSniffer rules | CI pipeline, batch scanning |
|
|
320
|
+
| IBM Equal Access | Browser + CI | IBM a11y rules | Enterprise environments |
|
|
321
|
+
| Stark | Design plugin | Contrast, vision sim | Figma/Sketch design phase |
|
|
322
|
+
|
|
323
|
+
**Limitations**: Automated tools detect ~30-40% of WCAG violations. They excel at: missing alt text, contrast ratios, missing labels, invalid ARIA. They cannot evaluate: alt text quality, logical reading order, meaningful link text, focus management correctness, or real screen reader experience.
|
|
324
|
+
|
|
325
|
+
### Manual Testing Checklist
|
|
326
|
+
|
|
327
|
+
**Keyboard Testing (do this first, every time):**
|
|
328
|
+
1. Unplug the mouse or disable the trackpad
|
|
329
|
+
2. Tab through the entire page — is every interactive element reachable?
|
|
330
|
+
3. Is the focus indicator always visible?
|
|
331
|
+
4. Can you activate buttons with `Enter` and `Space`?
|
|
332
|
+
5. Can you follow links with `Enter`?
|
|
333
|
+
6. Can you close modals/popovers with `Escape`?
|
|
334
|
+
7. Does tab order match visual order?
|
|
335
|
+
8. Are you ever trapped without an exit?
|
|
336
|
+
|
|
337
|
+
**Zoom Testing:**
|
|
338
|
+
1. Zoom to 200% — is all content still visible and functional?
|
|
339
|
+
2. Zoom to 400% — does content reflow to a single column (no horizontal scroll)?
|
|
340
|
+
3. Set browser font size to "Very Large" — does the layout accommodate?
|
|
341
|
+
|
|
342
|
+
**Color and Visual Testing:**
|
|
343
|
+
1. Enable Windows High Contrast Mode or macOS Increase Contrast
|
|
344
|
+
2. View the page in grayscale — is information conveyed without color?
|
|
345
|
+
3. Check all text and UI components against contrast requirements
|
|
346
|
+
|
|
347
|
+
**Content and Structure:**
|
|
348
|
+
1. Disable CSS — is the content readable in DOM order?
|
|
349
|
+
2. Check heading hierarchy with a browser extension (HeadingsMap, WAVE)
|
|
350
|
+
3. Verify all images have appropriate alt text (not just `alt` present)
|
|
351
|
+
4. Check all links have descriptive text (not "click here" or "read more")
|
|
352
|
+
|
|
353
|
+
### Screen Reader Testing
|
|
354
|
+
|
|
355
|
+
**Recommended Minimum Coverage:**
|
|
356
|
+
1. NVDA + Firefox (Windows) — free, most popular (40.5% market share, WebAIM 2024)
|
|
357
|
+
2. VoiceOver + Safari (macOS/iOS) — built-in, dominant on Apple platforms
|
|
358
|
+
3. TalkBack + Chrome (Android) — built-in, covers mobile Android
|
|
359
|
+
|
|
360
|
+
**Comprehensive Coverage (add to minimum):**
|
|
361
|
+
4. JAWS + Chrome (Windows) — enterprise standard (40.1% market share)
|
|
362
|
+
5. Narrator + Edge (Windows) — growing usage with Windows
|
|
363
|
+
|
|
364
|
+
**What to Test With Screen Readers:**
|
|
365
|
+
- Navigate by headings, landmarks, links, form fields
|
|
366
|
+
- Verify all images have meaningful announcements
|
|
367
|
+
- Complete forms end-to-end, including error recovery
|
|
368
|
+
- Test dynamic content updates (live regions, AJAX)
|
|
369
|
+
- Navigate data tables (row/column headers announced correctly)
|
|
370
|
+
- Test custom widgets (tabs, accordions, menus, dialogs)
|
|
371
|
+
|
|
372
|
+
### CI Integration
|
|
373
|
+
|
|
374
|
+
**axe-core with Playwright (recommended):**
|
|
375
|
+
```typescript
|
|
376
|
+
import { test, expect } from '@playwright/test';
|
|
377
|
+
import AxeBuilder from '@axe-core/playwright';
|
|
378
|
+
|
|
379
|
+
test('page has no a11y violations', async ({ page }) => {
|
|
380
|
+
await page.goto('/');
|
|
381
|
+
const results = await new AxeBuilder({ page })
|
|
382
|
+
.withTags(['wcag2a', 'wcag2aa', 'wcag22aa'])
|
|
383
|
+
.analyze();
|
|
384
|
+
expect(results.violations).toEqual([]);
|
|
385
|
+
});
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**jest-axe for Component Tests:**
|
|
389
|
+
```typescript
|
|
390
|
+
import { render } from '@testing-library/react';
|
|
391
|
+
import { axe, toHaveNoViolations } from 'jest-axe';
|
|
392
|
+
|
|
393
|
+
expect.extend(toHaveNoViolations);
|
|
394
|
+
|
|
395
|
+
test('form is accessible', async () => {
|
|
396
|
+
const { container } = render(<LoginForm />);
|
|
397
|
+
const results = await axe(container);
|
|
398
|
+
expect(results).toHaveNoViolations();
|
|
399
|
+
});
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
**CI Pipeline Strategy:**
|
|
403
|
+
- Run axe on every PR for critical pages (block on violations)
|
|
404
|
+
- Run full-site scans nightly (report, do not block)
|
|
405
|
+
- Generate JSON/HTML reports for tracking trends over time
|
|
406
|
+
- Set a violation budget: zero new violations per PR, reduce existing count by sprint
|
|
407
|
+
|
|
408
|
+
### Accessibility Auditing Methodology
|
|
409
|
+
|
|
410
|
+
1. **Automated scan** — establish baseline with axe-core or Lighthouse
|
|
411
|
+
2. **Keyboard walkthrough** — navigate the entire application without a mouse
|
|
412
|
+
3. **Screen reader walkthrough** — complete core user journeys with NVDA or VoiceOver
|
|
413
|
+
4. **WCAG criterion-by-criterion** — systematic check against each applicable SC
|
|
414
|
+
5. **Assistive technology matrix** — test with multiple AT combinations
|
|
415
|
+
6. **Cognitive walkthrough** — evaluate for users with cognitive disabilities (clear language, consistent navigation, error prevention)
|
|
416
|
+
7. **Document findings** — severity (critical/major/minor), impacted SC, impacted users, remediation guidance
|
|
417
|
+
|
|
418
|
+
### User Testing With People With Disabilities
|
|
419
|
+
|
|
420
|
+
- Recruit participants with diverse disabilities: blind, low-vision, deaf, motor-impaired, cognitive
|
|
421
|
+
- Use task-based testing: "Complete a purchase" rather than "Navigate the site"
|
|
422
|
+
- Participants use their own assistive technology and settings
|
|
423
|
+
- Observe without intervening — note where they struggle, not just where they fail
|
|
424
|
+
- Pay participants fairly for their expertise and time
|
|
425
|
+
- Conduct testing early and iteratively, not just before launch
|
|
426
|
+
|
|
427
|
+
---
|
|
428
|
+
|
|
429
|
+
## Performance Considerations
|
|
430
|
+
|
|
431
|
+
### Reduced Motion Preferences
|
|
432
|
+
|
|
433
|
+
```css
|
|
434
|
+
/* Default: include animations */
|
|
435
|
+
.card { transition: transform 0.3s ease; }
|
|
436
|
+
.card:hover { transform: scale(1.05); }
|
|
437
|
+
|
|
438
|
+
/* Respect user preference */
|
|
439
|
+
@media (prefers-reduced-motion: reduce) {
|
|
440
|
+
.card {
|
|
441
|
+
transition: none;
|
|
442
|
+
transform: none;
|
|
443
|
+
}
|
|
444
|
+
.card:hover {
|
|
445
|
+
opacity: 0.9; /* subtle non-motion alternative */
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
**JavaScript check:**
|
|
451
|
+
```javascript
|
|
452
|
+
const prefersReducedMotion =
|
|
453
|
+
window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
|
454
|
+
|
|
455
|
+
if (prefersReducedMotion) {
|
|
456
|
+
// Use instant transitions or fade-only effects
|
|
457
|
+
}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
Affects: vestibular disorder sufferers, epilepsy (SC 2.3.1 — no more than 3 flashes per second), migraine, ADHD. Also benefits battery life and low-end device performance.
|
|
461
|
+
|
|
462
|
+
### Loading States for Assistive Technology
|
|
463
|
+
|
|
464
|
+
- Mark loading containers with `aria-busy="true"` — screen readers defer re-reading until `aria-busy="false"`
|
|
465
|
+
- Announce loading state transitions via live region: "Loading results..." -> "5 results loaded"
|
|
466
|
+
- Skeleton screens should be hidden from screen readers (`aria-hidden="true"`) with a live-region announcement instead
|
|
467
|
+
- Never remove content from the DOM during loading — screen reader users lose their place
|
|
468
|
+
|
|
469
|
+
### Large DOM and Screen Reader Performance
|
|
470
|
+
|
|
471
|
+
- Screen readers build a virtual buffer/accessibility tree of the entire page — very large DOMs (>10,000 nodes) cause significant lag
|
|
472
|
+
- Virtualized lists (react-window, TanStack Virtual) improve performance but MUST maintain accessibility: `aria-setsize`, `aria-posinset` for each item, and `role="listbox"` or `role="grid"` on the container
|
|
473
|
+
- Lazy-loaded content must announce its arrival via live regions
|
|
474
|
+
- Infinite scroll must provide an alternative mechanism (pagination, "Load more" button) — keyboard users and screen reader users cannot reliably reach footer content with infinite scroll
|
|
475
|
+
|
|
476
|
+
### Performance vs Accessibility Tradeoffs
|
|
477
|
+
|
|
478
|
+
- Image lazy loading (`loading="lazy"`) is accessible — screen readers read the `alt` text regardless
|
|
479
|
+
- Code splitting does not inherently harm accessibility — but focus must be managed when new content renders
|
|
480
|
+
- Web fonts with `font-display: swap` can cause layout shift affecting screen magnifier users — use `font-display: optional` when possible
|
|
481
|
+
- Heavy client-side rendering delays screen reader access — use SSR/SSG for critical content
|
|
482
|
+
|
|
483
|
+
---
|
|
484
|
+
|
|
485
|
+
## Security Considerations
|
|
486
|
+
|
|
487
|
+
### CAPTCHAs and Accessibility
|
|
488
|
+
|
|
489
|
+
Traditional CAPTCHAs create an inherent conflict: making them machine-readable for assistive technology also makes them vulnerable to bots. WCAG 2.2 SC 3.3.8 (Accessible Authentication) prohibits cognitive function tests for authentication unless an alternative is provided.
|
|
490
|
+
|
|
491
|
+
**Accessible alternatives:**
|
|
492
|
+
- Cloudflare Turnstile — invisible behavioral analysis, no user interaction
|
|
493
|
+
- ALTCHA — proof-of-work, WCAG 2.2 AA compliant
|
|
494
|
+
- Honeypot fields — invisible to users, visible to bots
|
|
495
|
+
- Rate limiting + behavioral analysis — server-side bot detection
|
|
496
|
+
- Passkeys/WebAuthn — biometric authentication, inherently accessible
|
|
497
|
+
|
|
498
|
+
### Authentication Accessibility
|
|
499
|
+
|
|
500
|
+
- Login forms must have proper labels and be keyboard-accessible
|
|
501
|
+
- Multi-factor authentication must not rely solely on one sensory channel (e.g., visual-only QR codes need a text alternative)
|
|
502
|
+
- Password requirements must be clearly stated before submission, not just on error
|
|
503
|
+
- "Show password" toggle aids cognitive disability users — announce state change to screen readers
|
|
504
|
+
- Magic links and passkeys are more accessible than password + CAPTCHA flows
|
|
505
|
+
|
|
506
|
+
### Session Timeouts
|
|
507
|
+
|
|
508
|
+
- SC 2.2.1 (Level A): Users must be warned before timeout and given the option to extend
|
|
509
|
+
- Warning must appear at least 20 seconds before expiration
|
|
510
|
+
- User must be able to extend the session at least 10 times
|
|
511
|
+
- Save form data so it is not lost on timeout
|
|
512
|
+
- Exception: timeouts shorter than 20 hours for security are permissible if the user is warned
|
|
513
|
+
|
|
514
|
+
### Error Message Security vs Accessibility
|
|
515
|
+
|
|
516
|
+
- Tension: security best practice says "don't reveal whether an account exists" but accessibility says "be specific about errors"
|
|
517
|
+
- Balance: "The email or password is incorrect" is both secure and understandable
|
|
518
|
+
- Avoid: "Error 403" or "Invalid credentials" (too vague for cognitive disability users)
|
|
519
|
+
- Error messages must be programmatically associated with the relevant form field via `aria-describedby`
|
|
520
|
+
- Error messages must not disappear automatically — users with cognitive disabilities need time to read them
|
|
521
|
+
|
|
522
|
+
---
|
|
523
|
+
|
|
524
|
+
## Integration Patterns
|
|
525
|
+
|
|
526
|
+
### Component Library Accessibility
|
|
527
|
+
|
|
528
|
+
**Radix UI (React):**
|
|
529
|
+
- Unstyled primitives with full ARIA support, keyboard navigation, and focus management built in
|
|
530
|
+
- 28+ components (Dialog, Popover, Tabs, Select, etc.) following WAI-ARIA APG patterns
|
|
531
|
+
- Composable architecture — bring your own styles without breaking accessibility
|
|
532
|
+
- Used as the foundation for shadcn/ui
|
|
533
|
+
|
|
534
|
+
**React Aria (Adobe):**
|
|
535
|
+
- Behavior hooks that handle ARIA attributes, keyboard interactions, focus management, and internationalization
|
|
536
|
+
- Hooks-based architecture: `useButton`, `useDialog`, `useComboBox`, `useTable`
|
|
537
|
+
- Most comprehensive accessibility coverage of any component library
|
|
538
|
+
- Best choice when accessibility is the top priority
|
|
539
|
+
|
|
540
|
+
**Headless UI (Tailwind Labs):**
|
|
541
|
+
- React and Vue support with Tailwind CSS integration
|
|
542
|
+
- Fewer components than Radix but high-quality implementations
|
|
543
|
+
- Menu, Listbox, Combobox, Switch, Tabs, Dialog, Disclosure, Popover, Radio Group, Transition
|
|
544
|
+
|
|
545
|
+
**Selection guidance**: If you need a component that exists in these libraries, use it rather than building a custom one. The accessibility engineering in these libraries represents thousands of hours of testing.
|
|
546
|
+
|
|
547
|
+
### Design System Accessibility Tokens
|
|
548
|
+
|
|
549
|
+
Design systems should encode accessibility requirements in tokens:
|
|
550
|
+
```css
|
|
551
|
+
:root {
|
|
552
|
+
/* Contrast-safe color pairs */
|
|
553
|
+
--color-text-primary: #1a1a2e; /* 15.4:1 on white */
|
|
554
|
+
--color-text-secondary: #4a4a6a; /* 7.2:1 on white */
|
|
555
|
+
--color-text-on-primary: #ffffff; /* 4.6:1 on brand blue */
|
|
556
|
+
|
|
557
|
+
/* Focus indicators */
|
|
558
|
+
--focus-ring-width: 2px;
|
|
559
|
+
--focus-ring-offset: 2px;
|
|
560
|
+
--focus-ring-color: #005fcc;
|
|
561
|
+
|
|
562
|
+
/* Touch targets */
|
|
563
|
+
--target-size-minimum: 24px; /* WCAG AA */
|
|
564
|
+
--target-size-comfortable: 44px; /* WCAG AAA / Apple HIG */
|
|
565
|
+
--target-size-android: 48px; /* Material Design */
|
|
566
|
+
|
|
567
|
+
/* Spacing for target separation */
|
|
568
|
+
--target-spacing-minimum: 8px;
|
|
569
|
+
|
|
570
|
+
/* Typography minimums */
|
|
571
|
+
--font-size-minimum: 16px; /* prevents iOS zoom on focus */
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### CMS Accessibility Requirements
|
|
576
|
+
|
|
577
|
+
- WYSIWYG editors must produce semantic HTML (headings, lists, tables — not just styled divs)
|
|
578
|
+
- Image upload must require alt text (make it mandatory in the CMS)
|
|
579
|
+
- Link creation must prompt for descriptive link text
|
|
580
|
+
- Content preview should include accessibility warnings (missing alt, heading skips)
|
|
581
|
+
- Provide accessibility guidance inline for content editors
|
|
582
|
+
|
|
583
|
+
### PDF Accessibility
|
|
584
|
+
|
|
585
|
+
- Start from an accessible source document (Word, InDesign) with proper heading structure
|
|
586
|
+
- Tag the PDF with correct reading order, headings, lists, tables, and alt text
|
|
587
|
+
- Set the document title and language in PDF metadata
|
|
588
|
+
- Ensure form fields are labeled and tab order is correct
|
|
589
|
+
- Conform to PDF/UA (ISO 14289-1) standard
|
|
590
|
+
- Test with PAC (PDF Accessibility Checker) and screen readers
|
|
591
|
+
|
|
592
|
+
### Email Accessibility
|
|
593
|
+
|
|
594
|
+
- Use semantic HTML tables for layout (email clients have limited CSS support)
|
|
595
|
+
- Include `role="presentation"` on layout tables
|
|
596
|
+
- Use `alt` text on all images — many email clients block images by default
|
|
597
|
+
- Set `lang` attribute on the `<html>` element
|
|
598
|
+
- Use sufficient contrast (4.5:1 for text)
|
|
599
|
+
- Keep subject lines clear and descriptive
|
|
600
|
+
- Provide a plain-text alternative for every HTML email
|
|
601
|
+
- Test with Litmus or Email on Acid accessibility features
|
|
602
|
+
|
|
603
|
+
---
|
|
604
|
+
|
|
605
|
+
## DevOps & Deployment
|
|
606
|
+
|
|
607
|
+
### Accessibility CI/CD Gates
|
|
608
|
+
|
|
609
|
+
```yaml
|
|
610
|
+
# GitHub Actions example
|
|
611
|
+
accessibility-check:
|
|
612
|
+
runs-on: ubuntu-latest
|
|
613
|
+
steps:
|
|
614
|
+
- uses: actions/checkout@v4
|
|
615
|
+
- run: npm ci
|
|
616
|
+
- run: npx playwright install --with-deps
|
|
617
|
+
- run: npm run build && npm run start &
|
|
618
|
+
- name: Run accessibility tests
|
|
619
|
+
run: npx playwright test --project=accessibility
|
|
620
|
+
- name: Upload a11y report
|
|
621
|
+
if: always()
|
|
622
|
+
uses: actions/upload-artifact@v4
|
|
623
|
+
with:
|
|
624
|
+
name: accessibility-report
|
|
625
|
+
path: test-results/accessibility/
|
|
626
|
+
```
|
|
627
|
+
|
|
628
|
+
**Gate strategy:**
|
|
629
|
+
- PR gate: zero new axe violations on changed pages (block merge)
|
|
630
|
+
- Nightly gate: full-site scan with trend tracking (alert on regression)
|
|
631
|
+
- Release gate: manual screen reader audit sign-off for major releases
|
|
632
|
+
|
|
633
|
+
### Automated Accessibility Reporting
|
|
634
|
+
|
|
635
|
+
- Generate axe-core JSON reports and convert to HTML dashboards
|
|
636
|
+
- Track violation counts per page, per category, per severity over time
|
|
637
|
+
- Integrate with project management (create Jira/Linear tickets for violations)
|
|
638
|
+
- Use Pa11y Dashboard or Accessibility Insights for ongoing monitoring
|
|
639
|
+
|
|
640
|
+
### Accessibility Monitoring in Production
|
|
641
|
+
|
|
642
|
+
- Synthetic monitoring: scheduled axe scans against production URLs
|
|
643
|
+
- Real User Monitoring (RUM): track keyboard usage patterns, zoom levels, reduced-motion preferences, screen reader detection (with user consent)
|
|
644
|
+
- Error tracking: monitor for JavaScript errors that could break AT compatibility
|
|
645
|
+
- Performance monitoring: track Time to Interactive — slow pages disproportionately affect AT users
|
|
646
|
+
|
|
647
|
+
### Legal Compliance Tracking
|
|
648
|
+
|
|
649
|
+
| Law | Jurisdiction | Standard | Deadline | Penalty |
|
|
650
|
+
|---|---|---|---|---|
|
|
651
|
+
| ADA Title III | USA (private) | WCAG 2.1 AA (case law) | Ongoing | Lawsuits, settlements ($10K-$500K+) |
|
|
652
|
+
| ADA Title II | USA (government) | WCAG 2.1 AA | 2026 | Federal enforcement |
|
|
653
|
+
| Section 508 | USA (federal) | WCAG 2.0 AA (EN 301 549) | Ongoing | Contract loss, complaints |
|
|
654
|
+
| EAA | EU | EN 301 549 (WCAG 2.1 AA) | June 2025 | Up to 500K EUR per member state |
|
|
655
|
+
| AODA | Ontario, Canada | WCAG 2.0 AA | Ongoing | Up to $100K CAD/day |
|
|
656
|
+
| DDA | UK | WCAG 2.1 AA (guidance) | Ongoing | Litigation, enforcement |
|
|
657
|
+
|
|
658
|
+
Track compliance status per product/property. Maintain a VPAT (Voluntary Product Accessibility Template) or ACR (Accessibility Conformance Report) for enterprise sales.
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
## Decision Trees
|
|
663
|
+
|
|
664
|
+
### Which WCAG Level to Target?
|
|
665
|
+
|
|
666
|
+
```
|
|
667
|
+
Is your product used by a government agency?
|
|
668
|
+
|-- Yes --> Target AA minimum (Section 508 / EAA mandate)
|
|
669
|
+
| Consider AAA for specific criteria (target size, contrast)
|
|
670
|
+
|-- No
|
|
671
|
+
|-- Do you sell to enterprise / government?
|
|
672
|
+
| |-- Yes --> Target AA (required for procurement)
|
|
673
|
+
| |-- No
|
|
674
|
+
| |-- Do you operate in the EU or have EU customers?
|
|
675
|
+
| | |-- Yes --> Target AA (EAA compliance, June 2025)
|
|
676
|
+
| | |-- No
|
|
677
|
+
| | |-- Is accessibility part of your brand values?
|
|
678
|
+
| | | |-- Yes --> Target AA, adopt select AAA criteria
|
|
679
|
+
| | | |-- No --> Target AA anyway
|
|
680
|
+
| | | (ADA litigation risk + it is the right thing)
|
|
681
|
+
|
|
682
|
+
Bottom line: Target WCAG 2.2 AA. Always.
|
|
683
|
+
```
|
|
684
|
+
|
|
685
|
+
### Custom Component vs Native HTML Element?
|
|
686
|
+
|
|
687
|
+
```
|
|
688
|
+
Does a native HTML element exist for this pattern?
|
|
689
|
+
|-- Yes (button, a, input, select, details, dialog)
|
|
690
|
+
| |-- Does the native element meet your UX requirements?
|
|
691
|
+
| | |-- Yes --> Use the native element. Style it with CSS.
|
|
692
|
+
| | |-- No
|
|
693
|
+
| | |-- Can you enhance the native element with CSS/JS?
|
|
694
|
+
| | | |-- Yes --> Enhance the native element
|
|
695
|
+
| | | |-- No --> Use an accessible component library
|
|
696
|
+
| | | (Radix UI, React Aria, Headless UI)
|
|
697
|
+
|-- No (tabs, combobox, tree view, date picker)
|
|
698
|
+
|-- Does an accessible component library have this pattern?
|
|
699
|
+
| |-- Yes --> Use the library component
|
|
700
|
+
| |-- No --> Build custom following WAI-ARIA APG exactly
|
|
701
|
+
| - Implement all keyboard interactions from the APG
|
|
702
|
+
| - Test with 3+ screen readers
|
|
703
|
+
| - Test with keyboard only
|
|
704
|
+
| - Get review from accessibility specialist
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
### When to Use ARIA vs Semantic HTML?
|
|
708
|
+
|
|
709
|
+
```
|
|
710
|
+
Can a native HTML element convey the semantics you need?
|
|
711
|
+
|-- Yes --> Use the native element. Do NOT add ARIA.
|
|
712
|
+
| Example: <button> not <div role="button">
|
|
713
|
+
|-- No
|
|
714
|
+
|-- Are you building a custom interactive widget?
|
|
715
|
+
| |-- Yes --> ARIA is required
|
|
716
|
+
| | - Add role (e.g., role="tablist", role="tab")
|
|
717
|
+
| | - Add states (aria-selected, aria-expanded)
|
|
718
|
+
| | - Add properties (aria-controls, aria-labelledby)
|
|
719
|
+
| | - Implement ALL keyboard interactions from APG
|
|
720
|
+
| |-- No
|
|
721
|
+
| |-- Do you need to communicate dynamic state?
|
|
722
|
+
| | |-- Yes --> Use ARIA states/properties
|
|
723
|
+
| | | - aria-live for dynamic announcements
|
|
724
|
+
| | | - aria-expanded for disclosure state
|
|
725
|
+
| | | - aria-busy for loading state
|
|
726
|
+
| | |-- No
|
|
727
|
+
| | |-- Do you need to add a label or description?
|
|
728
|
+
| | | |-- Yes --> Use aria-label or aria-describedby
|
|
729
|
+
| | | | (only on elements with interactive roles)
|
|
730
|
+
| | | |-- No --> You probably do not need ARIA
|
|
731
|
+
|
|
732
|
+
Remember: ARIA changes what screen readers announce.
|
|
733
|
+
It does NOT change behavior. You must still implement
|
|
734
|
+
keyboard interaction and focus management yourself.
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
---
|
|
738
|
+
|
|
739
|
+
## Code Examples
|
|
740
|
+
|
|
741
|
+
### 1. Accessible Skip Link
|
|
742
|
+
|
|
743
|
+
```html
|
|
744
|
+
<!-- First element in <body> -->
|
|
745
|
+
<a href="#main-content" class="skip-link">
|
|
746
|
+
Skip to main content
|
|
747
|
+
</a>
|
|
748
|
+
|
|
749
|
+
<header><!-- site header, navigation --></header>
|
|
750
|
+
|
|
751
|
+
<main id="main-content" tabindex="-1">
|
|
752
|
+
<h1>Page Title</h1>
|
|
753
|
+
<!-- page content -->
|
|
754
|
+
</main>
|
|
755
|
+
|
|
756
|
+
<style>
|
|
757
|
+
.skip-link {
|
|
758
|
+
position: absolute;
|
|
759
|
+
top: -40px;
|
|
760
|
+
left: 0;
|
|
761
|
+
padding: 8px 16px;
|
|
762
|
+
background: #005fcc;
|
|
763
|
+
color: #ffffff;
|
|
764
|
+
font-weight: bold;
|
|
765
|
+
z-index: 1000;
|
|
766
|
+
transition: top 0.2s;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
.skip-link:focus {
|
|
770
|
+
top: 0;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
@media (prefers-reduced-motion: reduce) {
|
|
774
|
+
.skip-link { transition: none; }
|
|
775
|
+
}
|
|
776
|
+
</style>
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### 2. Accessible Form With Error Handling
|
|
780
|
+
|
|
781
|
+
```html
|
|
782
|
+
<form novalidate aria-labelledby="form-title">
|
|
783
|
+
<h2 id="form-title">Create Account</h2>
|
|
784
|
+
|
|
785
|
+
<!-- Error summary (appears on submit) -->
|
|
786
|
+
<div role="alert" id="error-summary" hidden>
|
|
787
|
+
<h3>Please fix the following errors:</h3>
|
|
788
|
+
<ul>
|
|
789
|
+
<li><a href="#email">Email address is required</a></li>
|
|
790
|
+
<li><a href="#password">Password must be at least 8 characters</a></li>
|
|
791
|
+
</ul>
|
|
792
|
+
</div>
|
|
793
|
+
|
|
794
|
+
<div>
|
|
795
|
+
<label for="email">
|
|
796
|
+
Email address <span aria-hidden="true">*</span>
|
|
797
|
+
<span class="visually-hidden">(required)</span>
|
|
798
|
+
</label>
|
|
799
|
+
<input
|
|
800
|
+
type="email"
|
|
801
|
+
id="email"
|
|
802
|
+
name="email"
|
|
803
|
+
required
|
|
804
|
+
aria-required="true"
|
|
805
|
+
aria-invalid="false"
|
|
806
|
+
aria-describedby="email-error"
|
|
807
|
+
autocomplete="email"
|
|
808
|
+
/>
|
|
809
|
+
<span id="email-error" class="error" hidden>
|
|
810
|
+
Enter a valid email address
|
|
811
|
+
</span>
|
|
812
|
+
</div>
|
|
813
|
+
|
|
814
|
+
<div>
|
|
815
|
+
<label for="password">
|
|
816
|
+
Password <span aria-hidden="true">*</span>
|
|
817
|
+
<span class="visually-hidden">(required)</span>
|
|
818
|
+
</label>
|
|
819
|
+
<input
|
|
820
|
+
type="password"
|
|
821
|
+
id="password"
|
|
822
|
+
name="password"
|
|
823
|
+
required
|
|
824
|
+
aria-required="true"
|
|
825
|
+
aria-invalid="false"
|
|
826
|
+
aria-describedby="password-hint password-error"
|
|
827
|
+
autocomplete="new-password"
|
|
828
|
+
/>
|
|
829
|
+
<span id="password-hint" class="hint">
|
|
830
|
+
Must be at least 8 characters with one number
|
|
831
|
+
</span>
|
|
832
|
+
<span id="password-error" class="error" hidden>
|
|
833
|
+
Password must be at least 8 characters
|
|
834
|
+
</span>
|
|
835
|
+
</div>
|
|
836
|
+
|
|
837
|
+
<button type="submit">Create Account</button>
|
|
838
|
+
</form>
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
### 3. Accessible Modal Dialog
|
|
842
|
+
|
|
843
|
+
```html
|
|
844
|
+
<dialog id="confirm-dialog" aria-labelledby="dialog-title"
|
|
845
|
+
aria-describedby="dialog-desc">
|
|
846
|
+
<h2 id="dialog-title">Confirm Deletion</h2>
|
|
847
|
+
<p id="dialog-desc">
|
|
848
|
+
Are you sure you want to delete this item?
|
|
849
|
+
This action cannot be undone.
|
|
850
|
+
</p>
|
|
851
|
+
<div class="dialog-actions">
|
|
852
|
+
<button id="cancel-btn" type="button">Cancel</button>
|
|
853
|
+
<button id="confirm-btn" type="button" class="destructive">
|
|
854
|
+
Delete
|
|
855
|
+
</button>
|
|
856
|
+
</div>
|
|
857
|
+
</dialog>
|
|
858
|
+
|
|
859
|
+
<button id="open-dialog" type="button">Delete Item</button>
|
|
860
|
+
|
|
861
|
+
<script>
|
|
862
|
+
const dialog = document.getElementById('confirm-dialog');
|
|
863
|
+
const openBtn = document.getElementById('open-dialog');
|
|
864
|
+
const cancelBtn = document.getElementById('cancel-btn');
|
|
865
|
+
const confirmBtn = document.getElementById('confirm-btn');
|
|
866
|
+
|
|
867
|
+
// Native <dialog> with showModal(): traps focus, handles Escape
|
|
868
|
+
openBtn.addEventListener('click', () => {
|
|
869
|
+
dialog.showModal();
|
|
870
|
+
cancelBtn.focus(); // Focus the safe action first
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
cancelBtn.addEventListener('click', () => {
|
|
874
|
+
dialog.close();
|
|
875
|
+
openBtn.focus(); // Return focus to trigger
|
|
876
|
+
});
|
|
877
|
+
|
|
878
|
+
confirmBtn.addEventListener('click', () => {
|
|
879
|
+
performDeletion();
|
|
880
|
+
dialog.close();
|
|
881
|
+
openBtn.focus(); // Return focus to trigger
|
|
882
|
+
});
|
|
883
|
+
</script>
|
|
884
|
+
```
|
|
885
|
+
|
|
886
|
+
### 4. Live Region for Dynamic Content
|
|
887
|
+
|
|
888
|
+
```html
|
|
889
|
+
<!-- Live region container: must exist in DOM before content changes -->
|
|
890
|
+
<div id="search-status" role="status" aria-live="polite"
|
|
891
|
+
class="visually-hidden"></div>
|
|
892
|
+
|
|
893
|
+
<input type="search" aria-label="Search products"
|
|
894
|
+
aria-describedby="search-status" />
|
|
895
|
+
|
|
896
|
+
<div id="results" aria-busy="false">
|
|
897
|
+
<!-- Search results rendered here -->
|
|
898
|
+
</div>
|
|
899
|
+
|
|
900
|
+
<script>
|
|
901
|
+
async function handleSearch(query) {
|
|
902
|
+
const resultsEl = document.getElementById('results');
|
|
903
|
+
const statusEl = document.getElementById('search-status');
|
|
904
|
+
|
|
905
|
+
// Announce loading state
|
|
906
|
+
resultsEl.setAttribute('aria-busy', 'true');
|
|
907
|
+
statusEl.textContent = 'Searching...';
|
|
908
|
+
|
|
909
|
+
const data = await fetchResults(query);
|
|
910
|
+
|
|
911
|
+
// Render results using safe DOM methods (not innerHTML)
|
|
912
|
+
resultsEl.replaceChildren();
|
|
913
|
+
data.forEach(item => {
|
|
914
|
+
const el = document.createElement('article');
|
|
915
|
+
el.textContent = item.title;
|
|
916
|
+
resultsEl.appendChild(el);
|
|
917
|
+
});
|
|
918
|
+
|
|
919
|
+
resultsEl.setAttribute('aria-busy', 'false');
|
|
920
|
+
|
|
921
|
+
// Announce result count
|
|
922
|
+
statusEl.textContent =
|
|
923
|
+
data.length + ' results found for "' + query + '"';
|
|
924
|
+
}
|
|
925
|
+
</script>
|
|
926
|
+
```
|
|
927
|
+
|
|
928
|
+
### 5. Accessible Navigation With Current Page
|
|
929
|
+
|
|
930
|
+
```html
|
|
931
|
+
<nav aria-label="Main navigation">
|
|
932
|
+
<ul role="list">
|
|
933
|
+
<li><a href="/" aria-current="page">Home</a></li>
|
|
934
|
+
<li><a href="/products">Products</a></li>
|
|
935
|
+
<li><a href="/about">About</a></li>
|
|
936
|
+
<li><a href="/contact">Contact</a></li>
|
|
937
|
+
</ul>
|
|
938
|
+
</nav>
|
|
939
|
+
|
|
940
|
+
<!-- Mobile menu toggle -->
|
|
941
|
+
<button aria-expanded="false" aria-controls="mobile-menu"
|
|
942
|
+
aria-label="Menu">
|
|
943
|
+
<svg aria-hidden="true" focusable="false">
|
|
944
|
+
<!-- hamburger icon -->
|
|
945
|
+
</svg>
|
|
946
|
+
</button>
|
|
947
|
+
|
|
948
|
+
<nav id="mobile-menu" aria-label="Main navigation" hidden>
|
|
949
|
+
<!-- Same links as above -->
|
|
950
|
+
</nav>
|
|
951
|
+
|
|
952
|
+
<script>
|
|
953
|
+
const menuBtn = document.querySelector('[aria-controls="mobile-menu"]');
|
|
954
|
+
const mobileMenu = document.getElementById('mobile-menu');
|
|
955
|
+
|
|
956
|
+
menuBtn.addEventListener('click', () => {
|
|
957
|
+
const isOpen = menuBtn.getAttribute('aria-expanded') === 'true';
|
|
958
|
+
menuBtn.setAttribute('aria-expanded', String(!isOpen));
|
|
959
|
+
mobileMenu.hidden = isOpen;
|
|
960
|
+
|
|
961
|
+
if (!isOpen) {
|
|
962
|
+
mobileMenu.querySelector('a').focus();
|
|
963
|
+
}
|
|
964
|
+
});
|
|
965
|
+
</script>
|
|
966
|
+
|
|
967
|
+
<!-- Visually hidden utility class -->
|
|
968
|
+
<style>
|
|
969
|
+
.visually-hidden {
|
|
970
|
+
position: absolute;
|
|
971
|
+
width: 1px;
|
|
972
|
+
height: 1px;
|
|
973
|
+
padding: 0;
|
|
974
|
+
margin: -1px;
|
|
975
|
+
overflow: hidden;
|
|
976
|
+
clip: rect(0, 0, 0, 0);
|
|
977
|
+
white-space: nowrap;
|
|
978
|
+
border: 0;
|
|
979
|
+
}
|
|
980
|
+
</style>
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
---
|
|
984
|
+
|
|
985
|
+
*Researched: 2026-03-07 | Sources: [W3C WCAG 2.2](https://www.w3.org/TR/WCAG22/), [W3C WAI-ARIA APG](https://www.w3.org/WAI/ARIA/apg/), [W3C What's New in WCAG 2.2](https://www.w3.org/WAI/standards-guidelines/wcag/new-in-22/), [WebAIM Million 2025](https://webaim.org/projects/million/), [MDN ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA), [web.dev ARIA and HTML](https://web.dev/learn/accessibility/aria-html), [Playwright Accessibility Testing](https://playwright.dev/docs/accessibility-testing), [Deque axe-core](https://www.deque.com/axe/axe-core/), [Level Access Section 508 Guide](https://www.levelaccess.com/compliance-overview/section-508-compliance/), [Level Access EAA Guide](https://www.levelaccess.com/compliance-overview/european-accessibility-act-eaa/), [Smashing Magazine CAPTCHA Accessibility](https://www.smashingmagazine.com/2025/11/accessibility-problem-authentication-methods-captcha/), [LogRocket Headless UI Alternatives](https://blog.logrocket.com/headless-ui-alternatives/), [MDN prefers-reduced-motion](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/At-rules/@media/prefers-reduced-motion), [W3C Modal Dialog Pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/)*
|