[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6CWDJ8T8X8Q6QBWVC474B7F":3,"skill-same:01M6CWDJ8T8X8Q6QBWVC474B7F":56},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":22,"publishedAt":29,"linkOnly":30,"markdownContent":31,"markdownBody":32,"frontMatter":33,"refName":36,"commitSha":37,"skillDirectory":5,"forksCount":38,"repositoryHtmlUrl":39,"repositoryHomepageUrl":6,"ownerHtmlUrl":40,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":41,"install":42,"resources":55},"01M6CWDJ8T8X8Q6QBWVC474B7F","accessibility",null,"Web accessibility (a11y) best practices and implementation","ffsshhttiikk\u002Fopencode-agents-skills","ffsshhttiikk","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F226346827?v=4","01M6CWD9RR3Y7VRQX3MXYC8FYH","01M6CWD9WVPYAZW0J82G1VKGHY",3,"MIT","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Faccessibility\u002FSKILL.md",[17],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[5,23,24,25,26,27,28],"frontend","web","best practices","web accessibility","opencode","implementation","2026-11-10 10:12:30",false,"---\nname: accessibility\ndescription: Web accessibility (a11y) best practices and implementation\nlicense: MIT\ncompatibility: opencode\nmetadata:\n  audience: developers\n  category: frontend\n---\n## What I do\n- Implement WCAG guidelines\n- Create accessible HTML structure\n- Handle keyboard navigation\n- Implement ARIA attributes\n- Ensure proper color contrast\n- Support screen readers\n- Design for various disabilities\n- Test accessibility\n\n## When to use me\nWhen creating accessible user interfaces or reviewing for accessibility.\n\n## WCAG Guidelines Summary\n```\nWCAG 2.1 Principles:\n1. Perceivable\n   - Text alternatives for images\n   - Captions for audio\n   - Adaptable layouts\n   - Distinguishable (color, contrast)\n\n2. Operable\n   - Keyboard accessible\n   - Enough time for interactions\n   - No seizure-inducing content\n   - Navigable (headings, focus order)\n\n3. Understandable\n   - Readable and predictable\n   - Input assistance\n\n4. Robust\n   - Compatible with current and future user agents\n\nConformance Levels:\n- A: Minimum (required)\n- AA: Recommended (target)\n- AAA: Highest (exceptional cases)\n```\n\n## Semantic HTML\n```html\n\u003C!-- BAD: Non-semantic markup -->\n\u003Cdiv class=\"header\">\n  \u003Cdiv class=\"logo\">\u003C\u002Fdiv>\n  \u003Cdiv class=\"nav\">\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"main\">\n  \u003Cdiv class=\"article\">Content\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"footer\">\u003C\u002Fdiv>\n\n\u003C!-- GOOD: Semantic HTML -->\n\u003Cheader>\n  \u003Ca href=\"\u002F\" aria-label=\"Homepage\">\n    \u003Cimg src=\"logo.png\" alt=\"Company Name\">\n  \u003C\u002Fa>\n  \u003Cnav aria-label=\"Main navigation\">\n    \u003Cul>\n      \u003Cli>\u003Ca href=\"\u002Fproducts\">Products\u003C\u002Fa>\u003C\u002Fli>\n      \u003Cli>\u003Ca href=\"\u002Fabout\">About\u003C\u002Fa>\u003C\u002Fli>\n    \u003C\u002Ful>\n  \u003C\u002Fnav>\n\u003C\u002Fheader>\n\u003Cmain>\n  \u003Carticle>\n    \u003Ch1>Page Title\u003C\u002Fh1>\n    \u003Cp>Main content goes here...\u003C\u002Fp>\n  \u003C\u002Farticle>\n\u003C\u002Fmain>\n\u003Cfooter>\n  \u003Cp>&copy; 2024 Company\u003C\u002Fp>\n\u003C\u002Ffooter>\n```\n\n## Keyboard Navigation\n```html\n\u003C!-- BAD: Non-interactive elements -->\n\u003Cdiv class=\"button\" onclick=\"save()\">Save\u003C\u002Fdiv>\n\n\u003C!-- GOOD: Proper interactive elements -->\n\u003Cbutton type=\"button\" onclick=\"save()\">Save\u003C\u002Fbutton>\n\n\n\u003C!-- Skip link for keyboard users -->\n\u003Chead>\n  \u003Cstyle>\n    .skip-link {\n      position: absolute;\n      top: -40px;\n      left: 0;\n      background: #000;\n      color: #fff;\n      padding: 8px;\n      z-index: 100;\n    }\n    \n    .skip-link:focus {\n      top: 0;\n    }\n  \u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Ca href=\"#main-content\" class=\"skip-link\">Skip to main content\u003C\u002Fa>\n  \n  \u003Cnav>...\u003C\u002Fnav>\n  \u003Cmain id=\"main-content\">\n    \u003Ch1>Main Content\u003C\u002Fh1>\n  \u003C\u002Fmain>\n\u003C\u002Fbody>\n\n\n\u003C!-- Focus management -->\n\u003Cbutton\n  type=\"button\"\n  onclick=\"openModal()\"\n  aria-haspopup=\"dialog\"\n  aria-expanded=\"false\"\n>\n  Open Modal\n\u003C\u002Fbutton>\n\n\u003Cdiv\n  role=\"dialog\"\n  aria-modal=\"true\"\n  aria-labelledby=\"modal-title\"\n  hidden\n>\n  \u003Ch2 id=\"modal-title\">Modal Title\u003C\u002Fh2>\n  \u003Cbutton\n    type=\"button\"\n    onclick=\"closeModal()\"\n    aria-label=\"Close modal\"\n  >\n    ×\n  \u003C\u002Fbutton>\n  \u003Cdiv>Modal content...\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n```\n\n## ARIA Attributes\n```html\n\u003C!-- ARIA roles for custom components -->\n\u003Cdiv role=\"button\" tabindex=\"0\" aria-pressed=\"false\">\n  Toggle Favorite\n\u003C\u002Fdiv>\n\n\u003C!-- Live regions for dynamic content -->\n\u003Cdiv\n  role=\"status\"\n  aria-live=\"polite\"\n  aria-atomic=\"true\"\n>\n  Changes will be announced\n\u003C\u002Fdiv>\n\n\u003C!-- Form validation -->\n\u003Cform>\n  \u003Clabel for=\"email\">Email\u003C\u002Flabel>\n  \u003Cinput\n    type=\"email\"\n    id=\"email\"\n    name=\"email\"\n    aria-describedby=\"email-hint email-error\"\n    aria-invalid=\"false\"\n  >\n  \u003Cp id=\"email-hint\">We'll never share your email\u003C\u002Fp>\n  \u003Cp id=\"email-error\" hidden>\n    Please enter a valid email address\n  \u003C\u002Fp>\n\u003C\u002Fform>\n```\n\n## Color Contrast\n```css\n\u002F* Minimum contrast ratios (WCAG AA) *\u002F\n\u002F* Normal text: 4.5:1 *\u002F\n\u002F* Large text (18pt+ or 14pt bold): 3:1 *\u002F\n\u002F* UI components: 3:1 *\u002F\n\n.good-contrast {\n  \u002F* Passes AAA (7:1) *\u002F\n  color: #1a1a1a;\n  background-color: #ffffff;\n}\n\n.acceptable-contrast {\n  \u002F* Passes AA (4.5:1) *\u002F\n  color: #333333;\n  background-color: #ffffff;\n}\n\n.large-text {\n  \u002F* Passes AA for large text (3:1) *\u002F\n  color: #555555;\n  background-color: #ffffff;\n  font-size: 18px;\n}\n\n\u002F* Don't rely on color alone *\u002F\n.status {\n  padding: 4px 8px;\n  border-radius: 4px;\n}\n\n.status.success {\n  background-color: #d4edda;\n  color: #155724;\n}\n\n.status.error {\n  background-color: #f8d7da;\n  color: #721c24;\n}\n\n\u002F* Add icon to reinforce color meaning *\u002F\n.status.success::before {\n  content: \"✓ \";\n}\n\n.status.error::before {\n  content: \"✕ \";\n}\n```\n\n## Screen Reader Support\n```html\n\u003C!-- Images must have alt text -->\n\u003Cimg src=\"chart.png\" alt=\"Sales chart showing 25% growth in Q4\">\n\n\u003C!-- Decorative images -->\n\u003Cimg src=\"decoration.png\" alt=\"\" role=\"presentation\">\n\n\u003C!-- Complex images need detailed descriptions -->\n\u003Cimg\n  src=\"infographic.png\"\n  alt=\"Infographic: Step 1 Research, Step 2 Design, Step 3 Development\"\n>\n\u003Cdetails>\n  \u003Csummary>View detailed description\u003C\u002Fsummary>\n  \u003Cp>Full description of the infographic content...\u003C\u002Fp>\n\u003C\u002Fdetails>\n\n\n\u003C!-- Tables need proper structure -->\n\u003Ctable>\n  \u003Ccaption>Quarterly Sales Report\u003C\u002Fcaption>\n  \u003Cthead>\n    \u003Ctr>\n      \u003Cth scope=\"col\">Quarter\u003C\u002Fth>\n      \u003Cth scope=\"col\">Revenue\u003C\u002Fth>\n      \u003Cth scope=\"col\">Expenses\u003C\u002Fth>\n    \u003C\u002Ftr>\n  \u003C\u002Fthead>\n  \u003Ctbody>\n    \u003Ctr>\n      \u003Cth scope=\"row\">Q1\u003C\u002Fth>\n      \u003Ctd>$100,000\u003C\u002Ftd>\n      \u003Ctd>$80,000\u003C\u002Ftd>\n    \u003C\u002Ftr>\n  \u003C\u002Ftbody>\n\u003C\u002Ftable>\n```\n\n## Form Accessibility\n```html\n\u003Cform>\n  \u003Cfieldset>\n    \u003Clegend>Contact Information\u003C\u002Flegend>\n    \n    \u003Cdiv class=\"form-group\">\n      \u003Clabel for=\"name\">Full Name \u003Cspan aria-hidden=\"true\">*\u003C\u002Fspan>\u003C\u002Flabel>\n      \u003Cinput\n        type=\"text\"\n        id=\"name\"\n        name=\"name\"\n        required\n        aria-required=\"true\"\n        autocomplete=\"name\"\n      >\n    \u003C\u002Fdiv>\n    \n    \u003Cdiv class=\"form-group\">\n      \u003Clabel for=\"email\">Email Address\u003C\u002Flabel>\n      \u003Cinput\n        type=\"email\"\n        id=\"email\"\n        name=\"email\"\n        required\n        aria-required=\"true\"\n        autocomplete=\"email\"\n      >\n    \u003C\u002Fdiv>\n    \n    \u003Cdiv class=\"form-group\">\n      \u003Clabel for=\"phone\">Phone Number\u003C\u002Flabel>\n      \u003Cinput\n        type=\"tel\"\n        id=\"phone\"\n        name=\"phone\"\n        autocomplete=\"tel\"\n        pattern=\"[0-9+\\-\\(\\) ]*\"\n        aria-describedby=\"phone-hint\"\n      >\n      \u003Cp id=\"phone-hint\">Include country code (e.g., +1)\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  \u003C\u002Ffieldset>\n  \n  \u003Cbutton type=\"submit\">Submit\u003C\u002Fbutton>\n\u003C\u002Fform>\n\n\n\u003C!-- Error handling -->\n\u003Cform>\n  \u003Cdiv class=\"form-group has-error\">\n    \u003Clabel for=\"email\">Email\u003C\u002Flabel>\n    \u003Cinput\n      type=\"email\"\n      id=\"email\"\n      name=\"email\"\n      aria-invalid=\"true\"\n      aria-describedby=\"email-error\"\n    >\n    \u003Cp id=\"email-error\" role=\"alert\">\n      Please enter a valid email address\n    \u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Fform>\n```\n\n## Testing Accessibility\n```python\n# Automated accessibility testing with axe-core\nimport pytest\n\n\nclass TestAccessibility:\n    def test_homepage_accessibility(self, page):\n        \"\"\"Test homepage with axe-core.\"\"\"\n        page.goto('\u002F')\n        \n        # Run axe-core\n        violations = page.evaluate('''() => {\n          const axe = window.axe;\n          return axe.run(document, {\n            runOnly: {\n              type: 'tag',\n              values: ['wcag2a', 'wcag2aa']\n            }\n          });\n        }''')\n        \n        assert len(violations['violations']) == 0, \\\n            f\"Accessibility violations: {violations['violations']}\"\n    \n    def test_keyboard_navigation(self, page):\n        \"\"\"Test keyboard navigation works.\"\"\"\n        page.goto('\u002F')\n        \n        # Press Tab multiple times\n        page.keyboard.press('Tab')\n        focused = page.evaluate('document.activeElement.tagName')\n        \n        # First focusable element should be first link\n        assert focused in ['A', 'BUTTON', 'INPUT']\n    \n    def test_color_contrast(self, page):\n        \"\"\"Test color contrast requirements.\"\"\"\n        page.goto('\u002F')\n        \n        violations = page.evaluate('''() => {\n          const axe = window.axe;\n          const results = axe.run(document, {\n            checks: ['color-contrast']\n          });\n          return results.violations;\n        }''')\n        \n        assert len(violations) == 0\n\n\n# Manual testing checklist\nACCESSIBILITY_CHECKLIST = \"\"\"\n[] All images have alt text\n[] Form inputs have associated labels\n[] Headings follow proper hierarchy (h1 > h2 > h3)\n[] Color is not the only means of conveying information\n[] Focus order is logical\n[] Keyboard navigation works throughout\n[] Skip links are present\n[] ARIA landmarks are used correctly\n[] Form errors are announced\n[] Error messages are specific\n[] Page has language attribute\n[] Content is readable at 200% zoom\n[] No keyboard traps\n[] Focus is not lost when modal closes\n\"\"\"\n```\n","## What I do\n- Implement WCAG guidelines\n- Create accessible HTML structure\n- Handle keyboard navigation\n- Implement ARIA attributes\n- Ensure proper color contrast\n- Support screen readers\n- Design for various disabilities\n- Test accessibility\n\n## When to use me\nWhen creating accessible user interfaces or reviewing for accessibility.\n\n## WCAG Guidelines Summary\n```\nWCAG 2.1 Principles:\n1. Perceivable\n   - Text alternatives for images\n   - Captions for audio\n   - Adaptable layouts\n   - Distinguishable (color, contrast)\n\n2. Operable\n   - Keyboard accessible\n   - Enough time for interactions\n   - No seizure-inducing content\n   - Navigable (headings, focus order)\n\n3. Understandable\n   - Readable and predictable\n   - Input assistance\n\n4. Robust\n   - Compatible with current and future user agents\n\nConformance Levels:\n- A: Minimum (required)\n- AA: Recommended (target)\n- AAA: Highest (exceptional cases)\n```\n\n## Semantic HTML\n```html\n\u003C!-- BAD: Non-semantic markup -->\n\u003Cdiv class=\"header\">\n  \u003Cdiv class=\"logo\">\u003C\u002Fdiv>\n  \u003Cdiv class=\"nav\">\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"main\">\n  \u003Cdiv class=\"article\">Content\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003Cdiv class=\"footer\">\u003C\u002Fdiv>\n\n\u003C!-- GOOD: Semantic HTML -->\n\u003Cheader>\n  \u003Ca href=\"\u002F\" aria-label=\"Homepage\">\n    \u003Cimg src=\"logo.png\" alt=\"Company Name\">\n  \u003C\u002Fa>\n  \u003Cnav aria-label=\"Main navigation\">\n    \u003Cul>\n      \u003Cli>\u003Ca href=\"\u002Fproducts\">Products\u003C\u002Fa>\u003C\u002Fli>\n      \u003Cli>\u003Ca href=\"\u002Fabout\">About\u003C\u002Fa>\u003C\u002Fli>\n    \u003C\u002Ful>\n  \u003C\u002Fnav>\n\u003C\u002Fheader>\n\u003Cmain>\n  \u003Carticle>\n    \u003Ch1>Page Title\u003C\u002Fh1>\n    \u003Cp>Main content goes here...\u003C\u002Fp>\n  \u003C\u002Farticle>\n\u003C\u002Fmain>\n\u003Cfooter>\n  \u003Cp>&copy; 2024 Company\u003C\u002Fp>\n\u003C\u002Ffooter>\n```\n\n## Keyboard Navigation\n```html\n\u003C!-- BAD: Non-interactive elements -->\n\u003Cdiv class=\"button\" onclick=\"save()\">Save\u003C\u002Fdiv>\n\n\u003C!-- GOOD: Proper interactive elements -->\n\u003Cbutton type=\"button\" onclick=\"save()\">Save\u003C\u002Fbutton>\n\n\n\u003C!-- Skip link for keyboard users -->\n\u003Chead>\n  \u003Cstyle>\n    .skip-link {\n      position: absolute;\n      top: -40px;\n      left: 0;\n      background: #000;\n      color: #fff;\n      padding: 8px;\n      z-index: 100;\n    }\n    \n    .skip-link:focus {\n      top: 0;\n    }\n  \u003C\u002Fstyle>\n\u003C\u002Fhead>\n\u003Cbody>\n  \u003Ca href=\"#main-content\" class=\"skip-link\">Skip to main content\u003C\u002Fa>\n  \n  \u003Cnav>...\u003C\u002Fnav>\n  \u003Cmain id=\"main-content\">\n    \u003Ch1>Main Content\u003C\u002Fh1>\n  \u003C\u002Fmain>\n\u003C\u002Fbody>\n\n\n\u003C!-- Focus management -->\n\u003Cbutton\n  type=\"button\"\n  onclick=\"openModal()\"\n  aria-haspopup=\"dialog\"\n  aria-expanded=\"false\"\n>\n  Open Modal\n\u003C\u002Fbutton>\n\n\u003Cdiv\n  role=\"dialog\"\n  aria-modal=\"true\"\n  aria-labelledby=\"modal-title\"\n  hidden\n>\n  \u003Ch2 id=\"modal-title\">Modal Title\u003C\u002Fh2>\n  \u003Cbutton\n    type=\"button\"\n    onclick=\"closeModal()\"\n    aria-label=\"Close modal\"\n  >\n    ×\n  \u003C\u002Fbutton>\n  \u003Cdiv>Modal content...\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n```\n\n## ARIA Attributes\n```html\n\u003C!-- ARIA roles for custom components -->\n\u003Cdiv role=\"button\" tabindex=\"0\" aria-pressed=\"false\">\n  Toggle Favorite\n\u003C\u002Fdiv>\n\n\u003C!-- Live regions for dynamic content -->\n\u003Cdiv\n  role=\"status\"\n  aria-live=\"polite\"\n  aria-atomic=\"true\"\n>\n  Changes will be announced\n\u003C\u002Fdiv>\n\n\u003C!-- Form validation -->\n\u003Cform>\n  \u003Clabel for=\"email\">Email\u003C\u002Flabel>\n  \u003Cinput\n    type=\"email\"\n    id=\"email\"\n    name=\"email\"\n    aria-describedby=\"email-hint email-error\"\n    aria-invalid=\"false\"\n  >\n  \u003Cp id=\"email-hint\">We'll never share your email\u003C\u002Fp>\n  \u003Cp id=\"email-error\" hidden>\n    Please enter a valid email address\n  \u003C\u002Fp>\n\u003C\u002Fform>\n```\n\n## Color Contrast\n```css\n\u002F* Minimum contrast ratios (WCAG AA) *\u002F\n\u002F* Normal text: 4.5:1 *\u002F\n\u002F* Large text (18pt+ or 14pt bold): 3:1 *\u002F\n\u002F* UI components: 3:1 *\u002F\n\n.good-contrast {\n  \u002F* Passes AAA (7:1) *\u002F\n  color: #1a1a1a;\n  background-color: #ffffff;\n}\n\n.acceptable-contrast {\n  \u002F* Passes AA (4.5:1) *\u002F\n  color: #333333;\n  background-color: #ffffff;\n}\n\n.large-text {\n  \u002F* Passes AA for large text (3:1) *\u002F\n  color: #555555;\n  background-color: #ffffff;\n  font-size: 18px;\n}\n\n\u002F* Don't rely on color alone *\u002F\n.status {\n  padding: 4px 8px;\n  border-radius: 4px;\n}\n\n.status.success {\n  background-color: #d4edda;\n  color: #155724;\n}\n\n.status.error {\n  background-color: #f8d7da;\n  color: #721c24;\n}\n\n\u002F* Add icon to reinforce color meaning *\u002F\n.status.success::before {\n  content: \"✓ \";\n}\n\n.status.error::before {\n  content: \"✕ \";\n}\n```\n\n## Screen Reader Support\n```html\n\u003C!-- Images must have alt text -->\n\u003Cimg src=\"chart.png\" alt=\"Sales chart showing 25% growth in Q4\">\n\n\u003C!-- Decorative images -->\n\u003Cimg src=\"decoration.png\" alt=\"\" role=\"presentation\">\n\n\u003C!-- Complex images need detailed descriptions -->\n\u003Cimg\n  src=\"infographic.png\"\n  alt=\"Infographic: Step 1 Research, Step 2 Design, Step 3 Development\"\n>\n\u003Cdetails>\n  \u003Csummary>View detailed description\u003C\u002Fsummary>\n  \u003Cp>Full description of the infographic content...\u003C\u002Fp>\n\u003C\u002Fdetails>\n\n\n\u003C!-- Tables need proper structure -->\n\u003Ctable>\n  \u003Ccaption>Quarterly Sales Report\u003C\u002Fcaption>\n  \u003Cthead>\n    \u003Ctr>\n      \u003Cth scope=\"col\">Quarter\u003C\u002Fth>\n      \u003Cth scope=\"col\">Revenue\u003C\u002Fth>\n      \u003Cth scope=\"col\">Expenses\u003C\u002Fth>\n    \u003C\u002Ftr>\n  \u003C\u002Fthead>\n  \u003Ctbody>\n    \u003Ctr>\n      \u003Cth scope=\"row\">Q1\u003C\u002Fth>\n      \u003Ctd>$100,000\u003C\u002Ftd>\n      \u003Ctd>$80,000\u003C\u002Ftd>\n    \u003C\u002Ftr>\n  \u003C\u002Ftbody>\n\u003C\u002Ftable>\n```\n\n## Form Accessibility\n```html\n\u003Cform>\n  \u003Cfieldset>\n    \u003Clegend>Contact Information\u003C\u002Flegend>\n    \n    \u003Cdiv class=\"form-group\">\n      \u003Clabel for=\"name\">Full Name \u003Cspan aria-hidden=\"true\">*\u003C\u002Fspan>\u003C\u002Flabel>\n      \u003Cinput\n        type=\"text\"\n        id=\"name\"\n        name=\"name\"\n        required\n        aria-required=\"true\"\n        autocomplete=\"name\"\n      >\n    \u003C\u002Fdiv>\n    \n    \u003Cdiv class=\"form-group\">\n      \u003Clabel for=\"email\">Email Address\u003C\u002Flabel>\n      \u003Cinput\n        type=\"email\"\n        id=\"email\"\n        name=\"email\"\n        required\n        aria-required=\"true\"\n        autocomplete=\"email\"\n      >\n    \u003C\u002Fdiv>\n    \n    \u003Cdiv class=\"form-group\">\n      \u003Clabel for=\"phone\">Phone Number\u003C\u002Flabel>\n      \u003Cinput\n        type=\"tel\"\n        id=\"phone\"\n        name=\"phone\"\n        autocomplete=\"tel\"\n        pattern=\"[0-9+\\-\\(\\) ]*\"\n        aria-describedby=\"phone-hint\"\n      >\n      \u003Cp id=\"phone-hint\">Include country code (e.g., +1)\u003C\u002Fp>\n    \u003C\u002Fdiv>\n  \u003C\u002Ffieldset>\n  \n  \u003Cbutton type=\"submit\">Submit\u003C\u002Fbutton>\n\u003C\u002Fform>\n\n\n\u003C!-- Error handling -->\n\u003Cform>\n  \u003Cdiv class=\"form-group has-error\">\n    \u003Clabel for=\"email\">Email\u003C\u002Flabel>\n    \u003Cinput\n      type=\"email\"\n      id=\"email\"\n      name=\"email\"\n      aria-invalid=\"true\"\n      aria-describedby=\"email-error\"\n    >\n    \u003Cp id=\"email-error\" role=\"alert\">\n      Please enter a valid email address\n    \u003C\u002Fp>\n  \u003C\u002Fdiv>\n\u003C\u002Fform>\n```\n\n## Testing Accessibility\n```python\n# Automated accessibility testing with axe-core\nimport pytest\n\n\nclass TestAccessibility:\n    def test_homepage_accessibility(self, page):\n        \"\"\"Test homepage with axe-core.\"\"\"\n        page.goto('\u002F')\n        \n        # Run axe-core\n        violations = page.evaluate('''() => {\n          const axe = window.axe;\n          return axe.run(document, {\n            runOnly: {\n              type: 'tag',\n              values: ['wcag2a', 'wcag2aa']\n            }\n          });\n        }''')\n        \n        assert len(violations['violations']) == 0, \\\n            f\"Accessibility violations: {violations['violations']}\"\n    \n    def test_keyboard_navigation(self, page):\n        \"\"\"Test keyboard navigation works.\"\"\"\n        page.goto('\u002F')\n        \n        # Press Tab multiple times\n        page.keyboard.press('Tab')\n        focused = page.evaluate('document.activeElement.tagName')\n        \n        # First focusable element should be first link\n        assert focused in ['A', 'BUTTON', 'INPUT']\n    \n    def test_color_contrast(self, page):\n        \"\"\"Test color contrast requirements.\"\"\"\n        page.goto('\u002F')\n        \n        violations = page.evaluate('''() => {\n          const axe = window.axe;\n          const results = axe.run(document, {\n            checks: ['color-contrast']\n          });\n          return results.violations;\n        }''')\n        \n        assert len(violations) == 0\n\n\n# Manual testing checklist\nACCESSIBILITY_CHECKLIST = \"\"\"\n[] All images have alt text\n[] Form inputs have associated labels\n[] Headings follow proper hierarchy (h1 > h2 > h3)\n[] Color is not the only means of conveying information\n[] Focus order is logical\n[] Keyboard navigation works throughout\n[] Skip links are present\n[] ARIA landmarks are used correctly\n[] Form errors are announced\n[] Error messages are specific\n[] Page has language attribute\n[] Content is readable at 200% zoom\n[] No keyboard traps\n[] Focus is not lost when modal closes\n\"\"\"\n```\n",{"name":5,"license":14,"metadata":34,"description":7,"compatibility":27},{"audience":35,"category":23},"developers","main","5f7a3e453c98261f93d19a6a7de44ad8f7b72d41",2,"https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk","2026-03-01 06:55:40",{"source":8,"skillName":5,"commands":43,"prompt":53,"zipAvailable":54},[44,47,50],{"tool":45,"command":46},"npx","npx skills add ffsshhttiikk\u002Fopencode-agents-skills --skill accessibility",{"tool":48,"command":49},"bunx","bunx skills add ffsshhttiikk\u002Fopencode-agents-skills --skill accessibility",{"tool":51,"command":52},"pnpm","pnpm dlx skills add ffsshhttiikk\u002Fopencode-agents-skills --skill accessibility","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Faccessibility\u002FSKILL.md",true,[],[57,68,78,87,97,106],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":29},"01M6CXT9TXDF79BWJTMQAPB49G","xamarin","Xamarin cross-platform development","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fxamarin\u002FSKILL.md",[],[59,64,65,66,27,67],"platform","cross-platform","mobile","development",{"skillNo":69,"name":70,"nameZh":6,"description":71,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":72,"categories":73,"keywords":74,"publishedAt":29},"01M6CXT8AD04MFYDA32VW3FKAG","wrangling","Data wrangling fundamentals","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwrangling\u002FSKILL.md",[],[70,75,27,76,77],"data wrangling","science","data",{"skillNo":79,"name":80,"nameZh":6,"description":81,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":82,"categories":83,"keywords":84,"publishedAt":29},"01M6CXT717GCN7SRRNPBDP4508","windows","Windows operating system administration and scripting","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwindows\u002FSKILL.md",[],[80,85,27,86],"system","scripting",{"skillNo":88,"name":89,"nameZh":6,"description":90,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":29},"01M6CXT54K794NMEM3XAPZZDKT","wide-column","Wide-column data model","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwide-column\u002FSKILL.md",[],[94,95,27,96,77],"wide column","databases","model",{"skillNo":98,"name":99,"nameZh":6,"description":100,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":101,"categories":102,"keywords":103,"publishedAt":29},"01M6CXT28FMT2P4V9GZE67WA8E","wide-column-stores","Wide-column database stores","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwide-column-stores\u002FSKILL.md",[],[104,95,27,105],"wide column stores","database",{"skillNo":107,"name":108,"nameZh":6,"description":109,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":110,"categories":111,"keywords":112,"publishedAt":29},"01M6CXT0D0M0Q4T2N7C2RX7DSN","websockets","WebSocket implementation and best practices","https:\u002F\u002Fgithub.com\u002Fffsshhttiikk\u002Fopencode-agents-skills\u002Fblob\u002Fmain\u002Fwebsockets\u002FSKILL.md",[],[108,113,114,115,27,25,28],"websocket","real-time","time"]