Communitygithub.com

addyosmani/agent-skills

构建生产级、可访问、响应式的用户界面。适用于构建或修改界面和页面、创建组件、实现布局、满足 WCAG 无障碍要求、管理状态,或当输出需要看起来是生产级而非 AI 生成时。

agent-skills 是什么?

该技能指导 AI 智能体构建高质量、以用户为中心的前端界面,避免常见的“AI 审美”陷阱,如过度使用紫色、渐变和通用的轮播图。它强制采用真正的设计系统一致性,包括正确的间距、排版和语义颜色令牌。该技能提供了组件架构的具体模式(组合优于配置、分离数据获取与展示)、状态管理指南(从本地状态到全局状态)、以及 WCAG 2.1 AA 无障碍标准(键盘导航、ARIA 标签、焦点管理)。它还涵盖了响应式设计(移动优先)、加载状态(骨架屏)、乐观更新和有意义的状态(空状态、错误状态)。此技能适用于 Cursor、Claude Code 等基于聊天的编码环境中,通过引用驱动的 UI 质量和系统化的设计合同来确保视觉一致性,从而弥合 AI 生成代码与生产级工程标准之间的差距。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/addyosmani/agent-skills/tree/HEAD/skills/frontend-ui-engineering

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

前端 UI 工程

概述

构建可访问、高性能且视觉上经过打磨的生产级用户界面。目标是让 UI 看起来像是顶级公司的设计意识工程师构建的,而不是 AI 生成的。这意味着真正的设计系统一致性、适当的可访问性、深思熟虑的交互模式,并且没有通用的“AI 审美”。

何时使用

  • 构建新的 UI 组件或页面
  • 修改现有的面向用户界面
  • 实现响应式布局
  • 添加交互性或状态管理
  • 修复视觉或 UX 问题

组件架构

文件结构

将与组件相关的所有内容放在一起:

src/components/
  TaskList/
    TaskList.tsx          # 组件实现
    TaskList.test.tsx     # 测试
    TaskList.stories.tsx  # Storybook stories (如果使用)
    use-task-list.ts      # 自定义 Hook (如果状态复杂)
    types.ts              # 组件特定类型 (如果需要)

组件模式

组合优于配置:

// 好:可组合
<Card>
  <CardHeader>
    <CardTitle>任务</CardTitle>
  </CardHeader>
  <CardBody>
    <TaskList tasks={tasks} />
  </CardBody>
</Card>

// 避免:过度配置
<Card
  title="任务"
  headerVariant="large"
  bodyPadding="md"
  content={<TaskList tasks={tasks} />}
/>

保持组件专注:

// 好:只做一件事
export function TaskItem({ task, onToggle, onDelete }: TaskItemProps) {
  return (
    <li className="flex items-center gap-3 p-3">
      <Checkbox checked={task.done} onChange={() => onToggle(task.id)} />
      <span className={task.done ? 'line-through text-muted' : ''}>{task.title}</span>
      <Button variant="ghost" size="sm" onClick={() => onDelete(task.id)}>
        <TrashIcon />
      </Button>
    </li>
  );
}

将数据获取与展示分离:

// 容器:处理数据
export function TaskListContainer() {
  const { tasks, isLoading, error } = useTasks();

  if (isLoading) return <TaskListSkeleton />;
  if (error) return <ErrorState message="加载任务失败" retry={refetch} />;
  if (tasks.length === 0) return <EmptyState message="暂无任务" />;

  return <TaskList tasks={tasks} />;
}

// 展示:处理渲染
export function TaskList({ tasks }: { tasks: Task[] }) {
  return (
    <ul role="list" className="divide-y">
      {tasks.map(task => <TaskItem key={task.id} task={task} />)}
    </ul>
  );
}

状态管理

选择最简单有效的方法:

本地状态 (useState)           → 组件特定的 UI 状态
提升状态 (Lifted state)       → 在 2-3 个兄弟组件间共享
Context                       → 主题、认证、区域设置 (读多写少)
URL 状态 (searchParams)       → 过滤、分页、可共享的 UI 状态
服务端状态 (React Query, SWR) → 带缓存的远程数据
全局存储 (Zustand, Redux)    → 在整个应用中共享的复杂客户端状态

避免超过 3 层的属性透传。 如果你正在通过不直接使用这些属性的组件传递 props,请引入 context 或重构组件树。

设计系统一致性

参考驱动的 UI 质量

当产品需要独特的视觉方向时,在选择布局前收集证据:

  1. 搜索可信的参考目录或使用产品团队提供的参考资料。
  2. 研究两到三个相关屏幕。记录关于层次、密度、导航、控件、响应式行为和交互状态的决定。
  3. 在实现之前,将这些决定转化为简短的设计合同。命名屏幕的职责、主要操作、所需状态、响应式规则和要拒绝的模式。
  4. 使用产品自己的组件、令牌、内容和视觉语言重建有用的结构。切勿复制其他产品的品牌标识、专有文本、图片或精确布局。

将参考用作证据,而非模板。如果参考不可用,请记录假设,并对照产品现有的设计系统验证结果。

避免 AI 审美

AI 生成的 UI 具有可识别的模式。避免所有这些:

AI 默认值为什么是问题生产质量
到处都是紫色/靛蓝色模型默认选择视觉上“安全”的调色板,使每个应用看起来都一样使用项目实际的调色板
过度的渐变渐变增加了视觉噪音,并与大多数设计系统冲突与设计系统匹配的平面或微妙渐变
到处都是圆角 (rounded-2xl)最大圆角表示“友好”,但忽略了真实设计中圆角半径的层次结构来自设计系统一致的 border-radius
通用的英雄区域模板驱动的布局,与实际内容或用户需求无关内容优先的布局
Lorem ipsum 风格的文字占位符文本隐藏了真实内容会暴露的布局问题(长度、换行、溢出)现实的占位符内容
到处都是过大的内边距等量的慷慨内边距破坏了视觉层次并浪费了屏幕空间一致的间距比例
通用的卡片网格统一的网格是一种布局捷径,忽略了信息优先级和浏览模式目的驱动的布局
阴影过重的设计分层阴影增加了与内容竞争的深度,并在低端设备上减慢渲染速度微妙的阴影或无阴影,除非设计系统指定

间距与布局

使用一致的间距比例。不要发明值:

/* 使用比例:0.25rem 增量 (或项目所用的任何比例) */
/* 好 */  padding: 1rem;      /* 16px */
/* 好 */  gap: 0.75rem;       /* 12px */
/* 坏 */   padding: 13px;      /* 不在任何比例上 */
/* 坏 */   margin-top: 2.3rem; /* 不在任何比例上 */

排版

尊重标题层次:

h1 → 页面标题(每页一个)
h2 → 章节标题
h3 → 子章节标题
body → 默认文本
small → 次要/辅助文本

不要跳过标题级别。不要为非标题内容使用标题样式。

颜色

  • 使用语义化颜色令牌:text-primary、bg-surface、border-default — 而非原始 hex 值
  • 确保足够对比度(正常文本 4.5:1,大文本 3:1)
  • 不要仅依赖颜色传达信息(也使用图标、文本或图案)

可访问性 (WCAG 2.1 AA)

每个组件必须满足这些标准:

键盘导航

// 每个交互元素必须可通过键盘访问
<button onClick={handleClick}>点击我</button>        // ✓ 默认可聚焦
<div onClick={handleClick}>点击我</div>               // ✗ 不可聚焦
<div role="button" tabIndex={0} onClick={handleClick}    // ✓ 但更喜欢 <button>
     onKeyDown={e => {
       if (e.key === 'Enter') handleClick();
       if (e.key === ' ') e.preventDefault();
     }}
     onKeyUp={e => {
       if (e.key === ' ') handleClick();
     }}>
  点击我
</div>

ARIA 标签

// 为缺少可见文本的交互元素添加标签
<button aria-label="关闭对话框"><XIcon /></button>

// 为表单输入添加标签
<label htmlFor="email">电子邮件</label>
<input id="email" type="email" />

// 或者当没有可见标签时使用 aria-label
<input aria-label="搜索任务" type="search" />

焦点管理

// 内容更改时移动焦点
function Dialog({ isOpen, onClose }: DialogProps) {
  const closeRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    if (isOpen) closeRef.current?.focus();
  }, [isOpen]);

  // 打开时将焦点限制在对话框内
  return (
    <dialog open={isOpen}>
      <button ref={closeRef} onClick={onClose}>关闭</button>
      {/* 对话框内容 */}
    </dialog>
  );
}

有意义的空状态和错误状态

// 不要显示空白屏幕
function TaskList({ tasks }: { tasks: Task[] }) {
  if (tasks.length === 0) {
    return (
      <div role="status" className="text-center py-12">
        <TasksEmptyIcon className="mx-auto h-12 w-12 text-muted" />
        <h3 className="mt-2 text-sm font-medium">暂无任务</h3>
        <p className="mt-1 text-sm text-muted">创建一个新任务来开始吧。</p>
        <Button className="mt-4" onClick={onCreateTask}>创建任务</Button>
      </div>
    );
  }

  return <ul role="list">...</ul>;
}

响应式设计

移动优先设计,然后扩展:

// Tailwind:移动优先的响应式
<div className="
  grid grid-cols-1      /* 移动端:单列 */
  sm:grid-cols-2        /* 小屏:2列 */
  lg:grid-cols-3        /* 大屏:3列 */
  gap-4
">

在这些断点测试:320px、768px、1024px、1440px。

加载与过渡

// 骨架加载(内容区域不要使用加载旋转器)
function TaskListSkeleton() {
  return (
    <div className="space-y-3" aria-busy="true" aria-label="正在加载任务">
      {Array.from({ length: 3 }).map((_, i) => (
        <div key={i} className="h-12 bg-muted animate-pulse rounded" />
      ))}
    </div>
  );
}

// 乐观更新以提升感知速度
function useToggleTask() {
  const queryClient = useQueryClient();

  return useMutation({
    mutationFn: toggleTask,
    onMutate: async (taskId) => {
      await queryClient.cancelQueries({ queryKey: ['tasks'] });
      const previous = queryClient.getQueryData(['tasks']);

      queryClient.setQueryData(['tasks'], (old: Task[]) =>
        old.map(t => t.id === taskId ? { ...t, done: !t.done } : t)
      );

      return { previous };
    },
    onError: (_err, _taskId, context) => {
      queryClient.setQueryData(['tasks'], context?.previous);
    },
  });
}

参见

有关详细的可访问性要求和测试工具,请参阅 ../../references/accessibility-checklist.md。

常见辩解

辩解现实
"可访问性是个可有可无的东西"在许多司法管辖区这是一个法律要求,也是工程质量标准。
"我们以后再让它响应式"事后改造响应式设计比从头构建要困难 3 倍。
"设计尚未最终确定,所以我跳过样式"使用设计系统默认值。未设置样式的 UI 会给审阅者留下糟糕的第一印象。
"这只是一个原型"原型会变成生产代码。从一开始就打好基础。
"AI 审美暂时没问题"它暗示低质量。从一开始就使用项目实际的设计系统。

红旗警告

  • 组件超过 200 行(拆分它们)
  • 内联样式或任意像素值
  • 缺少错误状态、加载状态或空状态
  • 未测试键盘导航
  • 颜色作为状态的唯一指示符(红色/绿色没有文字或图标)
  • 通用的“AI 外观”(紫色渐变、超大卡片、通用布局)

验证

构建 UI 后:

  • 组件渲染无控制台错误
  • 所有交互元素可通过键盘访问(用 Tab 键浏览页面)
  • 屏幕阅读器可以传达页面的内容和结构
  • 响应式:在 320px、768px、1024px、1440px 正常工作
  • 酌情处理加载、空、错误、成功和权限状态
  • 遵循项目的设计系统(间距、颜色、排版)
  • 渲染结果通过最终的 UI 专属完成审查
  • 开发者工具或 axe-core 中没有无障碍警告

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

addyosmani/agent-skills

Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend.

addyosmani/agent-skills

Prepares production launches. Use when preparing to deploy to production, or when asking what needs to be in place before shipping. Use when you need a pre-launch checklist, when setting up monitoring, when planning a staged rollout, or when you need a rollback strategy.

addyosmani/browser-testing-with-devtools

Tests in real browsers via Chrome DevTools MCP. Use when building or debugging anything that runs in a browser. Use when you need to inspect the DOM, capture console errors, analyze network requests, profile performance, or verify visual output with real runtime data. Requires the chrome-devtools MCP server to be configured.

addyosmani/ci-cd-and-automation

Automates CI/CD pipeline setup. Use when setting up or modifying build and deployment pipelines. Use when you need to automate quality gates, configure test runners in CI, or establish deployment strategies.

addyosmani/code-review-and-quality

Conducts multi-axis code review. Use before merging any change. Use when reviewing code written by yourself, another agent, or a human. Use when you need to assess code quality across multiple dimensions before it enters the main branch.

addyosmani/code-simplification

Simplifies code for clarity. Use when refactoring code for clarity without changing behavior. Use when code works but is harder to read, maintain, or extend than it should be. Use when reviewing code that has accumulated unnecessary complexity.

addyosmani/constraint-driven-development

Establishes a project's quality bar as a written contract and stops agents quietly lowering it. Interviews the user on which dimensions matter, supplies sane default thresholds when they have no number in mind, records everything in CONSTRAINTS.md, and watches the diff for a weakened bar — new @ts-ignore or eslint-disable suppressions, skipped or deleted tests, assertions stripped out, unimplemented stubs, thresholds edited down. Use when no quality bar is written down, when the user says "set up constraints" or "define our standards", when the user wants dimensions they care about — accessibility, web performance, coverage — set up as enforced constraints, when an agent keeps silencing checks or skipping tests to get to green, when you need a coverage or performance threshold and don't know what number to pick, or when an agent writes more code than anyone will read.

addyosmani/debugging-and-error-recovery

Guides systematic root-cause debugging. Use when tests fail, builds break, behavior doesn't match expectations, or you encounter any unexpected error. Use when you need a systematic approach to finding and fixing the root cause rather than guessing.

addyosmani/deprecation-and-migration

Manages deprecation and migration. Use when removing old systems, APIs, or features. Use when migrating users from one implementation to another. Use when deciding whether to maintain or sunset existing code.

addyosmani/documentation-and-adrs

Records decisions and documentation. Use when making architectural decisions, changing public APIs, shipping features, or when you need to record context that future engineers and agents will need to understand the codebase.

addyosmani/doubt-driven-development

Subjects every non-trivial decision to a fresh-context adversarial review before it stands. Use when correctness matters more than speed, when working in unfamiliar code, when stakes are high (production, security-sensitive logic, irreversible operations), or any time a confident output would be cheaper to verify now than to debug later.

addyosmani/git-workflow-and-versioning

Structures git workflow practices. Use when making any code change. Use when committing, branching, resolving conflicts, or when you need to organize work across multiple parallel streams.

addyosmani/idea-refine

Refines raw ideas into sharp, actionable concepts through structured divergent and convergent thinking. Use when an idea is still vague, when you need to stress-test assumptions before committing to a plan, or when you want to expand options before converging on one. Triggers on "ideate", "refine this idea", or "stress-test my plan".

addyosmani/incremental-implementation

Delivers changes incrementally. Use when implementing any feature or change that touches more than one file. Use when you're about to write a large amount of code at once, or when a task feels too big to land in one step.

addyosmani/interview-me

Extracts what the user actually wants instead of what they think they should want. Achieves this through one-question-at-a-time interview until ~95% confidence about the underlying intent. Use when an ask is underspecified ("build me X" without "for whom" or "why now"), when the user explicitly invokes ("interview me", "grill me", "are we sure?", "stress-test my thinking"), or when you catch yourself silently filling in ambiguous requirements before any plan, spec, or code exists.

addyosmani/observability-and-instrumentation

Instruments code so production behavior is visible and diagnosable. Use when adding logging, metrics, tracing, or alerting. Use when shipping any feature that runs in production and you need evidence it works. Use when production issues are reported but you can't tell what happened from the available data.

addyosmani/performance-optimization

Optimizes application performance. Use when performance requirements exist, when you suspect performance regressions, or when Core Web Vitals or load times need improvement. Use when profiling reveals bottlenecks that need fixing.

addyosmani/planning-and-task-breakdown

Breaks work into ordered tasks. Use when you have a spec or clear requirements and need to break work into implementable tasks. Use when a task feels too large to start, when you need to estimate scope, or when parallel work is possible.

addyosmani/security-and-hardening

Hardens code against vulnerabilities. Use when handling user input, authentication, data storage, or external integrations. Use when building any feature that accepts untrusted data, manages user sessions, or interacts with third-party services.

addyosmani/source-driven-development

Grounds every implementation decision in official documentation. Use when you want authoritative, source-cited code free from outdated patterns. Use when building with any framework or library where correctness matters.

相关技能