如何使用Chakra UI创建含步骤与子步骤的步进进度条
解决方案:基于页面跳转的嵌套步进器实现
针对你需要的页面跳转联动步进器功能,以下是修改后的实现代码,解决了进度条匹配、子步骤勾选与激活的问题:
import { Box, Flex, Progress, Step, StepIcon, StepIndicator, StepNumber, StepStatus, Stepper, Text, useSteps, useMemo } from '@chakra-ui/react'; import React from 'react'; interface StepperProps { subText?: string; } // 基础步骤配置 const baseSteps = [ { label: 'Customer Details', active: true, completed: false, subSteps: [ { label: 'Business Information', active: true, url: '/', completed: false }, { label: 'Primary Contact', active: false, url: '/primary-contact', completed: false }, { label: 'Offer Type', active: false, url: '/tradefull-solutions', completed: false }, ], }, { label: 'Supporting Documents', active: false, completed: false, subSteps: [ { label: 'Documents Upload', active: false, completed: false }, { label: 'Additional Assets', active: false, completed: false }, { label: 'Notes', active: false, completed: false }, ], }, { label: 'Review & Submit', active: false, completed: false, }, ]; function Steppers({ subText }: StepperProps) { const { activeStep, setActiveStep } = useSteps({ index: 0, count: baseSteps.length, }); // 根据当前页面动态计算步骤及子步骤状态 const currentSteps = useMemo(() => { const stepsCopy = JSON.parse(JSON.stringify(baseSteps)); // 处理Customer Details下的子步骤状态 const customerSubSteps = stepsCopy[0].subSteps; if (!customerSubSteps) return stepsCopy; switch(subText) { case 'business': customerSubSteps.forEach((sub, idx) => { sub.active = idx === 0; sub.completed = idx < 0; }); break; case 'contact': customerSubSteps.forEach((sub, idx) => { sub.active = idx === 1; sub.completed = idx < 1; }); stepsCopy[0].completed = false; break; case 'tradefull': customerSubSteps.forEach((sub, idx) => { sub.active = idx === 2; sub.completed = idx < 2; }); stepsCopy[0].completed = false; break; default: customerSubSteps.forEach((sub, idx) => { sub.active = idx === 0; sub.completed = false; }); } return stepsCopy; }, [subText]); // 计算进度条百分比 const getProgressPercent = () => { switch(subText) { case 'business': return 20; case 'contact': return 40; case 'tradefull': return 60; case 'documents': return 70; case 'assets': return 80; case 'notes': return 90; case 'review': return 100; default: return 20; } }; return ( <Box position="relative" display="flex" gap={4}> {/* 自定义垂直进度条 */} <Box position="relative" width="4px" bg="gray.200" h="full" borderRadius="full"> <Progress position="absolute" top="0" left="0" height="100%" width="4px" value={getProgressPercent()} colorScheme="blue" borderRadius="full" orientation="vertical" /> </Box> <Stepper mt={4} size="xs" index={activeStep} orientation="vertical" gap="0"> {currentSteps.map((step, index) => ( <Step key={index} onClick={() => setActiveStep(index)}> <StepIndicator> <StepStatus complete={<StepIcon />} active={<StepNumber>{index + 1}</StepNumber>} incomplete={<StepNumber>{index + 1}</StepNumber>} /> </StepIndicator> <Box flexShrink="0" mb={2}> <Text fontSize="md" fontWeight="medium" color={step.active ? "BaseClr.Primary" : "gray.600"} mt={0} mb={0} pb="3" > {step.label} </Text> {step.subSteps && step.subSteps.map((sub, subIdx) => ( <Flex gap={2} align="center" mb={2} key={subIdx}> {/* 子步骤状态图标 */} {sub.completed && <StepIcon boxSize={4} color="green.500" />} {!sub.completed && sub.active && <Box boxSize={4} borderRadius="full" bg="BaseClr.Primary" />} {!sub.completed && !sub.active && <Box boxSize={4} borderRadius="full" bg="gray.300" />} <Text mb={0} fontSize="sm" fontWeight={sub.active ? "semibold" : "regular"} color={sub.active ? "BaseClr.Primary" : "gray.600"} > {sub.label} </Text> </Flex> ))} </Box> </Step> ))} </Stepper> </Box> ); } export default Steppers;
关键改动说明
- 动态状态管理:使用
useMemo根据subText参数实时更新步骤和子步骤的active、completed状态,确保页面跳转时状态同步 - 自定义垂直进度条:替换默认的
StepSeparator,用Progress组件实现垂直方向的进度条,根据当前页面设置对应的进度百分比 - 子步骤视觉反馈:给子步骤添加状态图标(完成显示勾选、激活显示实心圆点、未开始显示灰色圆点),同时高亮激活状态的文本
- 父步骤状态联动:子步骤未全部完成时,父步骤保持未完成状态,符合步进逻辑
使用时只需在对应页面传入subText参数即可:
- Business页面:
<Steppers subText="business" /> - Primary Contact页面:
<Steppers subText="contact" /> - Offer Type页面:
<Steppers subText="tradefull" />
内容的提问来源于stack exchange,提问作者Maharajan K
相关产品推荐
相关产品推荐

