MCPInstall

accessibility

Build WCAG 2.1 AA compliant websites with semantic HTML, proper ARIA, focus management, and screen reader support. Includes color contrast (4.5:1 text), keyboard navigation, form labels, and live regions. Use when implementing accessible interfaces, fixing screen reader issues, keyboard navigation, or troubleshooting "focus outline missing", "aria-label required", "insufficient contrast".

Installs
504
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/jezweb/claude-skills --skill accessibility
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads accessibility automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Web Accessibility (WCAG 2.1 AA)

Status: Production Ready ✅ Last Updated: 2026-01-14 Dependencies: None (framework-agnostic) Standards: WCAG 2.1 Level AA


Quick Start (5 Minutes)

1. Semantic HTML Foundation

Choose the right element - don't use div for everything:

<!-- ❌ WRONG - divs with onClick -->
<div onclick="submit()">Submit</div>
<div onclick="navigate()">Next page</div>

<!-- ✅ CORRECT - semantic elements -->
<button type="submit">Submit</button>
<a href="/next">Next page</a>

Why this matters:

  • Semantic elements have built-in keyboard support
  • Screen readers announce role automatically
  • Browser provides default accessible behaviors

2. Focus Management

Make interactive elements keyboard-accessible:

/* ❌ WRONG - removes focus outline */
button:focus { outline: none; }

/* ✅ CORRECT - custom accessible outline */
button:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

CRITICAL:

  • Never remove focus outlines without replacement
  • Use :focus-visible to show only on keyboard focus
  • Ensure 3:1 contrast ratio for focus indicators

3. Text Alternatives

Every non-text element needs a text alternative:

<!-- ❌ WRONG - no alt text -->
<img src="logo.png">
<button><svg>...</svg></button>

<!-- ✅ CORRECT - proper alternatives -->
<img src="logo.png" alt="Company Name">
<button aria-label="Close dialog"><svg>...</svg></button>

The 5-Step Accessibility Process

Step 1: Choose Semantic HTML

Decision tree for element selection:

Need clickable element?
├─ Navigates to another page? → <a href="...">
├─ Submits form? → <button type="submit">
├─ Opens dialog? → <button aria-haspopup="dialog">
└─ Other action? → <button type="button">

Grouping content?
├─ Self-contained article? → <article>
├─ Thematic section? → <section>
├─ Navigation links? → <nav>
└─ Supplementary info? → <aside>

Form element?
├─ Text input? → <input type="text">
├─ Multiple choice? → <select> or <input type="radio">
├─ Toggle? → <input type="checkbox"> or <button aria-pressed>
└─ Long text? → <textarea>

See references/semantic-html.md for complete guide.

Step 2: Add ARIA When Needed

Golden rule: Use ARIA only when HTML can't express the pattern.

<!-- ❌ WRONG - unnecessary ARIA -->
<button role="button">Click me</button>  <!-- Button already has role -->

<!-- ✅ CORRECT - ARIA fills semantic gap -->
<div role="dialog" aria-labelledby="title" aria-modal="true">
  <h2 id="title">Confirm action</h2>
  <!-- No HTML dialog yet, so role needed -->
</div>

<!-- ✅ BETTER - Use native HTML when available -->
<dialog aria-labelledby="title">
  <h2 id="title">Confirm action</h2>
</dialog>

Common ARIA patterns:

  • aria-label - When visible label doesn't exist
  • aria-labelledby - Reference existing text as label
  • aria-describedby - Additional description
  • aria-live - Announce dynamic updates
  • aria-expanded - Collapsible/expandable state

See references/aria-patterns.md for complete patterns.

Step 3: Implement Keyboard Navigation

All interactive elements must be keyboard-accessible:

// Tab order management
function Dialog({ onClose }) {
  const dialogRef = useRef<HTMLDivElement>(null);
  const previousFocus = useRef<HTMLElement | null>(null);

  useEffect(() => {
    // Save previous focus
    previousFocus.current = document.activeElement as HTMLElement;

    // Focus first element in dialog
    const firstFocusable = dialogRef.current?.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
    (firstFocusable as HTMLElement)?.focus();

    // Trap focus within dialog
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
      if (e.key === 'Tab') {
        // Focus trap logic here
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      // Restore focus on close
      previousFocus.current?.focus();
    };
  }, [onClose]);

  return <div ref={dialogRef} role="dialog">...</div>;
}

Essential keyboard patterns:

  • Tab/Shift+Tab: Navigate between focusable elements
  • Enter/Space: Activate buttons/links
  • Arrow keys: Navigate within components (tabs, menus)
  • Escape: Close dialogs/menus
  • Home/End: Jump to first/last item

See references/focus-management.md for complete patterns.

Step 4: Ensure Color Contrast

WCAG AA requirements:

  • Normal text (under 18pt): 4.5:1 contrast ratio
  • Large text (18pt+ or 14pt+ bold): 3:1 contrast ratio
  • UI components (buttons, borders): 3:1 contrast ratio
/* ❌ WRONG - insufficient contrast */
:root {
  --background: #ffffff;
  --text: #999999;  /* 2.8:1 - fails WCAG AA */
}

/* ✅ CORRECT - sufficient contrast */
:root {
  --background: #ffffff;
  --text: #595959;  /* 4.6:1 - passes WCAG AA */
}

Testing tools:

  • Browser DevTools (Chrome/Firefox have built-in checkers)
  • Contrast checker extensions
  • axe DevTools extension

See references/color-contrast.md for complete guide.

Step 5: Make Forms Accessible

Every form input needs a visible label:

<!-- ❌ WRONG - placeholder is not a label -->
<input type="email" placeholder="Email address">

<!-- ✅ CORRECT - proper label -->
<label for="email">Email address</label>
<input type="email" id="email" name="email" required aria-required="true">

Error handling:

<label for="email">Email address</label>
<input
  type="email"
  id="email"
  name="email"
  aria-invalid="true"
  aria-describedby="email-error"
>
<span id="email-error" role="alert">
  Please enter a valid email address
</span>

Live regions for dynamic errors:

<div role="alert" aria-live="assertive" aria-atomic="true">
  Form submission failed. Please fix the errors above.
</div>

See references/forms-validation.md for complete patterns.


Critical Rules

Always Do

✅ Use semantic HTML elements first (button, a, nav, article, etc.) ✅ Provide text alternatives for all non-text content ✅ Ensure 4.5:1 contrast for normal text, 3:1 for large text/UI ✅ Make all functionality keyboard accessible ✅ Test with keyboard only (unplug mouse) ✅ Test with screen reader (NVDA on Windows, VoiceOver on Mac) ✅ Use proper heading hierarchy (h1 → h2 → h3, no skipping) ✅ Label all form inputs with visible labels ✅ Provide focus indicators (never just outline: none) ✅ Use aria-live for dynamic content updates

Never Do

❌ Use div with onClick instead of button ❌ Remove focus outlines without replacement ❌ Use color alone to convey information ❌ Use placeholders as labels ❌ Skip heading levels (h1 → h3) ❌ Use tabindex > 0 (messes with natural order) ❌ Add ARIA when semantic HTML exists ❌ Forget to restore focus after closing dialogs ❌ Use role="presentation" on focusable elements ❌ Create keyboard traps (no way to escape)


Known Issues Prevention

This skill prevents 12 documented accessibility issues:

Issue #1: Missing Focus Indicators

Error: Interactive elements have no visible focus indicator Source: WCAG 2.4.7 (Focus Visible) Why It Happens: CSS reset removes default outline Prevention: Always provide custom focus-visible styles

Issue #2: Insufficient Color Contrast

Error: Text has less than 4.5:1 contrast ratio Source: WCAG 1.4.3 (Contrast Minimum) Why It Happens: Using light gray text on white background Prevention: Test all text colors with contrast checker

Issue #3: Missing Alt Text

Error: Images missing alt attributes Source: WCAG 1.1.1 (Non-text Content) Why It Happens: Forgot to add or thought it was optional Prevention: Add alt="" for decorative, descriptive alt for meaningful images

Issue #4: Keyboard Navigation Broken

Error: Interactive elements not reachable by keyboard Source: WCAG 2.1.1 (Keyboard) Why It Happens: Using div onClick instead of button Prevention: Use semantic interactive elements (button, a)

Issue #5: Form Inputs Without Labels

Error: Input fields missing associated labels Source: WCAG 3.3.2 (Labels or Instructions) Why It Happens: Using placeholder as label Prevention: Always use <label> element with for/id association

Issue #6: Skipped Heading Levels

Error: Heading hierarchy jumps from h1 to h3 Source: WCAG 1.3.1 (Info and Relationships) Why It Happens: Using headings for visual styling instead of semantics Prevention: Use headings in order, style with CSS

Issue #7: No Focus Trap in Dialogs

Error: Tab key exits dialog to background content Source: WCAG 2.4.3 (Focus Order) Why It Happens: No focus trap implementation Prevention: Implement focus trap for modal dialogs

Issue #8: Missing aria-live for Dynamic Content

Error: Screen reader doesn't announce updates Source: WCAG 4.1.3 (Status Messages) Why It Happens: Dynamic content added without announcement Prevention: Use aria-live="polite" or "assertive"

Issue #9: Color-Only Information

Error: Using only color to convey status Source: WCAG 1.4.1 (Use of Color) Why It Happens: Red text for errors without icon/text Prevention: Add icon + text label, not just color

Issue #10: Non-descriptive Link Text

Error: Links with "click here" or "read more" Source: WCAG 2.4.4 (Link Purpose) Why It Happens: Generic link text without context Prevention: Use descriptive link text or aria-label

Issue #11: Auto-playing Media

Error: Video/audio auto-plays without user control Source: WCAG 1.4.2 (Audio Control) Why It Happens: Autoplay attribute without controls Prevention: Require user interaction to start media

Issue #12: Inaccessible Custom Controls

Error: Custom select/checkbox without keyboard support Source: WCAG 4.1.2 (Name, Role, Value) Why It Happens: Building from divs without ARIA Prevention: Use native elements or implement full ARIA pattern


WCAG 2.1 AA Quick Checklist

Perceivable

  • All images have alt text (or alt="" if decorative)
  • Text contrast ≥ 4.5:1 (normal), ≥ 3:1 (large)
  • Color not used alone to convey information
  • Text can be resized to 200% without loss of content
  • No auto-playing audio >3 seconds

Operable

  • All functionality keyboard accessible
  • No keyboard traps
  • Visible focus indicators
  • Users can pause/stop/hide moving content
  • Page titles describe purpose
  • Focus order is logical
  • Link purpose clear from text or context
  • Multiple ways to find pages (menu, search, sitemap)
  • Headings and labels describe purpose

Understandable

  • Page language specified (<html lang="en">)
  • Language changes marked (<span lang="es">)
  • No unexpected context changes on focus/input
  • Consistent navigation across site
  • Form labels/instructions provided
  • Input errors identified and described
  • Error prevention for legal/financial/data changes

Robust

  • Valid HTML (no parsing errors)
  • Name, role, value available for all UI components
  • Status messages identified (aria-live)

Testing Workflow

1. Keyboard-Only Testing (5 minutes)

1. Unplug mouse or hide cursor
2. Tab through entire page
   - Can you reach all interactive elements?
   - Can you activate all buttons/links?
   - Is focus order logical?
3. Use Enter/Space to activate
4. Use Escape to close dialogs
5. Use arrow keys in menus/tabs

2. Screen Reader Testing (10 minutes)

NVDA (Windows - Free):

VoiceOver (Mac - Built-in):

  • Start: Cmd+F5
  • Navigate: VO+Right/Left arrow (VO = Ctrl+Option)
  • Read: VO+A (read all)
  • Stop: Cmd+F5

What to test:

  • Are all interactive elements announced?
  • Are images described properly?
  • Are form labels read with inputs?
  • Are dynamic updates announced?
  • Is heading structure clear?

3. Automated Testing

axe DevTools (Browser extension - highly recommended):

  • Install: Chrome/Firefox extension
  • Run: F12 → axe DevTools tab → Scan
  • Fix: Review violations, follow remediation
  • Retest: Scan again after fixes

Lighthouse (Built into Chrome):

  • Open DevTools (F12)
  • Lighthouse tab
  • Select "Accessibility" category
  • Generate report
  • Score 90+ is good, 100 is ideal

Common Patterns

Pattern 1: Accessible Dialog/Modal

interface DialogProps {
  isOpen: boolean;
  onClose: () => void;
  title: string;
  children: React.ReactNode;
}

function Dialog({ isOpen, onClose, title, children }: DialogProps) {
  const dialogRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    if (!isOpen) return;

    const previousFocus = document.activeElement as HTMLElement;

    // Focus first focusable element
    const firstFocusable = dialogRef.current?.querySelector(
      'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
    ) as HTMLElement;
    firstFocusable?.focus();

    // Focus trap
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === 'Escape') {
        onClose();
      }
      if (e.key === 'Tab') {
        const focusableElements = dialogRef.current?.querySelectorAll(
          'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
        );
        if (!focusableElements?.length) return;

        const first = focusableElements[0] as HTMLElement;
        const last = focusableElements[focusableElements.length - 1] as HTMLElement;

        if (e.shiftKey && document.activeElement === first) {
          e.preventDefault();
          last.focus();
        } else if (!e.shiftKey && document.activeElement === last) {
          e.preventDefault();
          first.focus();
        }
      }
    };

    document.addEventListener('keydown', handleKeyDown);

    return () => {
      document.removeEventListener('keydown', handleKeyDown);
      previousFocus?.focus();
    };
  }, [isOpen, onClose]);

  if (!isOpen) return null;

  return (
    <>
      {/* Backdrop */}
      <div
        className="dialog-backdrop"
        onClick={onClose}
        aria-hidden="true"
      />

      {/* Dialog */}
      <div
        ref={dialogRef}
        role="dialog"
        aria-modal="true"
        aria-labelledby="dialog-title"
        className="dialog"
      >
        <h2 id="dialog-title">{title}</h2>
        <div className="dialog-content">{children}</div>
        <button onClick={onClose} aria-label="Close dialog">×</button>
      </div>
    </>
  );
}

When to use: Any modal dialog or overlay that blocks interaction with background content.

Pattern 2: Accessible Tabs

function Tabs({ tabs }: { tabs: Array<{ label: string; content: React.ReactNode }> }) {
  const [activeIndex, setActiveIndex] = useState(0);

  const handleKeyDown = (e: React.KeyboardEvent, index: number) => {
    if (e.key === 'ArrowLeft') {
      e.preventDefault();
      const newIndex = index === 0 ? tabs.length - 1 : index - 1;
      setActiveIndex(newIndex);
    } else if (e.key === 'ArrowRight') {
      e.preventDefault();
      const newIndex = index === tabs.length - 1 ? 0 : index + 1;
      setActiveIndex(newIndex);
    } else if (e.key === 'Home') {
      e.preventDefault();
      setActiveIndex(0);
    } else if (e.key === 'End') {
      e.preventDefault();
      setActiveIndex(tabs.length - 1);
    }
  };

  return (
    <div>
      <div role="tablist" aria-label="Content tabs">
        {tabs.map((tab, index) => (
          <button
            key={index}
            role="tab"
            aria-selected={activeIndex === index}
            aria-controls={`panel-${index}`}
            id={`tab-${index}`}
            tabIndex={activeIndex === index ? 0 : -1}
            onClick={() => setActiveIndex(index)}
            onKeyDown={(e) => handleKeyDown(e, index)}
          >
            {tab.label}
          </button>
        ))}
      </div>
      {tabs.map((tab, index) => (
        <div
          key={index}
          role="tabpanel"
          id={`panel-${index}`}
          aria-labelledby={`tab-${index}`}
          hidden={activeIndex !== index}
          tabIndex={0}
        >
          {tab.content}
        </div>
      ))}
    </div>
  );
}

When to use: Tabbed interface with multiple panels.

Pattern 3: Skip Links

<!-- Place at very top of body -->
<a href="#main-content" class="skip-link">
  Skip to main content
</a>

<style>
.skip-link {
  position: absolute;
  top: -40px;
  left: 0;
  background: var(--primary);
  color: white;
  padding: 8px 16px;
  z-index: 9999;
}

.skip-link:focus {
  top: 0;
}
</style>

<!-- Then in your layout -->
<main id="main-content" tabindex="-1">
  <!-- Page content -->
</main>

When to use: All multi-page websites with navigation/header before main content.

Pattern 4: Accessible Form with Validation

function ContactForm() {
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [touched, setTouched] = useState<Record<string, boolean>>({});

  const validateEmail = (email: string) => {
    if (!email) return 'Email is required';
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) return 'Email is invalid';
    return '';
  };

  const handleBlur = (field: string, value: string) => {
    setTouched(prev => ({ ...prev, [field]: true }));
    const error = validateEmail(value);
    setErrors(prev => ({ ...prev, [field]: error }));
  };

  return (
    <form>
      <div>
        <label htmlFor="email">Email address *</label>
        <input
          type="email"
          id="email"
          name="email"
          required
          aria-required="true"
          aria-invalid={touched.email && !!errors.email}
          aria-describedby={errors.email ? 'email-error' : undefined}
          onBlur={(e) => handleBlur('email', e.target.value)}
        />
        {touched.email && errors.email && (
          <span id="email-error" role="alert" className="error">
            {errors.email}
          </span>
        )}
      </div>

      <button type="submit">Submit</button>

      {/* Global form error */}
      <div role="alert" aria-live="assertive" aria-atomic="true">
        {/* Dynamic error message appears here */}
      </div>
    </form>
  );
}

When to use: All forms with validation.


Using Bundled Resources

References (references/)

Detailed documentation for deep dives:

  • wcag-checklist.md - Complete WCAG 2.1 Level A & AA requirements with examples
  • semantic-html.md - Element selection guide, when to use which tag
  • aria-patterns.md - ARIA roles, states, properties, and when to use them
  • focus-management.md - Focus order, focus traps, focus restoration patterns
  • color-contrast.md - Contrast requirements, testing tools, color palette tips
  • forms-validation.md - Accessible form patterns, error handling, announcements

When Claude should load these:

  • User asks for complete WCAG checklist
  • Deep dive into specific pattern (tabs, accordions, etc.)
  • Color contrast issues or palette design
  • Complex form validation scenarios

Agents (agents/)

  • a11y-auditor.md - Automated accessibility auditor that checks pages for violations

When to use: Request accessibility audit of existing page/component.


Advanced Topics

ARIA Live Regions

Three politeness levels:

<!-- Polite: Wait for screen reader to finish current announcement -->
<div aria-live="polite">New messages: 3</div>

<!-- Assertive: Interrupt immediately -->
<div aria-live="assertive" role="alert">
  Error: Form submission failed
</div>

<!-- Off: Don't announce (default) -->
<div aria-live="off">Loading...</div>

Best practices:

  • Use polite for non-critical updates (notifications, counters)
  • Use assertive for errors and critical alerts
  • Use aria-atomic="true" to read entire region on change
  • Keep messages concise and meaningful

Focus Management in SPAs

React Router doesn't reset focus on navigation - you need to handle it:

function App() {
  const location = useLocation();
  const mainRef = useRef<HTMLElement>(null);

  useEffect(() => {
    // Focus main content on route change
    mainRef.current?.focus();
    // Announce page title to screen readers
    const title = document.title;
    const announcement = document.createElement('div');
    announcement.setAttribute('role', 'status');
    announcement.setAttribute('aria-live', 'polite');
    announcement.textContent = `Navigated to ${title}`;
    document.body.appendChild(announcement);
    setTimeout(() => announcement.remove(), 1000);
  }, [location.pathname]);

  return <main ref={mainRef} tabIndex={-1} id="main-content">...</main>;
}

Accessible Data Tables

<table>
  <caption>Monthly sales by region</caption>
  <thead>
    <tr>
      <th scope="col">Region</th>
      <th scope="col">Q1</th>
      <th scope="col">Q2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">North</th>
      <td>$10,000</td>
      <td>$12,000</td>
    </tr>
  </tbody>
</table>

Key attributes:

  • <caption> - Describes table purpose
  • scope="col" - Identifies column headers
  • scope="row" - Identifies row headers
  • Associates data cells with headers for screen readers

Official Documentation


Troubleshooting

Problem: Focus indicators not visible

Symptoms: Can tab through page but don't see where focus is Cause: CSS removed outlines or insufficient contrast Solution:

*:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}

Problem: Screen reader not announcing updates

Symptoms: Dynamic content changes but no announcement Cause: No aria-live region Solution: Wrap dynamic content in <div aria-live="polite"> or use role="alert"

Problem: Dialog focus escapes to background

Symptoms: Tab key navigates to elements behind dialog Cause: No focus trap Solution: Implement focus trap (see Pattern 1 above)

Problem: Form errors not announced

Symptoms: Visual errors appear but screen reader doesn't notice Cause: No aria-invalid or role="alert" Solution: Use aria-invalid + aria-describedby pointing to error message with role="alert"


Complete Setup Checklist

Use this for every page/component:

  • All interactive elements are keyboard accessible
  • Visible focus indicators on all focusable elements
  • Images have alt text (or alt="" if decorative)
  • Text contrast ≥ 4.5:1 (test with axe or Lighthouse)
  • Form inputs have associated labels (not just placeholders)
  • Heading hierarchy is logical (no skipped levels)
  • Page has <html lang="en"> or appropriate language
  • Dialogs have focus trap and restore focus on close
  • Dynamic content uses aria-live or role="alert"
  • Color not used alone to convey information
  • Tested with keyboard only (no mouse)
  • Tested with screen reader (NVDA or VoiceOver)
  • Ran axe DevTools scan (0 violations)
  • Lighthouse accessibility score ≥ 90

Questions? Issues?

  1. Check references/wcag-checklist.md for complete requirements
  2. Use /a11y-auditor agent to scan your page
  3. Run axe DevTools for automated testing
  4. Test with actual keyboard + screen reader

Standards: WCAG 2.1 Level AA Testing Tools: axe DevTools, Lighthouse, NVDA, VoiceOver Success Criteria: 90+ Lighthouse score, 0 critical violations

FAQ

What does the accessibility skill do?

Build WCAG 2.1 AA compliant websites with semantic HTML, proper ARIA, focus management, and screen reader support. Includes color contrast (4.5:1 text), keyboard navigation, form labels, and live regions. Use when implementing accessible interfaces, fixing screen reader issues, keyboard navigation, or troubleshooting "focus outline missing", "aria-label required", "insufficient contrast".

How do I install accessibility?

Run npx skills add https://github.com/jezweb/claude-skills --skill accessibility in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/accessibility/ (personal) or .claude/skills/accessibility/ (project).

Which AI agents can use accessibility?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is accessibility safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains accessibility?

It is published by jezweb in jezweb/claude-skills. It has 504 recorded installs.

More from jezweb/claude-skills

View all →

shadcn-ui

jezweb/claude-skills

Install and configure shadcn/ui components for React projects. Guides component selection, installation order, dependency management, customisation with semantic tokens, and common UI recipes (forms, data tables, navigation, modals). Use after tailwind-theme-builder has set up the theme infrastructure, when adding components, building forms, creating data tables, or setting up navigation.

Frontend & Design3.6K installs

color-palette

jezweb/claude-skills

Generate complete, accessible colour palettes from a single brand hex. Produces 11-shade scale (50-950), semantic tokens, dark mode variants, Tailwind v4 CSS output, WCAG contrast checks. Use whenever the user supplies a brand hex and asks for a palette, mentions setting up a design system, wants Tailwind theme colours from a brand colour, or asks to check colour accessibility / contrast.

Frontend & Design3.2K installs

tailwind-theme-builder

jezweb/claude-skills

Set up Tailwind v4 + shadcn/ui themed UI with dark mode. Install deps, configure CSS variables via @theme inline, wire dark mode toggle, verify. Use whenever the user mentions Tailwind v4, setting up Tailwind theming, shadcn/ui colours, dark mode, or troubleshooting colours not working, tw-animate-css errors, @theme inline conflicts, @apply breaking after upgrade, or v3 → v4 migration issues.

Frontend & Design3.2K installs

wordpress-elementor

jezweb/claude-skills

Edit Elementor pages and manage templates on WordPress sites via browser automation (for visual / structural changes) or WP-CLI (for safe text replacements). Use whenever the user wants to edit an Elementor page, update text in Elementor widgets, apply or manage Elementor templates, or make content changes to pages built with the Elementor page builder.

ux-audit

jezweb/claude-skills

Walk through a live web app AS a real user to find usability + behavioural bugs that static reviews miss. REQUIRES proof of interaction (typing, clicking, sending, observing) before any verdict — a sweep that didn't interact terminates with verdict 'Incomplete'. Walks threads, exercises every element, runs the multi-pane stress matrix, visual polish sweep, component perfection checklist, automated a11y (axe-core), pragmatic performance budget (LCP/CLS/INP), scenario battery (11 scenarios), and stress recipes including the real-flavour data battery. Hard gates: console errors/warnings = 0, network 5xx = 0, layout collapse = 0, axe Critical/Serious = 0, perf budget green. Audit-the-audit meta-check rejects rushed reports. Each finding has reproduction steps, evidence path, and suspected code location. Trigger with 'ux audit', 'walkthrough', 'qa sweep', 'audit the app', 'dogfood this', 'check all pages', 'find what's broken', 'stress the UI'.

Frontend & Design2.8K installs

tailwind-v4-shadcn

jezweb/claude-skills

Set up Tailwind v4 with shadcn/ui using @theme inline pattern and CSS variable architecture. Four-step pattern: CSS variables, Tailwind mapping, base styles, automatic dark mode. Prevents 8 documented errors. Use when initializing React projects with Tailwind v4, or fixing colors not working, tw-animate-css errors, @theme inline dark mode conflicts, @apply breaking, v3 migration issues.

Frontend & Design2.6K installs

Popular frontend & design skills

View category →

setup-matt-pocock-skills

mattpocock/skills

Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.

Frontend & Design1.1M installs

frontend-design

anthropics/skills

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

OfficialFrontend & Design1M installs

hyperframes-animation

heygen-com/hyperframes

All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.

prototype

mattpocock/skills

Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.

Frontend & Design999.2K installs

hyperframes-core

heygen-com/hyperframes

The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.

Frontend & Design930.5K installs

vercel-react-best-practices

vercel-labs/agent-skills

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

OfficialFrontend & Design843.1K installs