Open Claude UI
中文
v1 · Claude UI Design Handbook (1.x)

Claude Frontend Design: UI & Motion Rules for AI Agents

Claude design system rules for AI coding agents: surface map, type scale, double focus ring, 7-stop fade mask, single closed border and 5-step button sizes.

中文版Last updated:

⬅️ Previous: Chapter 7: Engineering Config & Code Asset Overview · 📚 Back to the 1.x overview


This chapter is a rule set for AI coding agents that build front-end UI on the Claude design system (CDS) as documented in this handbook: the surface map, type scale, focus rings, spring presets, the single closed border principle, input guards and a self-check list. It is a translation of the Chinese handbook chapter; every value is copied from it unchanged, and code blocks are reproduced as-is.

Intended for: Cursor Agent, Claude Code, GitHub Copilot, Windsurf, Devin, Antigravity and any autonomous or assistive AI agent with access to the codebase.
Core mission: guide AI agents that read, generate or refactor front-end components and pages based on the Claude Design System (CDS) to follow the production specs actually extracted with REA v6.5.0: editorial warmth, second-order spring dynamics, the single closed border principle and zero copyright risk. No unverified guesswork.


🧭 Contents


8.1 Agent role and design philosophy

When an agent uses CDS in this project or a downstream project, it must understand what fundamentally sets the Anthropic Claude interface apart:

  1. Editorial Warmth:
    • Never generate highly saturated cyberpunk blue/purple gradients or glaring neon colors.
    • The main brand accent is clay (Clay: #d97757 / Hover: #cc5a36 / Light: #fbf3ef).
    • Backgrounds use a slightly warm paper gray (--cds-surface-0: #f9f9f7 / dark --cds-surface-0: #0b0b0b); never overuse harsh #000000 in dark mode (except the code highlight background #0d0d0c).
  2. Low-contrast Surface Layering:
    • Drop the habit of hard 1px black borders. Build depth with the small lightness differences between the Surface 0 ~ 3 layers (only 1%~3% per step) and border-subtle hairlines (10% in light mode / 9% in dark mode).
  3. Tactile Organic Physics:
    • Never use the CSS defaults ease or linear, or exaggerated, overly bouncy animation.
    • All movement, scaling and expansion must use a real spring model based on mass, stiffness and damping (ClaudeMotionPresets.ts) or the 15-stop CSS linear() spring curve.

8.2 Design tokens and the color reference contract

All styles must reference the predefined CSS variables or Tailwind extension classes first (see code-examples/cds-theme.css and code-examples/tailwind.config.js):

1. Surface map (per REA v6.5.0 evidence)

/* Agent 编写组件时应使用的背景颜色映射 */
:root {
  --cds-surface-0: var(--cds-gray-20); /* #f9f9f7 侧边栏/画布底层 Canvas */
  --cds-surface-1: var(--cds-gray-10); /* #fcfcfb 页面主聊天画布背景 */
  --cds-surface-2: var(--cds-gray-0);  /* #ffffff 消息卡片表面 */
  --cds-surface-3: var(--cds-gray-0);  /* #ffffff 输入框容器/高层浮层 */
  --cds-surface-popover: var(--cds-gray-0); /* #ffffff 悬浮 Popover 表面 */
}

[data-mode="dark"], .dark {
  --cds-surface-0: var(--cds-gray-900); /* #0b0b0b 暗色侧边栏/底色 */
  --cds-surface-1: var(--cds-gray-850); /* #151515 暗色主聊天背景 */
  --cds-surface-2: var(--cds-gray-830); /* #1a1a19 暗色卡片表面 */
  --cds-surface-3: var(--cds-gray-800); /* #20201f 暗色输入框与高层浮层 */
  --cds-surface-popover: var(--cds-gray-750); /* #2c2c2a 悬浮气泡表面 */
}

2. Text and type scale

--cds-text-primary:   #151515; /* 一级主要正文、标题 / [Dark]: #f5f5f5 */
--cds-text-secondary: #525252; /* 二级辅助文字、副标题 / [Dark]: #a3a3a3 */
--cds-text-muted:     #8a8a8a; /* 三级微弱文字、快捷键、占位符 / [Dark]: #666666 */

3. Double focus ring with a clay diffuse ring

For focus states on buttons, inputs and dropdowns, always use a two-layer ring shadow (a subtle inner ring and an outer clay diffuse ring):

--cds-focus-shadow: inset 0 0 0 1px var(--cds-surface-1), 0 0 0 1.5px var(--cds-clay), 0 0 6px 1px rgba(217, 119, 87, 0.25);

8.3 Motion physics: decision tree for four spring presets

When writing interaction animation, an agent must import the standard spring configs from code-examples/ClaudeMotionPresets.ts and choose by scenario:

graph TD
    Trigger["用户交互触发"]
    
    Trigger --> Type{"交互类型判断"}
    
    Type -->|"按钮点击 / Pill 切换 / Tab 移动"| Snappy["SPRING_SNAPPY<br/>stiffness: 600, damping: 30<br/>超调 +8.8%, 时延 0.22s"]
    Type -->|"开关切换 / Badge 入场 / 成功微反馈"| Bouncy["SPRING_BOUNCY<br/>stiffness: 380, damping: 18<br/>超调 +19.4%, 时延 0.58s"]
    Type -->|"对话框打开 / Thinking 展开 / 气泡进入"| Gentle["SPRING_GENTLE<br/>stiffness: 320, damping: 28<br/>超调 +1.8%, 时延 0.35s"]
    Type -->|"拖拽占位线碰撞 / 边缘吸附 / 抽屉关闭"| HeavySnap["SPRING_HEAVY_SNAP<br/>stiffness: 1200, damping: 80<br/>严格 0% 超调, 时延 0.14s"]

7-Stop Non-Linear Alpha Mask

When an agent implements edge fades on a scrolling viewport (the conversation, sidebar history, code blocks), a single linear gradient is not allowed; it must use the official 7 non-linear sample points calibrated to perceptual gamma:

mask-image: linear-gradient(
  to bottom,
  transparent,
  #0000000d calc(var(--cds-scroll-fade-top) * .15),
  #00000026 calc(var(--cds-scroll-fade-top) * .3),
  #0000004d calc(var(--cds-scroll-fade-top) * .45),
  #00000080 calc(var(--cds-scroll-fade-top) * .6),
  #000000b3 calc(var(--cds-scroll-fade-top) * .75),
  #000000d9 calc(var(--cds-scroll-fade-top) * .87),
  #000 var(--cds-scroll-fade-top),
  #000 calc(100% - var(--cds-scroll-fade-bottom)),
  #000000d9 calc(100% - var(--cds-scroll-fade-bottom) * .87),
  #000000b3 calc(100% - var(--cds-scroll-fade-bottom) * .75),
  #00000080 calc(100% - var(--cds-scroll-fade-bottom) * .6),
  #0000004d calc(100% - var(--cds-scroll-fade-bottom) * .45),
  #00000026 calc(100% - var(--cds-scroll-fade-bottom) * .3),
  #0000000d calc(100% - var(--cds-scroll-fade-bottom) * .15),
  transparent
);

8.4 Control atom rules and the single closed border principle

1. Single-Stroke Border Discipline

  • Core rule: never place a secondary button or feature Chip with its own border inside a bordered container (such as ChatComposer or AttachmentCard).
  • Correct approach: inline buttons inside a container must use border-none + bg-transparent, and signal interactivity only through the Surface background change and higher icon contrast on Hover.

2. The 5-step button size scale (per REA v6.5.0 evidence)

SizeHeightHorizontal paddingFont sizeBorder and radiusTactile curve
XS20px (h-5)6px (px-1.5)11px (text-[11px])4px (rounded)15-stop linear() spring curve
SM24px (h-6)8px (px-2)12px (text-xs)6px (rounded-md)15-stop linear() spring curve
MD28px (h-7)10px (px-2.5)13px (text-[13px])8px (rounded-lg)15-stop linear() spring curve
LG32px (h-8)12px (px-3)14px (text-sm)8px (rounded-lg)15-stop linear() spring curve
XL40px (h-10)16px (px-4)16px (text-base)10px (rounded-xl)15-stop linear() spring curve

3. Tabular Numbers

Anywhere counters, token gauges, audio waveform bars, timestamps or diff line numbers appear, declare tabular-nums explicitly to avoid horizontal jitter as digits change.


8.5 Interaction guards and edge cases

When writing interaction logic, an agent must include these 4 guards by default:

1. WebKit 500ms Post-Composition guard

When input-method composition ends in a text field, WebKit leaves a lingering composition flag for a few microseconds, so block it twice:

const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
  // 1. 标准合成标志位与 229 键码
  if (e.nativeEvent.isComposing || e.keyCode === 229) return;
  // 2. WebKit 500ms 延迟守卫拦截
  if (isWebKit && Math.abs(e.timeStamp - lastCompositionEndTime) < 500) return;

  if (e.key === 'Enter' && !e.shiftKey) {
    e.preventDefault();
    submitMessage();
  }
};

2. Anti-hijack scroll pinning during streaming (150ms Cooldown Latch)

While a streamed reply is being written, if the user scrolls up slightly to read history, never pull them back to the bottom. Interlock a 40px bottom tolerance with a 150ms cooldown timestamp:

const handleUserScroll = () => {
  lastUserScrollTimestamp.current = performance.now();
};

const shouldAutoScroll = () => {
  const isWithinBottomTolerance = scrollHeight - scrollTop - clientHeight <= 40;
  const isCooldownExpired = performance.now() - lastUserScrollTimestamp.current > 150;
  return isWithinBottomTolerance && isCooldownExpired;
};

3. Sandbox security and user activation gate (Iframe Security)

When handling Artifacts previews or injected external code:

  • always remove allow-same-origin to keep null-origin isolation;
  • verify the origin of cross-origin postMessage calls;
  • check the native event.userActivation before triggering system-level calls.

4. No external black-box audio assets (Procedural Audio Synthesis)

Never fetch or import unlicensed external .mp3 files in code. Synthesize chords with native Web Audio API oscillators, add smooth gain fades (to prevent pops), and keep the volume at a gentle 30% baseline.


8.6 Quick assembly guide for the production component library (30 modules)

When an agent needs to implement a page feature, look it up and reuse it directly in code-examples/:

code-examples/
├── CdsButton.tsx                    # 5 级尺寸 5 大变体标准按钮 (15 阶 linear 弹簧)
├── SegmentedControl.tsx             # 999px 全圆角滑动分段胶囊 (2px 轨道几何)
├── StatusIndicators.tsx             # 6px 状态指示灯与骨架屏扫光
├── ConfirmationDialog.tsx           # 16px 模态确认对话框 (双环弥散投影)
├── AttachmentCard.tsx               # 7.5rem 磁贴与行内附件芯片
├── ChatComposer.tsx                 # 20px 核心输入终端
├── ChatMessageBubbles.tsx           # 会话流双态气泡 (18px 圆角与 clamp 文本 stop)
├── ThinkingAccordion.tsx            # 思考过程状态机折叠组件 (Grid 0fr<->1fr)
├── RichComposerWithMentions.tsx     # 指令与提及富文本编辑器 (WebKit 500ms 守卫)
├── ModelSwitcherWithTokenGauge.tsx  # 模型切换与四色 Token 显存表
├── McpToolDecisionCard.tsx          # MCP 决策与授权卡片
├── ClaudeMotionPresets.ts           # 4 套物理弹簧预设
├── ReasoningAmbientGlow.tsx         # 陶土漫反射光效 (wl-glow & 1.1s epitaxy-sweep)
├── ScrollFadeContainer.tsx          # 原生 CSS Scroll-Driven 7 档非线性遮罩容器
├── ClaudeAudioPlayer.ts             # Web Audio 纯代码合成音效
├── LiveMicActivityBars.tsx          # 6 频段非线性麦克风波形柱 (0.7 Gamma)
├── MediaLightboxViewer.tsx          # 仿射变换光标锚点画廊 (75vw 跑道)
├── useClaudeSharedElementTransition.ts # View Transitions 共享元素变形 Hook
├── ArtifactsSplitPaneResizer.tsx    # 50/50 居中吸附双栏分割条 (4px 死区)
├── EpitaxyIframeBridge.tsx          # 沙箱隔离双向通信桥 (null-origin 隔离)
├── StreamingDiffViewer.tsx          # 等宽流式代码差异对比 (--diffs-* 变量)
├── CodeBlock.tsx                    # 12px 纯黑底色高亮代码块
├── createClaudeMainWindow.ts        # Electron 桌面窗口工厂 (WebContentsView 解耦)
├── ClaudeDesktopHeader.tsx          # macOS 74px 避让沉浸式顶栏
├── DraggableSessionList.tsx         # 拓扑重排与微倾斜投影
├── CoworkAgentCanvas.tsx            # 多 Agent 协同网格看板
├── useClaudeScrollPinning.ts        # 视口图钉防抢夺 Hook (150ms 冷却)
├── ContainerResponsiveBar.tsx       # 4 阶容器查询响应栏
├── useClaudeRovingFocus.ts          # W3C WAI-ARIA 焦点漫游 Hook
└── useRateLimitBackoff.ts           # 指数退避与全抖动重试 (3 次上限保护)

8.7 Agent self-check and quality gate checklist

Before finishing any front-end code change or submitting output, the agent must check each item and run the verification:

  • Semantic tokens: are all styles using var(--cds-*) or the semantic Tailwind extension classes? (No arbitrary hard-coded colors.)
  • Spring physics: does all dynamic interaction come from ClaudeMotionPresets or the 15-stop linear() spring? (No hand-written animation without physical damping.)
  • Input guard: do text input events include the WebKit 500ms post-composition guard?
  • Dark mode: are background lightness contrast and text contrast correct under both :root and .dark?
  • Layout jitter: do frequently changing numbers and metrics have tabular-nums?
  • Single closed border: do secondary controls inside containers use border-none?
  • Build:
    npm run typecheck # 必须 0 TS 类型报错
    npm run build     # 必须成功输出 0 编译错误

⬅️ Chapter 7: Engineering Config & Code Asset Overview · 📚 1.x overview

Open Claude UI is an unofficial community analysis, MIT licensed. Claude is a trademark of Anthropic; this project is not affiliated with Anthropic.

On this page