五、D2C:设计稿转代码
Semi Design的D2C功能是行业领先的设计稿转代码方案,由抖音前端团队自研。
5.1 D2C的整体定位
D2C(Design to Code)是将Figma设计稿一键转换为可用代码的技术方案。Semi D2C的定位是前端工程师的辅助工具,目标是加快前端还原设计稿的效率,降低人工编写UI模板的工作量。
核心能力边界:
5.2 与其他方案的差异
Semi D2C与其他方案最大的区别在于三点:
1.不依赖标注,原生提供组件级识别
Semi D2C方案提供了精准到组件级props的识别能力,对全部Semi基础组件的全部设计形态都提供了识别能力,不需要研发手动对组件进行标注。设计师使用Semi UI Kit搭建出的设计稿,全部都能被转换成真实的组件代码。
2.不改变设计师使用习惯
Semi的方案允许设计师继续通过Figma Variant变体的方式使用组件,与原有的设计流程一致。对设计师而言,无需安装额外插件,与原有习惯保持一致。
3.与设计系统深度打通
Semi由于自身掌控底层组件库资产,可以针对性做迭代适配修改。对Semi组件的支持天然可以做到更全、更合理,产物可以产出更合理的图层结构和AutoLayout支持,同时还能兼顾主题定制等业务场景。
5.3 使用方式
// 1. 在Figma中安装Semi D2C插件
// 2. 选中设计稿图层
// 3. 在右侧DevMode面板查看实时转换的JSX + CSS代码
// 4. 复制代码到项目中或通过插件直接写入本地仓库
支持的产物格式:
JSX + SCSS
JSX + Tailwind CSS
JSX + Emotion
JSON Schema(用于低代码平台)
5.4 D2C的优势
真实组件识别:将设计图层识别为具体的Semi组件,保留完整的组件语义
AutoLayout支持:产出具有Flexbox/Grid布局的自适应代码
主题兼容:完美支持Semi的主题定制功能
六、核心组件详解
Semi Design提供了丰富的组件,以下是在新版本中的核心组件更新和重要特性。
6.1 表单组件(Form)
Form组件是Semi中复杂度较高的组件之一,最新版本增强了静默校验功能,支持不触发UI错误展示的校验方式:
import { Form, Input, Button } from 'semi-ui';
function SilentValidationForm() {
const formApi = Form.useForm();
const handleSubmit = async () => {
// 普通校验:会显示错误UI
const isValid = await formApi.validate();
// 静默校验:仅返回校验结果,不显示错误UI
const isValidSilently = await formApi.validate({ silent: true });
if (isValidSilently) {
// 提交数据
}
};
return (
<Form getFormApi={(api) => formApi = api}>
<Form.Field field="username" label="用户名" rules={[{ required: true }]}>
<Input placeholder="请输入用户名" />
</Form.Field>
<Form.Field field="email" label="邮箱" rules={[{ type: 'email' }]}>
<Input placeholder="请输入邮箱" />
</Form.Field>
<Button onClick={handleSubmit}>提交</Button>
</Form>
);
}
6.2 表格组件(Table)
Table组件新增了筛选确认模式,支持带确认和重置按钮的筛选交互:
import { Table } from 'semi-ui';
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
filters: [
{ text: '张三', value: '张三' },
{ text: '李四', value: '李四' }
],
filterMultiple: true,
filterConfirmMode: true // 启用确认模式
}
];
function DataTable() {
return (
<Table
columns={columns}
dataSource={data}
scroll={
{ y: 400 }}
scrollToFirstRowOnChange={true}
/>
);
}
6.3 用户引导组件(UserGuide)
Semi提供了专门的新手引导组件UserGuide,用于帮助新用户快速了解页面功能。
import { useState, useRef } from 'react';
import { UserGuide, Button } from 'semi-ui';
function OnboardingGuide() {
const [visible, setVisible] = useState(false);
const btnRef = useRef();
const tableRef = useRef();
const steps = [
{
title: '欢迎使用',
description: '欢迎来到数据分析平台,让我们快速了解核心功能。',
target: () => document.body,
cover: 'https://example.com/welcome.png'
},
{
title: '核心操作',
description: '点击这个按钮可以新建数据报告。',
target: () => btnRef.current,
position: 'bottom',
showArrow: true
},
{
title: '数据表格',
description: '这里展示您所有的数据记录,支持排序和筛选。',
target: () => tableRef.current,
position: 'top'
}
];
return (
<div>
<Button ref={btnRef} onClick={() => setVisible(true)}>
开始引导
</Button>
<UserGuide
visible={visible}
steps={steps}
onFinish={() => setVisible(false)}
onSkip={() => setVisible(false)}
mode="popup"
theme="primary"
mask={true}
/>
</div>
);
}

6.4 Form新增PinCode组件
在需要验证码输入的场景,Semi提供了专门的PinCode组件:
import { Form } from 'semi-ui';
function VerificationForm() {
return (
<Form>
<Form.PinCode
field="verifyCode"
length={6}
onComplete={(value) => {
console.log('完整验证码:', value);
}}
/>
</Form>
);
}
6.5 聊天AI组件(Chat/AIChat)
Semi提供了聊天相关的专用组件,适合AI对话应用的场景:
Chat:基础聊天容器,支持avatar传入ReactNode(如矢量图标)
AIChatInput:AI对话输入框,支持clearContentOnGenerating属性
AIChatDialogue:AI对话气泡,支持escapeHtml防XSS
七、主题定制最佳实践
7.1 企业级主题定制流程
在企业级B端项目中,经常需要为不同客户提供个性化的UI风格。借助Semi的SCSS编译工具和Design Token系统,可以建立高效的团队主题协作机制:
设计侧主题定义:设计师通过Figma UI Kit + Semi DSM进行品牌主题定义
主题包构建:DSM生成包含token的npm主题包
研发侧集成:通过Vite插件引入主题包,覆盖默认样式
7.2 动态切换主题色
// ThemeProvider组件
import React, { createContext, useContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
// 基于主色生成完整调色板的算法
const generateColorPalette = (mainColor) => {
// 基于HSL/HSV色彩空间,对主色进行明度/饱和度调整,生成配套的辅助色[citation:10]
return {
lightest: adjustBrightness(mainColor, 20),
light: adjustBrightness(mainColor, 10),
base: mainColor,
dark: adjustBrightness(mainColor, -10),
darkest: adjustBrightness(mainColor, -20)
};
};
const applyThemeColors = (colors) => {
Object.entries(colors).forEach(([key, value]) => {
document.documentElement.style.setProperty(`--semi-${key}`, value);
});
};
return (
<ThemeContext.Provider value={
{ theme, setTheme, applyThemeColors }}>
{children}
</ThemeContext.Provider>
);
}
7.3 主题持久化
将用户选择的主题配置保存在服务端,实现主题设置的持久化:
// 保存用户主题偏好
async function saveUserThemePreference(userId, themeConfig) {
await fetch(`/api/users/${userId}/theme`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(themeConfig)
});
}
// 加载用户主题偏好
async function loadUserThemePreference(userId) {
const response = await fetch(`/api/users/${userId}/theme`);
const themeConfig = await response.json();
applyThemeToDocument(themeConfig);
}
八、常见问题与解决方案
8.1 样式隔离与覆盖问题
问题场景:在组件库中覆盖Semi默认样式不生效。
解决方案:使用Vite插件统一修改前缀:
// vite.config.js
semiPlugin({
prefixCls: 'my-app' // 将.semi-button替换为.my-app-button
})
8.2 CSS优先级冲突
当业务自定义样式无法覆盖Semi默认样式时,可以采用以下策略:
提高选择器权重(如添加!important,慎用)
利用CSS Modules的作用域隔离
通过Token变量统一调整,而非分散覆盖
8.3 类型定义问题
确保项目中正确安装了Semi的类型定义:
npm install @types/semi-ui