如何使用 Shadcn UI 在 React 中构建可扩展的客户身份验证及入职流程
任何具有合规性要求的B2B SaaS产品(比如涉及银行业务、贷款服务、工资发放或加密货币相关的应用)在开发初期都会遇到同样的问题:在允许企业使用你的平台之前,你必须先核实他们的身份。 这意味着需要收集企业的类型信息、审核他们的注册文件,并向用户展示他们的验证进度,但整个流程不能让人感觉像是在填写繁琐的海关表格一样。 本文详细介绍了如何利用Shadcn UI构建一个功能完备的三步客户身份验证流程:包括用于显示操作进度的步骤提示组件、用于选择账户类型的单选组、用于上传文件的区域,以及用于显示验证状态的警告提示。你会看到实际的代码实现,而不仅仅是简化后的示例代码,同时也会了解到每个设计决策背后的理由
任何具有合规性要求的B2B SaaS产品(比如涉及银行业务、贷款服务、工资发放或加密货币相关的应用)在开发初期都会遇到同样的问题:在允许企业使用你的平台之前,你必须先核实他们的身份。
这意味着需要收集企业的类型信息、审核他们的注册文件,并向用户展示他们的验证进度,但整个流程不能让人感觉像是在填写繁琐的海关表格一样。
本文详细介绍了如何利用Shadcn UI构建一个功能完备的三步客户身份验证流程:包括用于显示操作进度的步骤提示组件、用于选择账户类型的单选组、用于上传文件的区域,以及用于显示验证状态的警告提示。你会看到实际的代码实现,而不仅仅是简化后的示例代码,同时也会了解到每个设计决策背后的理由。
你可以在onboarding-kyc-flow.vercel.app尝试这个完整的验证流程。在继续阅读之前,请先点击一遍该链接,这样下面的代码会更容易理解。此外,这个界面还提供了深色和浅色两种显示模式。
目录
先决条件
在开始学习这个流程之前,你应该已经熟悉React函数组件以及各种钩子函数,特别是useState、useRef和useEffect。
你需要具备以下条件:
一个已经初始化了App Router和shadcn/ui的Next.js项目,因为本文不会讲解这些初始设置步骤。
是否使用v0账户是可选的。你也可以使用Bolt或Lovable这两个库,它们同样支持shadcn MCP提示功能。
您正在构建的内容
整个流程包含三个步骤:
账户类型:用户可以选择“创业企业”“大型企业”或“政府机构”。这一选择将决定后续的所有操作流程。系统会向用户显示确认信息,通常也会根据用户的选择来确定默认使用的工作区设置。
文件上传:用户需要上传企业注册证明、纳税申报表或公司登记信息,这些文件可以是PDF格式,也可以是CSV格式。
验证状态:用户可以实时查看文件的验证进度:可能是“正在检查中”,也可能是“已经验证通过”或“存在需要处理的问题”。
项目结构
该项目是一个标准的Next.js应用程序,且已经预先配置好了shadcn/ui框架。其顶层文件结构如下:
onboarding-kyc-flow/
├── .vercel/
├ ├── app/
├ ├── components/
├ ├── lib/
├ ├── public/
├ ├── .env.development.local
├ ├── .gitignore
├ ├── components.json
├ ├── next-env.d.ts
├ ├── next.config.mjs
├ ├── package.json
├ ├── pnpm-lock.yaml
├ ├── postcss.config.mjs
├ ├── tsconfig.json
└── tsconfig.tsbuildinfo
components.json文件是shadcn CLI用来确定组件的存放位置以及所使用的样式库和基础组件的文件。components/目录中包含了所有通用的UI组件(如警告框、徽章、按钮、卡片、进度条、单选组等)。lib/utils.ts文件提供了cn辅助函数,用于在代码中动态生成条件性的类名。app/目录则存放了应用程序的核心逻辑代码。
Radix UI与Base UI:此流程使用哪些基础组件
Shadcn组件库并不依赖任何特定的基础组件库。虽然该生态系统的多数组件默认使用Radix UI,但Base UI也是一个可靠的替代方案,而这个流程正是基于Base UI构建的。
所使用的基础组件库会直接影响组件的功能及其在项目中的使用方式。如果您从像Shadcn UI这样的组件库中获取组件,请务必先确认它使用的是哪个基础组件库,然后再将不同来源的组件混合使用。
虽然将基于Radix UI的组件与基于Base UI的组件混合使用是可行的,但这意味着在同一项目中需要同时使用两种不同的样式库。您可以通过此处比较Radix UI与Base UI来了解更多相关信息。
使用v0版本及MCP服务器构建流程框架
MCP(模型上下文协议)服务器会将组件库作为一组可调用的工具提供给AI编码助手。这样一来,助手就不需要从训练数据中推测组件的名称和属性了,而是可以直接从服务器获取最新的API接口信息。
在这里,这一点尤为重要,因为目前已经有几组名称相似但属性不同的Shadcn风格组件。
Shadcn Components库为其免费组件集提供了一个MCP服务器,通过遵循其入门指南,可以将其与v0版本连接起来。下面的视频会逐步讲解连接过程。同样生成的输出内容也可以通过Lovable或Bolt工具的复制功能导入到这些系统中,因此工作流程并不局限于某一款AI构建工具。
用于构建这一工作流程的提示框内容如下:
创建一个企业级SaaS注册与身份验证流程。使用Shadcn Space MCP服务器中的免费组件:shadcn alert、shadcn radio group、shadcn stepper、shadcn file upload。仅使用免费组件,切勿使用专业版组件,并明确指出每个环节使用了哪些免费组件。
步骤1:账户类型(stepper)——选择“初创企业”、“企业”或“政府机构”
步骤2:上传文件(stepper)——上传企业注册所需的文件
步骤3:验证信息(stepper)——显示验证状态的提示框
这样就可以快速生成一个可用的初稿。接下来是对这个初稿进行优化处理后的结果:包括了真实的状态管理机制、有效的验证流程,以及那些在初始版本中可能被忽略的细节。
步骤1:使用单选组选择账户类型
账户类型是整个流程中的第一个决策环节,因为它的选择很可能会影响后续的所有步骤。提前询问用户这个信息,可以让后续的流程内容始终与用户的当前选择保持关联。
const tiers: { id: Tier; name: string; description: string; tag: string }[] = [
{ id: 'startup', name: '初创企业', description: '适用于快速发展和扩张的团队', tag: '最多支持25个用户' },
{ id: 'enterprise', name: '企业', description: '适用于有复杂需求的成熟团队', tag: '无限用户数' },
{ id: 'government', name: '政府机构', description: '适用于公共部门和受监管的团队', tag: '符合FedRAMP安全标准' },
]
<RadioGroup value={tier} onValueChange={(value) => setTier(value as Tier)} className="grid gap-3">
<fieldset className="contents">
<legend className="sr-only">>账户类型
推荐使用}
>{item.description}</span>
>{item.tag}</span>
))}
</RadioGroup>
这里有兩点值得注意。层级数据存储在组件外部的一个普通数组中,因此后来添加第四个层级只需要修改一行代码,而无需对标记进行任何更改。而使用fieldset并结合视觉上隐藏的(sr-only)说明文字,可以使屏幕阅读器将这三个选项视为一个相关的选择项。有视力的用户根本看不到这个隐藏的说明文字,因为上方的卡片标题已经明确写明了“请选择您的账户类型”。
在这一步中,我们使用了shadcn单选组而不是下拉菜单或复选框,因为账户类型是一个互斥的单一选项,而单选组是三种选择方式中唯一一种能够让人一眼就能看到所有选项以及当前所选的选项的那种方式。
实时预览:
步骤2:通过拖放上传文档
上传区域需要能够清晰地处理三种状态:尚未选择任何文件、已选中一个文件且可以上传,以及被拒绝的文件并附有具体的拒绝原因。
function FileUpload({ file, onFile, onRemove, error }: {
file: File | null
onFile: (file: File) => void
onRemove: () => void
error: string
}) {
const inputRef = useRef<HTMLInputElement>>(null)
const [dragging, setDragging] = useState(false)
const accept = (candidate: File) => {
if (candidate.type !== 'application/pdf' && candidate.type !== 'text/csv' && !candidate.name.toLowerCase().endsWith('.csv')) {
return '仅支持上传PDF或CSV格式的文件。'
}
if (candidate.size > 10 * 1024 * 1024) {
return '文件大小必须小于10MB。'
}
onFile(candidate)
return ''
}
return (
>
>
将您的业务文档拖放到此处
或点击浏览 · PDF或CSV格式 · 最大文件大小为10MB
>>
)
shadcn警告组件与进度条结合使用,可以同时完成两项功能:警告信息会用文字说明当前的状态,而进度条则能大致显示还有多少工作需要完成,但不会给出具体的完成时间。单独使用其中任何一个组件都无法完整地反映整个验证过程的情况——仅靠警告信息显得过于静态,而仅靠进度条也无法让用户了解到底在检查哪些内容。
需要特别指出的是,当演示仅展示成功路径时,这种状态很容易被忽略:即文档中的税号与公司注册信息不一致的情况。这种情况下应该发出专门的警告,并明确提示用户下一步该怎么做——联系客服或重新上传经过更正的文档。由于当前的流程只会显示“检查中”或“已验证”两种状态,所以这个情况没有在上面的演示中体现出来,但实际上,在实际应用中,这种情况出现的频率会非常高。
实时预览:
向流程中添加步骤
步骤组件是整个流程的视觉标识,它能够告诉用户,在完成检查及选择账户类型之前还剩下哪些步骤需要执行。
function Stepper({ current }: { current: Step }) {
return (