news 2026/9/16 13:39:33

用 coss Empty 原语构建 Kaneo 的空状态与恢复式 UI 实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用 coss Empty 原语构建 Kaneo 的空状态与恢复式 UI 实战指南

用 coss Empty 原语构建 Kaneo 的空状态与恢复式 UI 实战指南

【免费下载链接】app🎯 All you need. Nothing you don't. Open source project management that works for you, not against you.项目地址: https://gitcode.com/GitHub_Trending/app116/app

空状态(Empty State)是列表类界面中最容易被忽略、却又直接影响用户留存体验的环节:当项目列表、标签列表或搜索结果为空时,用户需要的不是一行干巴巴的"暂无数据",而是明确的方向指引和可执行的动作。本文基于 Kaneo(app116)开源项目仓库中skills/coss/references/primitives/empty.md的 coss Empty 原语规范,结合apps/web/src/components/ui/empty.tsx的真实实现与页面级使用案例,讲解如何在 React + Tailwind CSS v4 项目中搭建语义完整、带恢复引导的空状态组件。读完本文,你将掌握 coss Empty 的完整 API 结构、组合模式、真实项目落地写法,以及容易踩中的三类陷阱。

Empty 原语是什么:何时使用、何时不用

coss 是一套基于 Base UI、提供 shadcn 式开发体验的组件库,仓库中的 coss skill(skills/coss/SKILL.md)为其 53 个原语各维护了一份参考指南,empty.md是其中之一。它专门回答一个核心问题:列表没有数据时,界面该怎么呈现

empty.md的"When to use"定义,Empty 原语适用于两类场景:

  • 无数据 / 无结果状态(No-data/no-results):列表、搜索结果、过滤结果为空的页面,需要给出引导性说明;
  • 面向行动恢复的 UI(Action-oriented recovery):空内容列表需要引导用户立刻执行某个恢复动作,例如"创建第一个项目"。

反过来说,Empty 原语不是万能的容器——加载中和报错状态应使用专门的加载/错误原语(如 skeleton、alert),而不是复用空状态组件。这一点在"Common pitfalls"一节中被明确列为反面典型,下文会展开。

安装:CLI 一键添加与手动依赖

empty.md给出了两种安装方式。

方式一:shadcn CLI 安装(推荐)

npx shadcn@latest add @coss/empty

这是 coss 组件注册表的标准安装入口(与skills/coss/references/cli.md中的整体安装流程一致),CLI 会把组件文件写入项目的components/ui目录。

方式二:手动安装

# No extra runtime dependency required for this primitive.

原语文档明确说明:Empty 不需要任何额外的运行时依赖。这与许多需要 Radix 或 Base UI 包支撑的原语不同——Empty 本质上是纯展示型结构组件,只依赖 React 与 Tailwind。手动安装时只需把组件文件复制到本地、并将导入路径改为当前应用的别名配置即可,这也是skills/coss/SKILL.md中"Quick manual pattern"的通用流程。

在 Kaneo 仓库中,Empty 的落点正是apps/web/src/components/ui/empty.tsx,导入别名是@/components/ui/empty

组件 API 结构:六个子组件与源码级剖析

coss Empty 采用"容器 + 语义子组件"的组合式 API,empty.md给出的规范导入如下:

import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle, } from "@/components/ui/empty"

对照apps/web/src/components/ui/empty.tsx的真实实现,这六个导出都有明确的职责划分:

子组件DOM 元素职责关键样式要点(源码确认)
Emptydiv整体容器flex flex-col items-center justify-center gap-6 text-center p-6 md:p-12,带data-slot="empty"
EmptyHeaderdiv头部信息区max-w-sm限制宽度,垂直居中
EmptyMediadiv视觉媒体区(图标)基于cvavariant变体:default(透明)与icon(带边框小方块)
EmptyTitlediv标题font-heading font-semibold text-xl
EmptyDescriptionp描述文字text-muted-foreground text-sm,内嵌链接自动下划线
EmptyContentdiv动作区max-w-sm,子元素垂直排列gap-4

值得注意的实现细节:

1.data-slot语义选择器。每个子组件都携带data-slot属性(emptyempty-headerempty-mediaempty-titleempty-descriptionempty-content),这与 coss skill 的skills/coss/references/rules/styling.md中强调的><Empty> <EmptyHeader> <EmptyMedia variant="icon"> <Icon /> </EmptyMedia> <EmptyTitle>No data</EmptyTitle> <EmptyDescription>No data found</EmptyDescription> </EmptyHeader> <EmptyContent> <Button>Add data</Button> </EmptyContent> </Empty>

注意结构层次:EmptyMedia / EmptyTitle / EmptyDescription必须统一放在EmptyHeader内,动作按钮放在EmptyContent内,这是组合式 API 的约定俗成,破坏这个层次会导致布局与语义错乱。

实战模式:Kaneo 中的真实空状态用例

empty.md提供了带图标与动作按钮的推荐模式,而 Kaneo 仓库中正好有三个页面级实现可供对照,其中两个值得逐行解读。

用例一:工作区无项目(完整恢复式空状态)

apps/web/src/routes/_layout/_authenticated/dashboard/workspace/$workspaceId/index.tsxempty.md中"Always include an actionable next step"原则的教科书级落地:

<Empty className="min-h-[60vh]"> <EmptyHeader> <EmptyMedia variant="icon"> <LayoutGrid /> </EmptyMedia> <EmptyTitle>{t("workspace:projects.emptyTitle")}</EmptyTitle> <EmptyDescription> {canCreate ? t("workspace:projects.emptyDescription") : t("workspace:projects.emptyDescriptionReadOnly")} </EmptyDescription> </EmptyHeader> <EmptyContent> {canCreate && ( <Button onClick={handleCreateProject}> <Plus /> {t("workspace:projects.createProject")} </Button> )} </EmptyContent> </Empty>

几个可以照抄到任何项目的细节:

  • className="min-h-[60vh]":通过 className 透传撑高整个空状态区,避免空页面显得头重脚轻,这是Empty容器接受React.ComponentProps<"div">的灵活之处;
  • 权限感知的文案与动作canCreate为 true 时显示"创建项目"按钮与创建引导文案;无权限时只显示只读文案并隐藏按钮——空状态的"下一步"必须与用户实际权限匹配,否则是无效引导;
  • 图标语义LayoutGrid暗示"项目"的业务语义,Plus表示"新增",均带aria-hidden由描述文字承担可访问性信息;
  • 动作即跳转handleCreateProject会打开CreateProjectModal(紧随其后的CreateProjectModal),完成"空状态 → 引导 → 创建 → 列表刷新"的完整闭环。

用例二:无自定义角色(引导性空状态)

apps/web/src/routes/_layout/_authenticated/dashboard/settings/workspace/roles.tsx展示了无动作按钮的变体——当"创建"动作以其他形式存在(页面头部有新建入口)时,空状态只需提供图标 + 标题 + 描述:

<Empty> <EmptyHeader> <EmptyMedia variant="icon"> <Shield /> </EmptyMedia> <EmptyTitle> {t("settings:workspaceRoles.emptyTitle")} </EmptyTitle> <EmptyDescription> {t("settings:workspaceRoles.emptyDescription")} </EmptyDescription> </EmptyHeader> </Empty>

该文件还展示了正确的条件渲染顺序roles.tsx):isLoading → 加载提示 → error → 错误提示 → 空列表 → Empty 组件 → 否则渲染真实列表,即 Empty 只接管"数据已加载且确认为空"的分支,绝不与加载态、错误态混用——这正是empty.md"Common pitfalls" 第 2 条的直接印证。同样的模式还出现在labels.tsx(工作区标签为空时)。

常见陷阱:三类高频失误与规避方案

empty.md的"Common pitfalls"一节列出了三条高频错误,结合 Kaneo 源码可以给出更具体的规避手段:

陷阱 1:空状态没有可执行的下一步。只展示"暂无数据"四个字而不给按钮/链接,用户会陷入死胡同。规避:只要业务上允许,就在EmptyContent中放入明确的恢复动作(按钮、链接、快捷键提示);即便动作放在页面其他位置,也应如 roles.tsx 那样在描述中说明"如何开始"。

陷阱 2:用空状态组件冒充加载态 / 错误态。加载中应使用骨架屏(skeleton),错误应使用 alert/destructive 提示,两者与"空"是语义不同的状态。规避:如 roles.tsx 所示,把isLoadingerrorempty三个分支拆开渲染,Empty 只负责data.length === 0的场景。

陷阱 3:纯文案空状态,缺少上下文相关的恢复指引。描述文字要"因场景而异":工作区空项目与搜索无结果、筛选无匹配的引导文案与动作完全不同。规避:描述文案走 i18n(Kaneo 中统一使用t("workspace:projects.emptyDescription")这类翻译键),且按canCreate等上下文动态切换,确保每条空状态都回答"为什么空 + 下一步干什么"。

延伸阅读

  • 原语规范:skills/coss/references/primitives/empty.md(本文的规范来源,含p-empty-1核心粒子模式索引)
  • 组件实现:apps/web/src/components/ui/empty.tsx
  • 页面级用例:工作区无项目、无自定义角色、无标签
  • coss 技能总览与组件注册表:skills/coss/SKILL.mdskills/coss/references/component-registry.md
  • 样式与组合规则:skills/coss/references/rules/styling.mdskills/coss/references/rules/composition.md

【免费下载链接】app🎯 All you need. Nothing you don't. Open source project management that works for you, not against you.项目地址: https://gitcode.com/GitHub_Trending/app116/app

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 13:39:33

page-agent PageAgentCore源码逐行解读:execute()方法里的100个细节

page-agent PageAgentCore源码逐行解读&#xff1a;execute()方法里的100个细节 【免费下载链接】page-agent JavaScript in-page GUI agent. Control web interfaces with natural language. 项目地址: https://gitcode.com/GitHub_Trending/pa/page-agent page-agent …

作者头像 李华
网站建设 2026/9/16 13:39:01

Spring Boot旅游线路规划系统:从数据模型到核心算法实战

简介&#xff1a;一套基于SpringBoot与MySQL的旅游线路规划系统毕业设计资源包&#xff0c;面向计算机相关专业毕业生、Java学习者及需要快速搭建同类型项目的开发者。系统覆盖地图信息查看与缩放、景点搜索与坐标定位、旅游线路智能推荐、沿途住宿推荐以及导航导游方向指示等用…

作者头像 李华
网站建设 2026/9/16 13:37:04

Resolume Arena 7 实时视觉合成引擎深度指南

简介&#xff1a;Resolume Arena 7 大屏控制软件是面向舞台视觉设计师、现场演出技术人员及数字艺术创作者的专业级实时视频处理工具&#xff0c;专为多屏同步播放、动态视觉合成与交互式投影映射等高要求场景打造。资源包共264个文件&#xff0c;含204个XML配置与映射参数文件…

作者头像 李华
网站建设 2026/9/16 13:37:00

Cursor Docs Canvas 插件:把文档渲染成可导航 Canvas 的完整指南

Cursor Docs Canvas 插件&#xff1a;把文档渲染成可导航 Canvas 的完整指南 【免费下载链接】plugins Cursor plugin specification and official plugins 项目地址: https://gitcode.com/GitHub_Trending/plugins125/plugins Docs Canvas 是 Cursor 官方插件仓库中的一…

作者头像 李华