Agent Skillstambo-ai/tambo › validating-accessibility

validating-accessibility

GitHub

针对 Web 前端组件的无障碍访问(a11y)审查与开发指南,涵盖语义化 HTML、ARIA 标签、键盘导航及表单规范,确保 UI 交互符合 WCAG 标准。

.claude/skills/validating-accessibility/SKILL.md tambo-ai/tambo

Trigger Scenarios

创建或修改 .tsx 组件 添加按钮、链接或交互元素 构建或编辑表单 添加对话框或模态框 审查 UI 代码

Install

npx skills add tambo-ai/tambo --skill validating-accessibility -g -y
More Options

Non-standard path

npx skills add https://github.com/tambo-ai/tambo/tree/main/.claude/skills/validating-accessibility -g -y

Use without installing

npx skills use tambo-ai/tambo@validating-accessibility

指定 Agent (Claude Code)

npx skills add tambo-ai/tambo --skill validating-accessibility -a claude-code -g -y

安装 repo 全部 skill

npx skills add tambo-ai/tambo --all -g -y

预览 repo 内 skill

npx skills add tambo-ai/tambo --list

SKILL.md

Frontmatter
{
    "name": "validating-accessibility",
    "metadata": {
        "internal": true
    },
    "description": "Use this skill when creating, modifying, or reviewing any .tsx component in apps\/web, even if the user doesn't mention \"accessibility.\" Covers semantic HTML, aria labels, navigation landmarks, forms, dialogs, and keyboard navigation. Trigger on: adding buttons, links, toggles, icons, or any interactive element; building or editing forms; adding dialogs or modals; reviewing UI code. Includes inline verification patterns for scanning violations. Not for styling or layout changes that don't involve interactive elements."
}

Accessibility Checklist

Every UI component in apps/web must meet these standards. No partial compliance.

Gotchas

  • role="button" divs may exist in the codebase -- fix them when touching affected files. <TableHead> elements with role="button" for sortable columns are acceptable.
  • Nested interactive elements -- when replacing a <div role="button"> that contains a child <button> (e.g., a copy button inside a collapsible toggle), do not just swap the outer div to <button>. That creates invalid nested buttons. Instead, restructure into sibling elements: a toggle <button> and a separate action <button> side by side in a flex container.
  • Standalone inputs outside react-hook-form need manual ID pairing -- use useId() with htmlFor/id. The shadcn <FormField> handles this automatically, but raw <Input> does not.
  • AlertDialog vs Dialog -- use AlertDialog for destructive confirmations (requires AlertDialogTitle + AlertDialogDescription). Use Dialog for content/forms. Never build custom modal overlays.
  • Icon-only buttons without aria-label are common in new code. Every icon-only button needs one, and it must include context: Delete API key ${keyName}, not just "Delete".

Semantic HTML

Use native elements. Never recreate <button> behavior with <div role="button"> + keyboard handlers.

Interaction Element
Clickable action <button> or <Button> from @/components/ui/button
Navigation link <Link> (Next.js) or <a>
Navigation group <nav> with descriptive aria-label
Item list <ul>/<ol> + <li>
Section heading <h1>-<h6> in order, never skip levels

Aria Labels

Every interactive element without visible text needs aria-label with both action AND target:

<Button size="icon" aria-label={`Delete API key ${keyName}`}>
  <Trash2 className="h-4 w-4" />
</Button>

<Switch aria-label={`${enabled ? "Disable" : "Enable"} skill ${skillName}`} />

Prefer state-aware labels ("Copied!" vs "Copy"). Buttons with visible text skip aria-label.

Reference implementations: copy-button.tsx (state-aware), context-attachment-badge.tsx (contextual remove), thread-table-header.tsx (sort state) -- all in apps/web/components/.

Navigation Landmarks

Wrap navigation groups in <nav> with a unique aria-label per region on the page.

Forms

Use shadcn Form components from @/components/ui/form (FormField, FormItem, FormLabel, FormControl, FormMessage). They handle ID generation, label association, aria-describedby, and aria-invalid automatically.

For standalone inputs outside react-hook-form, pair useId() with htmlFor/id. Never use placeholder as label substitute.

Keyboard Navigation

  • Only tabIndex={0} or tabIndex={-1} (never positive values)
  • Never remove focus outlines
  • Prefer <button> over manual Enter/Space handlers

Verification

Scan apps/web/components for common violations. For each check, grep for the pattern and fix any matches found.

Check 1: role="button" on non-button elements

Search for role="button" in .tsx files. Flag <div or <span elements with this attribute; they should be <button> or <Button> instead. <TableHead> elements with role="button" for sortable columns are acceptable.

Pattern: role="button"

Check 2: <div onClick> patterns

Search for <div elements with onClick handlers. These should use <button> instead for proper keyboard support.

Pattern: <div[^>]*onClick

Check 3: Positive tabIndex values

Search for tabIndex with values greater than 0. Only tabIndex={0} and tabIndex={-1} are allowed.

Pattern: tabIndex={[1-9]

Check 4: Icon buttons missing aria-label

Search for size="icon" in .tsx files. For each match, check surrounding lines (5-10 above and below) for aria-label on the same <Button> element or an sr-only span. Flag buttons that have neither.

Pattern: size="icon" without nearby aria-label

Manual checks

These cannot be detected by pattern matching:

  • Form inputs have associated <label> elements
  • Navigation groups use <nav> with unique aria-label
  • Dialogs use Radix-based components (AlertDialog or Dialog)
  • Focus outlines intact

Version History

  • 0c84ae0 Current 2026-08-20 13:39

Same Skill Collection

.claude/skills/ai-sdk-model-manager/SKILL.md
.claude/skills/api-resource-lifecycle/SKILL.md
.claude/skills/compound-components/SKILL.md
.claude/skills/creating-styled-wrappers/SKILL.md
plugins/tambo/skills/building-with-tambo/SKILL.md
plugins/tambo/skills/generative-ui/SKILL.md
.claude/skills/building-settings-ui/SKILL.md

Metadata

Files
0
Version
0c84ae0
Hash
ec2f3ac7
Indexed
2026-08-20 13:39

- 위키
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-08-25 14:39
浙ICP备14020137号-1 $방문자$