Agent skill

validating-accessibility

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.

Stars 11,120
Forks 560

Install this agent skill to your Project

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

Metadata

Additional technical details for this skill

internal
YES

SKILL.md

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:

tsx
<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

Expand your agent's capabilities with these related and highly-rated skills.

tambo-ai/tambo

building-compound-components

Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating component libraries, implementing Radix-style namespaced components, or when the user mentions "compound components", "headless", "unstyled", "primitives", or "render props".

11,120 560
Explore
tambo-ai/tambo

creating-styled-wrappers

Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use base primitives, implementing opinionated design systems on top of headless components, or when the user mentions "use base components", "compose primitives", "styled wrapper", or "refactor to use base".

11,120 560
Explore
tambo-ai/tambo

api-resource-lifecycle

Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when adding delete/remove operations, creating validation logic, building resources that depend on other resources, or when the user mentions "cascade delete", "orphan records", "duplicate detection", "validation errors", "resource cleanup", or "rollback on failure".

11,120 560
Explore
tambo-ai/tambo

building-settings-ui

Use this skill when adding or modifying settings UI in Tambo Cloud. Covers where a new settings section belongs (Agent tab vs Settings tab), and the component patterns used across both pages (card layout, toasts, confirmation dialogs, destructive styling, save behavior conventions). Triggers on "add a new settings section", "where should X go?", "settings UI", "settings page", "agent page", or any work touching apps/web/components/dashboard-components/project-details/, project-settings.tsx, or agent-settings.tsx. Not for full-stack feature building (DB, tRPC, tests); those patterns will get their own skills.

11,120 560
Explore
tambo-ai/tambo

ai-sdk-model-manager

Manages AI SDK model configurations - updates packages, identifies missing models, adds new models with research, and updates documentation

11,120 560
Explore
tambo-ai/tambo

generative-ui

Creates a new Tambo generative UI app from scratch. Scaffolds with tambo create-app, wires TamboProvider, registers starter components. Triggers on "new Tambo app", "create a generative UI app", "build an AI app from scratch", "start a new project with Tambo". For existing apps, use building-with-tambo.

11,120 560
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results