Skip to content
Frontend
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,

From plugin
tambo
11k8 skills2 agents4 commands

Claude Code

$ npx -y skills add tambo-ai/tambo --skill validating-accessibility --agent claude-code

SKILL.md

validating-accessibility.SKILL.md
name: validating-accessibility
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.
metadata:
  internal: true

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
Read more
@tambo-ai
Ships withtambo

Generative UI SDK for React

11k8 skills2 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
11.2k
Star history of tambo-ai/tambo on GitHub, a chart by star-history.com

Other skills on tambo.

ai-sdk-model-manager

ai-sdk-model-manager

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

@tambo-ai@tambo-aiInstall Skill
api-resource-lifecycle

api-resource-lifecycle

Guides CRUD operations for API resources with cascading dependencies, descriptive validation, and orphan prevention. Use when…

@tambo-ai@tambo-aiInstall Skill
building-settings-ui

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…

@tambo-ai@tambo-aiInstall Skill
compound-components

compound-components

Creates unstyled compound components that separate business logic from styles. Use when building headless UI primitives, creating…

@tambo-ai@tambo-aiInstall Skill
creating-styled-wrappers

creating-styled-wrappe…

Creates styled wrapper components that compose headless/base compound components. Use when refactoring styled components to use…

@tambo-ai@tambo-aiInstall Skill
building-with-tambo

building-with-tambo

Integrates Tambo into existing React apps — detects tech stack, installs @tambo-ai/react, wires TamboProvider, registers…

@tambo-ai@tambo-aiInstall Skill

More skills from other plugins.

next-bundle-optimizer
Auto-invoked

next-bundle-optimizer

Audit and reduce Next.js browser initial-load work. Use for slow route startup, oversized client bundles, duplicate browser…

nextjs1d143k
@vercel@vercelInstall Skill
migrate-radix-to-base

migrate-radix-to-base

Migrates React projects and components from Radix UI to Base UI. Use when asked to migrate from radix, move to base-ui, convert…

ui10d127k
@shadcn-ui@shadcn-uiInstall Skill
chrome-release-cls

chrome-release-cls

Given a Chrome Releases blog post URL (chromereleases.googleblog.com), extract every CVE/bug and find the underlying Gerrit CL…

electron1d124k
@electron@electronInstall Skill
taste-skill
Auto-invoked

taste-skill

tasteskill v2, the anti-slop frontend skill. Art direction for websites, distilled from a study of 247 curated gallery sites (One…

@leonxlnx@leonxlnxInstall Skill

Questions about validating-accessibility.

Which coding agents can use validating-accessibility?
validating-accessibility installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.