with one click
ui-refactor
UI重构标准化流程技能。用于页面/组件的视觉重构、主题适配、交互优化。当用户请求重构页面、优化UI、修复样式问题时调用。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
UI重构标准化流程技能。用于页面/组件的视觉重构、主题适配、交互优化。当用户请求重构页面、优化UI、修复样式问题时调用。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
| 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 警告/错误
□ 无硬编码颜色值
□ 动画过渡流畅
□ 响应式布局正常
□ 无障碍功能完整