You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Next.js + Tailwind项目中实现Figma设计的步骤组件?

Next.js + Tailwind 实现步骤展示模块的思路

结合你的技术栈,以下几种落地性强的实现思路可以参考:

1. 静态硬编码(适合固定步骤场景)

如果步骤数量和内容不会变动,直接用JSX编写结构,配合Tailwind快速完成样式:

  • 用flex垂直排列每个步骤项,左侧放编号容器(用rounded-full实现圆形样式),右侧承载标题和描述
  • 步骤间的连线通过绝对定位元素实现:给非最后一步的步骤项添加相对定位,内部嵌入一条垂直细线作为连接

示例代码:

<div className="space-y-6">
  {/* 步骤1 */}
  <div className="flex items-start relative">
    <div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white">1</div>
    <div className="ml-4">
      <h3 className="font-semibold text-lg">第一步标题</h3>
      <p className="text-gray-600 mt-1">这是第一步的操作说明,清晰描述步骤要点</p>
    </div>
    <div className="absolute left-5 top-10 bottom-0 w-px bg-gray-300"></div>
  </div>

  {/* 步骤2 */}
  <div className="flex items-start relative">
    <div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white">2</div>
    <div className="ml-4">
      <h3 className="font-semibold text-lg">第二步标题</h3>
      <p className="text-gray-600 mt-1">这是第二步的操作说明,清晰描述步骤要点</p>
    </div>
    <div className="absolute left-5 top-10 bottom-0 w-px bg-gray-300"></div>
  </div>

  {/* 步骤3(无连接线) */}
  <div className="flex items-start">
    <div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white">3</div>
    <div className="ml-4">
      <h3 className="font-semibold text-lg">第三步标题</h3>
      <p className="text-gray-600 mt-1">这是第三步的操作说明,清晰描述步骤要点</p>
    </div>
  </div>
</div>

2. 数据驱动渲染(适合动态/可配置步骤)

如果步骤需要从接口获取或后续可能修改,把数据抽象成数组,通过map循环渲染:

  • 可以在组件内定义静态数组,也可以通过Next.js的getStaticProps/getServerSideProps从后端拉取数据
  • 循环时通过条件判断自动控制连接线的显隐,避免重复写冗余代码

示例代码:

const steps = [
  { id: 1, title: "第一步标题", desc: "这是第一步的操作说明,清晰描述步骤要点" },
  { id: 2, title: "第二步标题", desc: "这是第二步的操作说明,清晰描述步骤要点" },
  { id: 3, title: "第三步标题", desc: "这是第三步的操作说明,清晰描述步骤要点" },
];

export default function StepsModule() {
  return (
    <div className="space-y-6">
      {steps.map((step, index) => (
        <div key={step.id} className={`flex items-start ${index !== steps.length - 1 ? 'relative' : ''}`}>
          <div className="w-10 h-10 rounded-full bg-blue-600 flex items-center justify-center text-white">{step.id}</div>
          <div className="ml-4">
            <h3 className="font-semibold text-lg">{step.title}</h3>
            <p className="text-gray-600 mt-1">{step.desc}</p>
          </div>
          {index !== steps.length - 1 && (
            <div className="absolute left-5 top-10 bottom-0 w-px bg-gray-300"></div>
          )}
        </div>
      ))}
    </div>
  );
}

3. 组件化封装(高复用性场景)

如果项目多个页面需要步骤模块,把单个步骤封装成独立组件,通过props传递状态和内容:

  • 封装StepItem组件,接收number、title、desc、isLast、isActive等参数,动态切换样式
  • 父组件统一管理步骤数据和激活状态,批量调用子组件即可

示例代码:

// components/StepItem.jsx
export default function StepItem({ number, title, desc, isLast, isActive = false }) {
  const numberBg = isActive ? 'bg-blue-600' : 'bg-gray-300';
  const numberText = isActive ? 'text-white' : 'text-gray-700';

  return (
    <div className={`flex items-start ${!isLast ? 'relative' : ''}`}>
      <div className={`w-10 h-10 rounded-full ${numberBg} flex items-center justify-center ${numberText}`}>
        {number}
      </div>
      <div className="ml-4">
        <h3 className={`font-semibold text-lg ${isActive ? 'text-blue-600' : ''}`}>{title}</h3>
        <p className="text-gray-600 mt-1">{desc}</p>
      </div>
      {!isLast && (
        <div className="absolute left-5 top-10 bottom-0 w-px bg-gray-300"></div>
      )}
    </div>
  );
}

// 父组件使用
import StepItem from '@/components/StepItem';
import { useState } from 'react';

const steps = [/* 步骤数据 */];

export default function StepsModule() {
  const [activeStep, setActiveStep] = useState(1);

  return (
    <div className="space-y-6">
      {steps.map((step, index) => (
        <StepItem
          key={step.id}
          number={step.id}
          title={step.title}
          desc={step.desc}
          isLast={index === steps.length - 1}
          isActive={step.id === activeStep}
          onClick={() => setActiveStep(step.id)}
        />
      ))}
    </div>
  );
}

4. 交互增强(带状态切换/滚动触发)

如果需要实现点击切换、滚动激活等交互:

  • 用useState管理当前激活步骤,点击时更新状态并切换样式
  • 滚动激活可以借助react-intersection-observer的useInView钩子,监听步骤项是否进入视口,自动激活对应步骤

示例(滚动激活核心代码):

import { useInView } from 'react-intersection-observer';

export default function StepItem({ number, title, desc, isLast }) {
  const [ref, inView] = useInView({
    threshold: 0.5,
    triggerOnce: true,
  });

  const numberBg = inView ? 'bg-blue-600' : 'bg-gray-300';
  const numberText = inView ? 'text-white' : 'text-gray-700';

  return (
    <div ref={ref} className={`flex items-start ${!isLast ? 'relative' : ''}`}>
      {/* 内容结构同上 */}
    </div>
  );
}

额外优化点

  • 响应式适配:用Tailwind的sm:/md:前缀,在移动端调整布局(比如改为水平排列)
  • 动画效果:配合transition类,给激活状态添加平滑过渡(比如背景色渐变)

内容的提问来源于stack exchange,提问作者Hosea Kibet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 05:35:05