Figma 空状态与结果反馈系统(Empty State & Result Architecture)组件架构实战:从 6 大业务缺省场景、Auto Layout 视口垂直居中自适应、双 CTA 插槽解耦到 Variables 动态状态机与 Dev Mode 前端交付
在 Web 桌面端、SaaS 系统管理后台与移动端移动应用开发中,空状态(Empty State) 与 结果反馈页(Result Page) 是衡量产品体验成熟度与容错能力的关键试金石。用户在日常使用流程中,不可避免会遇到数据未录入、网络离线、搜索无匹配、权限受限或流程提交完成等节点。一个设计粗糙、缺乏引导的空白界面往往直接导致用户困惑与流失,而优雅且具启发性的空状态设计能够将体验低谷转化为业务激活转化点。
然而,在日常的设计规范搭建与协同交付中,空状态往往面临多重工程化痛点:
- 场景孤岛与形态碎片化:不同设计师在绘制空状态时各自发挥,插图尺寸杂乱(从 48px 到 320px 随意摆放),缺乏统一规范;
- 响应式断裂与极端布局失真:静态绘制的空状态在被放置于全屏、弹窗或局部卡片内时,常发生垂直拉伸错位、文案折行被遮挡或插图溢出容器;
- 操作引导(Call to Action)扩展性差:某些场景需要单一主按钮,某些场景需要“刷新 + 提交工单”双按钮,传统复制副本的做法导致变体数量指数级膨胀;
- 原型难以真实模拟业务流程:缺少状态切换能力,评审时只能看静态图,无法演示“清空表格后自动弹出缺省引导、点击创建后数据回填”的闭环链路;
- 研发交付上下文脱节:前端开发在 Dev Mode 开发模式 中只看到孤立图元,无法快速提取结构化语义代码,不知道何时展示重试逻辑与错误码映射。
本文将深入拆解空状态与结果反馈系统的组件架构,实战自适应容器约束,配置正交的属性插槽,并结合 Figma Variables 搭建高度可运行的原型与前端可复用代码规范。
空状态与结果反馈的形态解耦与业务选型矩阵 #
空状态与结果反馈虽然同属“缺省占位与信息反馈”范畴,但在信息架构(IA)层级、情感表达与交互指引上具有明确的业务分工:
| 业务场景 | 触发时机与核心诉求 | 推荐视觉锚点 | 核心文案结构 | 推荐 CTA 动作组合 | 容错与无障碍(a11y)要点 |
|---|---|---|---|---|---|
| 首次使用(First Use) | 账户新注册或模块初次启用,无存量数据 | 具象化业务引导插图或新手礼盒(160px) | 主标明确价值,副标说明前置准备或功能收益 | 主按钮:立即创建 / 导入模板 | 避免使用负面词汇,在主按钮旁提供快速示例数据 |
| 筛选/搜索无果(No Search) | 用户输入的关键词或筛选组合未命中任何结果 | 放大镜或空箱子单色矢量图(120px) | 明确指出搜索词并提示调整条件 | 次按钮:清空筛选条件 / 重置搜索 | 将用户当前搜索词作为变量回显,方便对比排查 |
| 无网络/服务中断(Offline/500) | 客户端网络断开、DNS 异常或后端接口 5xx | 断开的插头、云朵雷雨警示图标(120px) | 简明指出网络或服务异常,展示错误码 | 主按钮:重新加载;文本链:查看帮助文档 | 避免使用纯技术堆栈报错,提供一键重试机制 |
| 无权限访问(403 Forbidden) | 用户当前角色未被分配该功能或数据的查看权限 | 锁具、防护盾牌或受限证件插画(160px) | 告知权限不足并说明所需角色 | 主按钮:申请访问权限;次按钮:返回工作台 | 显示审批人或所属管理员联系方式链接 |
| 资源不存在(404 Not Found) | 路由错误、页面已下线或数据记录已被物理删除 | 经典的 404 标志或迷路指南针插图(200px) | 告知页面已丢失,消除用户惊慌 | 主按钮:返回首页 / 回到上一页 | 保持全局导航栏完整,提供全局搜索栏入口 |
| 操作成功完成(Result Success) | 表单批量提交、订单付款成功或审批流程归档 | 绿色圆环对勾或成功庆典插画(160px) | 肯定操作完成,告知后续状态与流转时间 | 主按钮:查看详情;次按钮:继续创建 | 明确告知通知渠道(如邮件/短信)与后续生效时间 |
视觉锚点(Visual Anchor):插图层级与 Tokens 语义色绑定 #
空状态的视觉中心是插图(Illustration)或图标(Icon),必须建立清晰的阶梯梯度,严禁在不同模块中随意缩放。
1. 3 级标准尺寸比例阶梯 #
在设计系统中将空状态尺寸规范化为 3 种标准阶梯,通过 组件与变体 统一管理:
[Empty State Scale Hierarchy]
│
├── Mini (用于小卡片、下拉浮层、侧边抽屉):
│ - 视觉区: 80×80px 基础单色线框图标
│ - 标题字号: 14px / lineHeight: 20px
│ - 副标题字号: 12px / lineHeight: 18px
│
├── Standard (用于表格缺省、详情页主面板、对话列表):
│ - 视觉区: 160×160px 双色微渐变矢量插图
│ - 标题字号: 16px / lineHeight: 24px
│ - 副标题字号: 14px / lineHeight: 22px
│
└── Hero / Fullpage (用于 404/500/403 独立全屏或首次上手欢迎):
- 视觉区: 240×240px 场景化立体插画
- 标题字号: 24px / lineHeight: 32px
- 副标题字号: 14px / lineHeight: 22px
2. Tokens 语义化色彩绑定与暗色模式自适应 #
插画设计切忌使用写死的十六进制裸色。所有矢量轮廓线、背景光圈与主体色块均需严格绑定到系统 Design Tokens 标准命名与结构对照手册 中的语义变量:
- 主色轮廓线(Outline):绑定
border-subtle(浅色模式#CBD5E1,深色模式#334155); - 主体浅色受光面(Primary Fill):绑定
surface-subtle或品牌主色低透明度版(如blue-50/blue-950); - 辅助点缀色(Accent Accent):根据场景绑定
color-brand、color-warning或color-danger; - 底层光晕底座(Shadow / Glow Base):使用径向渐变,绑定带 Alpha 通道的
neutral-200/50。
通过这套变量绑定,当用户在 Figma 中通过模式(Modes)将页面切换至暗黑模式(Dark Mode)时,空状态插画会自动翻转为低对比度的夜间冷灰阶,不会产生刺眼的白色方块贴图。
Auto Layout 弹性容器与视口防畸变架构实战 #
空状态在实际业务中会置于各种不同的容器中:全屏视口、定高表格、固定 320px 宽度的侧边栏等。若未做合理的约束控制,极易发生内容挤压或拉伸破损。
1. 骨架拓扑结构 #
整个组件采用严格自顶向下的纵向 Auto Layout 布局 架构:
[Empty-State-Root] (Auto Layout Vertical, Align: Center, Hug Contents / Fill Container)
│ Padding: 48px 24px (桌面) / 32px 16px (移动)
│ Gap: 24px
│
├── [Illustration-Slot] (Frame, 160x160px, Hug / Fixed, Align: Center)
│ └── [Vector Graphic] (Constraints: Scale / Center)
│
├── [Text-Group] (Auto Layout Vertical, Align: Center, Gap: 8px, Fill Container)
│ ├── [Title-Text] (16px, SemiBold, Color: text-primary, Fill Container, Text-align: Center)
│ └── [Description-Text] (14px, Regular, Color: text-secondary, Fill Container, Text-align: Center)
│
└── [Action-Slot] (Auto Layout Horizontal, Align: Center, Gap: 12px, Hug Contents)
├── [Primary-Button] (Button Instance)
└── [Secondary-Button] (Button Instance)
2. 关键属性约束设置技巧 #
- Text-Group 的 Fill Container 与居中排版:
- 将
Title-Text与Description-Text的横向尺寸统一设为 Fill Container,并将文字对齐方式设置为 Align Center; - 在父级
Text-Group上配置Max width: 480px(在 Figma 右侧属性面板中展开尺寸下拉,选择 Add max width); - 防御性价值:当空状态被放入 1920px 宽的大屏时,解释性副标文案不会无限横向延展成一长条难以阅读的单行字,而是优雅地约束在 480px 舒适阅读宽度内折行。
- 将
- 根容器的视口垂直居中自适应:
- 当空状态作为独立页面或表格占位时,父级承载容器(如 Table Body Frame)必须开启 Auto Layout,并将对齐方向设为 Align: Center(水平与垂直居中);
- 根容器本身的纵向尺寸设为 Hug contents,同时设定
Min height: 360px。如此一来,即使表格仅有表头,空状态也不会塌陷成一条细线,保证足够的视觉留白呼吸感。关于更多网格与坐标约束,可参考 组合布局网格与约束。
双 CTA 操作插槽(Action Slot)与组件属性(Component Properties)解耦 #
在实际业务迭代中,空状态底部的操作区往往千变万化:有时只需要“新建”,有时需要“清空筛选 + 提交反馈”,有时需要“返回上级”纯文本链接。
如果为每种按钮组合创建变体,组件集将急剧膨胀。我们通过 Component Properties(组件属性) 彻底解耦:
1. 配置布尔控制(Boolean Property) #
- 在操作区放置两个按钮组件实例,左侧为
Secondary-Button(次操作),右侧为Primary-Button(主操作); - 选中主按钮,在右侧图层显示属性上新建布尔属性
ShowPrimaryAction,默认值设为true; - 选中次按钮,绑定布尔属性
ShowSecondaryAction,默认值设为false; - 收益:设计师可按需在侧边栏一键勾选展示单按钮、双按钮或完全隐藏操作区。
2. 配置文本属性(Text Property) #
- 选中标题文字图层,创建文本属性
TitleText(默认值:暂无匹配数据); - 选中描述文字图层,创建文本属性
DescText(默认值:请尝试调整筛选条件或搜索关键词重新查询); - 选中按钮内部文字,分别绑定
PrimaryActionText与SecondaryActionText; - 收益:无需双击深入多层子图层直接在右侧面板修改文案,避免误触内部 Auto Layout 布局参数。
3. 配置实例替换插槽(Instance Swap Property) #
- 将
Illustration-Slot设为组件实例,并在属性面板声明Illustration实例替换属性,限定作用域为系统插画库; - 允许用户从下拉菜单中一键在
Illustration/No-Data、Illustration/404、Illustration/500与Illustration/Auth-Locked之间平滑切换。关于组件实例替换规范,详见 使用组件与实例指南。
Figma Variables 驱动的空状态/数据列表无缝穿梭动态原型 #
高保真交互评审中最常见的问题是:“当用户执行了清空或者批量删除后,界面是如何平滑过渡到空状态的?”
通过 Figma Variables 变量 与交互式组件(Interactive Components),我们可以在单个画框内实现高保真状态切换。
1. 创建状态控制变量 #
在 Local Variables 面板中新建 State-Vars 变量集合:
hasData(Boolean 变量):默认值为true;recordCount(Number 变量):默认值为12。
2. 图层可见性绑定(Layer Visibility) #
- 选中页面中的数据表格图层(Table Grid),将其图层右键眼睛图标绑定到变量
hasData(当hasData为 true 时可见,为 false 时自动隐藏); - 选中并排的
Empty-State-Root空状态组件实例,将其图层眼睛图标绑定到表达式或直接配合变体——使用另一个布尔变量isEmpty,或者在按钮上配置切换动作。
3. 原型交互绑定(Prototyping Interaction) #
在数据列表顶部的“清空全部数据”操作按钮上添加点击事件:
- Trigger:
On click - Action 1:
Set variable->hasData=false - Action 2:
Set variable->recordCount=0
在空状态底部的“重置并加载演示数据”主按钮上添加点击事件:
- Trigger:
On click - Action 1:
Set variable->hasData=true - Action 2:
Set variable->recordCount=12
运行原型演示时,点击清空,数据表格瞬间消失,带有精致插图与文案引导的空状态组件垂直居中呈现在屏幕中央;点击“加载演示数据”,表格无缝回显!无需绘制重复画框,交互链路真实且震撼。更多高级原型技巧见 高级原型与滚动溢出。
Dev Mode 研发协同与前端组件代码交付规范 #
进入 Dev Mode 开发模式,前端工程师可以清晰提取空状态的几何参数、Token 变量映射与语义化代码。
为了让组件在 React + Tailwind CSS / Ant Design 技术栈中做到无损复用,我们规范了标准的研发交付代码规范:
1. React + TypeScript 企业级空状态组件实现 #
import React from 'react';
import classNames from 'classnames';
export type EmptyStateType = 'first-use' | 'no-search' | 'offline' | '403' | '404' | 'success';
export interface EmptyStateProps {
type?: EmptyStateType;
size?: 'mini' | 'standard' | 'hero';
title?: React.ReactNode;
description?: React.ReactNode;
illustration?: React.ReactNode;
primaryAction?: {
label: string;
onClick: () => void;
icon?: React.ReactNode;
};
secondaryAction?: {
label: string;
onClick: () => void;
};
className?: string;
style?: React.CSSProperties;
}
const defaultTypeMap: Record<EmptyStateType, { title: string; desc: string }> = {
'first-use': { title: '暂无数据,从创建开始', desc: '点击下方按钮快速开启您的第一份工作流。' },
'no-search': { title: '未找到匹配结果', desc: '请尝试更换关键词或重置筛选条件后重试。' },
'offline': { title: '网络连接已中断', desc: '请检查您的网络连接并刷新重试。' },
'403': { title: '无权访问此内容', desc: '当前账号缺少查看该资源的权限,请联系管理员申请。' },
'404': { title: '找不到目标页面', desc: '抱歉,您访问的页面不存在或已被移除。' },
'success': { title: '操作已顺利完成', desc: '系统已成功处理您的提交,结果可在列表查看。' },
};
export const EmptyState: React.FC<EmptyStateProps> = ({
type = 'first-use',
size = 'standard',
title,
description,
illustration,
primaryAction,
secondaryAction,
className,
style,
}) => {
const meta = defaultTypeMap[type];
const finalTitle = title || meta.title;
const finalDesc = description || meta.desc;
const sizeStyles = {
mini: { wrap: 'py-6 px-4 gap-3', img: 'w-20 h-20', title: 'text-sm', desc: 'text-xs' },
standard: { wrap: 'py-12 px-6 gap-6', img: 'w-40 h-40', title: 'text-base font-semibold', desc: 'text-sm' },
hero: { wrap: 'py-16 px-8 gap-8', img: 'w-60 h-60', title: 'text-2xl font-bold', desc: 'text-base' },
}[size];
return (
<div
role="status"
aria-live="polite"
className={classNames(
'flex flex-col items-center justify-center text-center w-full min-h-[320px]',
sizeStyles.wrap,
className
)}
style={style}
>
{/* 视觉锚点插图 */}
<div className={classNames('flex items-center justify-center select-none', sizeStyles.img)}>
{illustration || <div className="bg-slate-100 dark:bg-slate-800 rounded-full w-full h-full flex items-center justify-center text-slate-400">Icon</div>}
</div>
{/* 文本区域,限制最大宽度 480px 防止大屏横向拉伸失真 */}
<div className="flex flex-col items-center gap-2 max-w-[480px] w-full">
<h3 className={classNames('text-slate-900 dark:text-slate-100 tracking-tight', sizeStyles.title)}>
{finalTitle}
</h3>
{finalDesc && (
<p className={classNames('text-slate-500 dark:text-slate-400 leading-relaxed', sizeStyles.desc)}>
{finalDesc}
</p>
)}
</div>
{/* 操作按钮插槽 */}
{(primaryAction || secondaryAction) && (
<div className="flex items-center justify-center gap-3 mt-2">
{secondaryAction && (
<button
type="button"
onClick={secondaryAction.onClick}
className="px-4 py-2 text-sm font-medium text-slate-700 bg-white border border-slate-300 rounded-lg hover:bg-slate-50 dark:bg-slate-800 dark:text-slate-200 dark:border-slate-700 dark:hover:bg-slate-700 transition"
>
{secondaryAction.label}
</button>
)}
{primaryAction && (
<button
type="button"
onClick={primaryAction.onClick}
className="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-lg hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 transition shadow-sm"
>
{primaryAction.label}
</button>
)}
</div>
)}
</div>
);
};
2. 无障碍(Accessibility)核对清单 #
role="status"与aria-live="polite":动态从“加载中”切换为“空状态”时,读屏软件能够友好地播报文案,而不会粗暴打断用户当前操作;- 插图装饰性标记(
aria-hidden="true"):如果插图仅具装饰性,必须为 SVG 声明aria-hidden="true",避免读屏软件朗读内部 path 路径代码; - 按钮键盘聚焦轮廓:所有 CTA 操作按钮必须保留高对比度聚焦环(
focus-visible:ring-2),契合 WCAG 2.1 AA 规范。若在构建过程中遇到组件对齐或渲染问题,可随时查阅 故障排查速查手册。
核心手册与速查工具
高频手册与实用设计生产力工具直达常见问题与答疑 (FAQ)
高频疑难解析与避坑指南完全不需要。绝大多数核心功能在免费 Starter 计划中均可完整体验与实操练习,无需额外付费购买付费团队版。