一键导入
ui-refactor
UI重构标准化流程技能。用于页面/组件的视觉重构、主题适配、交互优化。当用户请求重构页面、优化UI、修复样式问题时调用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
UI重构标准化流程技能。用于页面/组件的视觉重构、主题适配、交互优化。当用户请求重构页面、优化UI、修复样式问题时调用。
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | ui-refactor |
| description | UI重构标准化流程技能。用于页面/组件的视觉重构、主题适配、交互优化。当用户请求重构页面、优化UI、修复样式问题时调用。 |
设计哲学:UI 应该像一个精致的暗色画廊,退后一步让 AI 生成的内容占据中心舞台。
Luminous Asymmetry 原则:
核心色板(Core Tokens):
/* 主色调 - 活力紫色 */
--primary: #ba9eff /* 表面着色 / 光晕 */
--primary-dim: #8455ef /* 淡化主色 */
--primary-container: #ae8dff /* 主要操作基础 */
/* 次色调 - 霓虹青色 */
--secondary: #34b5fa /* 进度与强调 */
--secondary-dim: #17a8ec /* 淡化次色 */
--secondary-container: #f3f8ff /* 次色容器 */
/* 三色调 - 电光洋红 */
--tertiary: #ec63ff /* 创意火花 */
--tertiary-dim: #f487ff /* 淡化三色 */
--tertiary-container: #19001e /* 三色容器 */
/* 背景色系 */
--background: #070d1f /* 虚空 */
--surface: #070d1f /* 表面 */
--surface-variant: #1c253e /* 表面变体 */
--surface-container-low: #0c1326 /* 低层容器 */
--surface-container-highest: #11192e /* 最高层容器 */
--surface-container-lowest: #000000 /* 最低层容器 */
/* 文字颜色 */
--on-background: #dfe4fe /* 背景上的文字 */
--on-surface: #dfe4fe /* 表面上的文字 */
--on-surface-variant: #a5aac2 /* 表面变体上的文字 */
--on-primary: #39008c /* 主色上的文字 */
--on-primary-container: #2b006e /* 主色容器上的文字 */
--on-secondary: #003047 /* 次色上的文字 */
--on-tertiary: #3d0047 /* 三色上的文字 */
/* 边框颜色 */
--outline: #6f758b /* 轮廓 */
--outline-variant: #41475b /* 轮廓变体 */
/* 错误色 */
--error: #ff6e84 /* 错误 */
--error-dim: #d73357 /* 淡化错误 */
--error-container: #a70138 /* 错误容器 */
严格禁止:使用传统 1px solid 边框进行结构分区
正确做法:使用 Tonal Transitions(色调转换)
surface 转换到 surface-container-low 来区分例外情况:仅在需要显式边界时(如输入框)使用 "Ghost Border"
实现标志性感觉:避免静态扁平颜色用于主要表面
签名渐变:
/* 主要 CTA */
background: linear-gradient(135deg, var(--primary) 0%, var(--primary-dim) 100%);
/* 次要渐变 */
background: linear-gradient(135deg, var(--secondary) 0%, var(--secondary-dim) 100%);
/* 创意渐变 */
background: linear-gradient(135deg, var(--tertiary) 0%, var(--tertiary-dim) 100%);
Glassmorphism(玻璃态):
surface-variant(40-60% 不透明度)backdrop-filter: blur(20px) 到 blur(40px)outline-variant 在 15% 不透明度)Plus Jakarta Sans - Display & Headlines
-0.02emManrope - Body & Labels
body-sm 下,AI 提示和技术元数据也清晰/* Display-LG - Hero 语句或 AI 生成标题 */
font-size: 3.5rem;
font-family: 'Plus Jakarta Sans', sans-serif;
font-weight: 800;
letter-spacing: -0.02em;
/* Headline-MD - 卡片标题,赋予"杂志"感觉 */
font-size: 1.75rem;
font-family: 'Plus Jakarta Sans', sans-serif;
font-weight: 700;
/* Body-LG - 正文内容 */
font-size: 1.125rem;
font-family: 'Manrope', sans-serif;
/* Label-MD - 技术 AI 参数 */
font-size: 0.75rem;
font-family: 'Manrope', sans-serif;
letter-spacing: 0.1em;
text-transform: uppercase;
深度原则:深度不是距离用户的距离,而是光的折射
不使用阴影,而是"堆叠"层级:
/* Level 0 (Base) */
background: var(--surface);
/* Level 1 (Sections) */
background: var(--surface-container-low);
/* Level 2 (Cards) */
background: rgba(17, 25, 38, 0.6); /* surface-container-highest at 60% opacity */
backdrop-filter: blur(30px);
当组件需要"浮动"时(如下拉菜单或模态框),使用环境光晕而非灰色阴影:
/* 光晕令牌 */
box-shadow: 0 40px rgba(186, 158, 255, 0.08);
/* 解释 */
blur: 40px
spread: 0
color: var(--primary) at 8% opacity
/* 效果:模拟屏幕光线击中元素后面的表面 */
如果元素需要边界(如输入框),使用 Ghost Border:
outline-variant 令牌在 20% 不透明度Primary 按钮:
<button style={{
background: 'linear-gradient(135deg, var(--primary) 0%, var(--primary-dim) 100%)',
color: 'var(--on-primary-container)',
padding: '20px 40px',
borderRadius: '14px',
fontSize: '1rem',
fontWeight: 'bold',
transition: 'all 0.3s ease',
boxShadow: '0 8px 24px rgba(186, 158, 255, 0.4)',
}} />
交互效果:
surface-tint 光晕强度,scale 1.02xlabel-md (bold),颜色:var(--on-primary)Secondary 按钮:
<button style={{
background: 'rgba(28, 37, 62, 0.4)',
backdropFilter: 'blur(40px)',
color: 'var(--on-background)',
padding: '20px 40px',
borderRadius: '14px',
fontSize: '1rem',
fontWeight: 'bold',
transition: 'all 0.3s ease',
}} />
The Workspace(工作空间):
<div style={{
background: 'rgba(28, 37, 62, 0.4)',
backdropFilter: 'blur(30px)',
border: '1px solid rgba(65, 71, 91, 0.15)',
borderRadius: '3rem', /* xl */
padding: '2rem',
}}>
{/* 内容 */}
</div>
规则:
surface-container-highest (40% 不透明度)30pxoutline-variant at 15%)xl (3rem) 用于外部容器;lg (2rem) 用于内部内容卡片spacing-6 (2rem) 垂直留白分隔标题和正文The Prompt Engine(提示词引擎):
<input style={{
background: 'var(--surface-container-lowest)',
border: '1px solid rgba(65, 71, 91, 0.2)',
borderRadius: '14px',
padding: '16px 20px',
fontSize: '1.125rem',
fontFamily: 'Manrope, sans-serif',
transition: 'all 0.3s ease',
}} />
Focus 状态:
<input style={{
border: '1px solid var(--primary)',
boxShadow: '0 0 20px rgba(186, 158, 255, 0.3)',
}} />
Metadata(元数据):
<span style={{
background: 'rgba(52, 181, 250, 0.2)',
backdropFilter: 'blur(20px)',
padding: '6px 16px',
borderRadius: '9999px',
fontSize: '0.75rem',
fontFamily: 'Manrope, sans-serif',
letterSpacing: '0.1em',
textTransform: 'uppercase',
fontWeight: 'bold',
color: 'var(--secondary)',
}}>
GPT-4
</span>
surface-container-low vs surface 分隔侧边栏和主舞台surface (#070d1f) 保持"午夜"深度14px(按钮)。AI 美学应该感觉有机和可接近,不是工业的spacing-8 (2.75rem) 间隙。空间是奢华虽然玻璃态是美学的,但确保所有 on-surface 文本在模糊背景上保持 4.5:1 对比度。使用 primary-fixed-dim 令牌用于次要操作,以确保可见性而不破坏暗色模式沉浸感。
#ffffff, rgba(255,255,255,0.5))正确:使用 CSS 变量
<div style={{
background: 'rgba(28, 37, 62, 0.4)',
backdropFilter: 'blur(40px)',
color: 'var(--on-background)',
border: '1px solid rgba(65, 71, 91, 0.15)',
}}>
错误:硬编码颜色
<div style={{
background: '#1e293b',
color: 'white',
border: '1px solid rgba(255,255,255,0.1)',
}}>
// 使用 useState 管理悬停状态
const [isHovered, setIsHovered] = useState(false);
<div
style={{
background: isHovered ? 'rgba(255, 255, 255, 0.1)' : 'rgba(28, 37, 62, 0.4)',
transform: isHovered ? 'scale(1.05)' : 'scale(1)',
transition: 'all 0.3s ease',
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
map 循环中使用 useState!important 覆盖样式1. 读取目标文件,理解当前结构
2. 识别硬编码颜色值
3. 识别旧组件依赖(Card、Button等)
4. 评估交互状态管理方式
5. 检查主题适配问题
6. 检查是否违反 "No-Line" 规则
1. 确定页面主题色(参考功能类型)
2. 规划组件层级结构(Level 0/1/2)
3. 设计交互状态变化(scale + 光晕)
4. 确定需要提取的公共样式
5. 设计 Luminous Asymmetry 布局
1. 替换硬编码颜色为 CSS 变量
2. 移除传统 1px solid 边框,使用 Tonal Transitions
3. 实现玻璃态效果(半透明 + blur)
4. 添加环境光晕而非灰色阴影
5. 添加悬停/点击交互状态
6. 应用渐变到主要 CTA
7. 确保主题切换兼容
1. 运行 TypeScript 类型检查
2. 在亮色模式下验证
3. 在暗色模式下验证
4. 测试交互反馈(scale + 光晕)
5. 检查响应式布局
6. 验证无障碍对比度
import React, { useState } from 'react';
import { Link } from 'react-router-dom';
export default function PageTemplate() {
const [backHover, setBackHover] = useState(false);
return (
<div style={{
minHeight: '100vh',
background: 'var(--surface)',
color: 'var(--on-background)',
fontFamily: 'Manrope, sans-serif',
position: 'relative',
overflowX: 'hidden',
}}>
{/* Header - Level 1 */}
<header style={{
position: 'fixed',
top: 0,
left: 0,
right: 0,
height: '80px',
background: 'rgba(7, 13, 31, 0.6)',
backdropFilter: 'blur(24px)',
borderBottom: '1px solid rgba(255, 255, 255, 0.1)',
boxShadow: '0 20px 50px rgba(139, 92, 246, 0.1)',
zIndex: 50,
}}>
<div style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '0 32px',
height: '100%',
maxWidth: '1440px',
margin: '0 auto',
}}>
<div style={{
fontSize: '24px',
fontWeight: 900,
letterSpacing: '-0.02em',
color: 'var(--on-background)',
background: 'linear-gradient(135deg, var(--primary) 0%, var(--tertiary) 100%)',
WebkitBackgroundClip: 'text',
WebkitTextFillColor: 'transparent',
backgroundClip: 'text',
fontFamily: 'Plus Jakarta Sans, sans-serif',
cursor: 'pointer',
}}>
开演AI
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: '16px' }}>
<Link to="/back" style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '48px',
height: '48px',
borderRadius: '50%',
textDecoration: 'none',
background: backHover
? 'linear-gradient(135deg, var(--primary) 0%, var(--primary-dim) 100%)'
: 'rgba(28, 37, 62, 0.4)',
backdropFilter: 'blur(40px)',
color: 'var(--on-background)',
transition: 'all 0.3s ease',
}}
onMouseEnter={() => setBackHover(true)}
onMouseLeave={() => setBackHover(false)}
>
←
</Link>
</div>
</div>
</header>
{/* Content - Level 0 */}
<main style={{
paddingTop: '120px',
paddingBottom: '80px',
padding: '24px',
position: 'relative',
}}>
{/* 页面内容 */}
</main>
</div>
);
}
function GlassCard({ title, children }) {
const [isHovered, setIsHovered] = useState(false);
return (
<div
style={{
background: isHovered ? 'rgba(255, 255, 255, 0.1)' : 'rgba(28, 37, 62, 0.4)',
backdropFilter: 'blur(30px)',
border: '1px solid rgba(65, 71, 91, 0.15)',
borderRadius: '3rem',
padding: '2rem',
transition: 'all 0.3s ease',
transform: isHovered ? 'translateY(-4px) scale(1.02)' : 'translateY(0) scale(1)',
boxShadow: isHovered ? '0 40px rgba(186, 158, 255, 0.08)' : 'none',
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{title && (
<h2 style={{
fontSize: '1.75rem',
fontFamily: 'Plus Jakarta Sans, sans-serif',
fontWeight: 700,
color: 'var(--on-background)',
marginBottom: '2rem',
letterSpacing: '-0.02em',
}}>{title}</h2>
)}
{children}
</div>
);
}
function GlassButton({ variant = 'primary', children, onClick }) {
const [isHovered, setIsHovered] = useState(false);
const styles = {
primary: {
background: isHovered
? 'linear-gradient(135deg, var(--primary) 0%, var(--primary-dim) 100%)'
: 'linear-gradient(135deg, var(--primary-dim) 0%, var(--primary) 100%)',
color: 'var(--on-primary-container)',
border: 'none',
boxShadow: isHovered ? '0 8px 24px rgba(186, 158, 255, 0.6)' : '0 8px 24px rgba(186, 158, 255, 0.4)',
},
secondary: {
background: isHovered ? 'rgba(255, 255, 255, 0.1)' : 'rgba(28, 37, 62, 0.4)',
backdropFilter: 'blur(40px)',
color: 'var(--on-background)',
border: '1px solid rgba(65, 71, 91, 0.15)',
boxShadow: 'none',
},
};
return (
<button
onClick={onClick}
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '8px',
padding: '20px 40px',
borderRadius: '14px',
fontSize: '1rem',
fontWeight: 'bold',
fontFamily: 'Manrope, sans-serif',
cursor: 'pointer',
transition: 'all 0.3s ease',
transform: isHovered ? 'scale(1.05)' : 'scale(1)',
...styles[variant],
}}
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{children}
</button>
);
}
function GlassInput({ placeholder, type = 'text', value, onChange }) {
const [isFocused, setIsFocused] = useState(false);
return (
<input
type={type}
value={value}
onChange={onChange}
placeholder={placeholder}
style={{
background: 'var(--surface-container-lowest)',
border: isFocused
? '1px solid var(--primary)'
: '1px solid rgba(65, 71, 91, 0.2)',
borderRadius: '14px',
padding: '16px 20px',
fontSize: '1.125rem',
fontFamily: 'Manrope, sans-serif',
color: 'var(--on-background)',
transition: 'all 0.3s ease',
outline: 'none',
boxShadow: isFocused ? '0 0 20px rgba(186, 158, 255, 0.3)' : 'none',
}}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
/>
);
}
原因:使用了硬编码颜色值 解决:替换为对应的 CSS 变量
原因:在 map 循环中使用 useState 解决:将悬停状态提升到父组件,使用 id 或索引管理
原因:背景不透明度过高或模糊度不够 解决:
原因:使用了传统边框而非色调转换 解决:
原因:在深色玻璃背景上使用了浅色文字 解决:
on-background 或 on-surface 变量primary-fixed-dim重构完成后,按以下清单逐项检查:
□ 使用 Luminous Asymmetry(非对称布局)
□ 移除传统 1px solid 边框,使用 Tonal Transitions
□ 实现玻璃态效果(半透明 + blur)
□ 应用渐变到主要 CTA
□ 使用环境光晕而非灰色阴影
□ 使用 Plus Jakarta Sans 和 Manrope 字体
□ 字体层次正确(Display-LG, Headline-MD, Body-LG, Label-MD)
□ 悬停状态有明显视觉反馈(scale + 光晕)
□ 对比度符合 WCAG 2.1 AA 标准
□ 无 TypeScript 类型错误
□ 无 console 警告/错误
□ 无硬编码颜色值
□ 动画过渡流畅
□ 响应式布局正常
□ 无障碍功能完整