跳到正文
DEV Community· Chloe Chen·· 4 小時前AI 評分58

plugin87/ux-ui-agent-skills 評測:用建置檢查把元件庫無障礙要求納入驗證

Enforcing Accessibility Gates in Component Libraries: plugin87/ux-ui-agent-skills Review

AI 導讀

作者在客戶專案中使用 plugin87/ux-ui-agent-skills 遷移 React 元件庫,三週內由建置閘門捕捉 14 項人工 QA 漏掉的無障礙回歸。該套件提供 52 種元件模式和 50 個驗證閘門,針對 WCAG 2.2 AA/AAA 要求,以可執行測試檢查焦點管理及鍵盤操作。作者指出,閘門不涵蓋視覺回歸測試,而自訂元件的初始設定需時 2-3 小時。

正文

The Problem: LLMs Generate Plausible Garbage

When you ask Claude or GPT to build a modal dialog with "proper accessibility," you'll get role="dialog" and aria-labelledby attributes. Ship it to production and discover VoiceOver users are trapped inside the modal because focus management is broken.

The root cause: code generation optimizes for syntactic correctness, not runtime behavior. Most component skills teach the model ARIA vocabulary without enforcing the invariants that make it work.

What plugin87/ux-ui-agent-skills Does Differently

This repository packages 52 production-grade component patterns (modals, dropdowns, tabs, carousels) with 50 objective verification gates that fail your build if the output violates WCAG 2.2 AA/AAA requirements.

Key architectural decisions:

  1. DTCG token contracts first: Design tokens follow the W3C Design Token Community Group spec, so Tailwind utility classes map to semantic color/spacing/typography tokens that survive theme switches.

  2. Framework-agnostic primitives: The skill set teaches Claude to reason about accessible state machines (disclosure widgets, comboboxes) independent of React/Vue/Svelte, then emit framework-specific bindings.

  3. Objective gates over subjective prompts: Instead of "make sure focus is managed," the skill includes executable tests (using tools like axe-core + Playwright) that physically verify focus trap behavior and keyboard navigation sequences.

Integration Example: Dropdown with Live Region Announcements

When I integrated this into our design system migration, the skill generated a Radix Primitives dropdown that handles an edge case our team missed:

import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import { VisuallyHidden } from '@radix-ui/react-visually-hidden';

export function AccessibleDropdown({ items, onSelect }) {
  const [announcement, setAnnouncement] = React.useState('');

  return (
    <>
      <DropdownMenu.Root>
        <DropdownMenu.Trigger className="px-4 py-2 bg-primary-600 text-white rounded-md">
          Options
        </DropdownMenu.Trigger>

        <DropdownMenu.Portal>
          <DropdownMenu.Content
            className="min-w-[220px] bg-white rounded-md shadow-lg p-1"
            onCloseAutoFocus={(e) => e.preventDefault()}
          >
            {items.map((item) => (
              <DropdownMenu.Item
                key={item.id}
                className="px-3 py-2 rounded hover:bg-gray-100 focus:bg-gray-100 outline-none cursor-pointer"
                onSelect={() => {
                  onSelect(item);
                  setAnnouncement(`${item.label} selected`);
                }}
              >
                {item.label}
              </DropdownMenu.Item>
            ))}
          </DropdownMenu.Content>
        </DropdownMenu.Portal>
      </DropdownMenu.Root>

      <VisuallyHidden role="status" aria-live="polite" aria-atomic="true">
        {announcement}
      </VisuallyHidden>
    </>
  );
}

Why this matters: The live region announces selection changes to screen reader users without visual flash. Most component libraries skip this because sighted QA never catches it.

The Build Gate That Saved Us

Our CI pipeline now runs:

npx playwright test --grep @a11y

One of the generated tests physically verifies focus behavior:

test('dropdown focus trap @a11y', async ({ page }) => {
  await page.goto('/dropdown-demo');
  await page.click('[data-testid="dropdown-trigger"]');

  // Verify focus enters the menu
  await page.keyboard.press('Tab');
  const firstItem = page.locator('[role="menuitem"]').first();
  await expect(firstItem).toBeFocused();

  // Verify Escape closes and returns focus
  await page.keyboard.press('Escape');
  await expect(page.locator('[data-testid="dropdown-trigger"]')).toBeFocused();
});

This caught a regression where a junior dev removed onCloseAutoFocus={(e) => e.preventDefault()} during a refactor, breaking keyboard navigation for 8% of our user base.

TailwindCSS Integration: Container Queries for Responsive Components

The skill set includes a micro-interaction pattern leveraging Tailwind v4's native container query support:

@layer components {
  .adaptive-card {
    container-type: inline-size;
    @apply bg-white rounded-lg shadow;
  }

  .adaptive-card__title {
    @apply text-lg font-semibold;
  }

  @container (min-width: 400px) {
    .adaptive-card__title {
      @apply text-2xl;
    }
    .adaptive-card__content {
      @apply grid grid-cols-2 gap-4;
    }
  }
}

This eliminates layout thrashing from JavaScript-based resize observers. Our Lighthouse performance score jumped from 78 to 94 after migrating 23 card components to this pattern.

When to Use This vs. shadcn/ui Directly

If you're building a standard CRUD app, shadcn/ui's pre-built components are faster. Use plugin87/ux-ui-agent-skills when:

  1. You need to teach an LLM your design system's accessibility requirements
  2. You're migrating legacy components and want automated compliance checks
  3. You're in a regulated industry (healthcare, finance, government) where WCAG violations carry legal risk

The 138 design system references (Material, Spectrum, Carbon, etc.) help Claude generate components that match your existing visual language without manual token mapping.

Limitations I Hit

No visual regression testing: The gates verify semantic HTML and ARIA, but won't catch a button that's visually 2px too small for WCAG 2.2's 24×24 touch target requirement. You still need Percy or Chromatic.

Learning curve for custom components: The DTCG token structure assumes you've already defined semantic design tokens. If you're still using raw Tailwind utilities everywhere, the initial setup takes 2-3 hours.

Conclusion

After three weeks using plugin87/ux-ui-agent-skills on a client project (migrating a React component library to Radix + Tailwind v4), the build gates caught 14 accessibility regressions that our manual QA process missed.

The killer feature isn't the 52 component patterns—it's the shift from "Claude, make this accessible" (subjective, unverifiable) to "the build fails if focus order is wrong" (objective, enforceable).

If you're tired of shipping ARIA soup that looks correct in the inspector but breaks for real users, this skill set forces the issue at merge time instead of in production.

來源:DEV Community · dev.to