下一个步骤

下一个步骤 是 Next.js / React 应用程序的轻量级入载库。 它利用 动议 用于平滑动画,并支持包括Next.js,React Router,和Remix在内的多个回放框架.
一些使用案例:
- 方便登机: 引导新用户分步走
- 接触促进: 帮助 Docs 交互,因此用户通过 进行中。 。 。 .
- 更好的错误处理: 跳过通用烤面包机——向用户展示用量身定制的游览来修正的准确内容.
- 基于事件的旅行: 关键动作后触发自定义巡演,使用户得以回归.
库允许用户使用自定义卡(tooltips)来进行更方便的集成.
如果你喜欢这个项目,请留下一颗星星! ⭐️⭐️⭐️⭐️⭐️
开始
# npm
npm i nextstepjs motion
# pnpm
pnpm add nextstepjs motion
# yarn
yarn add nextstepjs motion
# bun
bun add nextstepjs motion
导航适配器(v2.0+)
NextStep 2.0通过导航适配器引入了框架不可知路由系统. 每个适配器被单独包装以最小化捆绑大小 - 只有您导入的适配器会包含在您的捆绑中 .
重要内容: 确保导入应用程序中所需的适配器,以便访问完整的功能. 没有适配器,导航功能就如
nextRoute财务报告和审定财务报表prevRoute也许不能正常工作.
内建适应器
下一个.js
NextStep 使用 Next.js 适配器作为默认,因此不需要导入.
// app/layout.tsx or pages/_app.tsx
import { NextStep, NextStepProvider } from 'nextstepjs';
export default function Layout({ children }) {
return (
<NextStepProvider>
<NextStep steps={steps}>{children}</NextStep>
</NextStepProvider>
);
}
将路由器作为框架
//app/root.tsx
import { NextStepProvider, NextStepReact, type Tour } from 'nextstepjs';
import { useReactRouterAdapter } from 'nextstepjs/adapters/react-router';
export default function App() {
return (
<NextStepProvider>
<NextStepReact navigationAdapter={useReactRouterAdapter} steps={steps}>
<Outlet />
</NextStepReact>
</NextStepProvider>
);
}
重混合
// root.tsx
import { NextStepProvider, NextStepReact } from 'nextstepjs';
import { useRemixAdapter } from 'nextstepjs/adapters/remix';
export default function App() {
return (
<NextStepProvider>
<NextStepReact navigationAdapter={useRemixAdapter} steps={steps}>
<Outlet />
</NextStepReact>
</NextStepProvider>
);
}
Vite (反应路由器或再混合) 的重要配置
如果您使用带有 React Router 或 Remix 的 Vite, 请在您的配置中添加以下配置 : vite.config.ts数字 :
export default defineConfig({
ssr: {
noExternal: ['nextstepjs', 'motion'],
},
});
Vite 还需要 next/navigation 被嘲笑,以便正常工作.
- 创建模拟文件
Next,例如next-navigation.ts并放入/src/mocks
// Mock for Next.js navigation to prevent build errors with nextstepjs
// This file is used to mock Next.js imports when using nextstepjs in a Vite app
export const useRouter = () => {
return {
push: () => {},
replace: () => {},
prefetch: () => {},
back: () => {},
forward: () => {},
refresh: () => {},
};
};
export const usePathname = () => {
return '';
};
export const useSearchParams = () => {
return new URLSearchParams();
};
export const useParams = () => {
return {};
};
- 更新
vite.config.mts为 Next.js 导航导入使用适当的别名
import path from 'node:path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
resolve: {
alias: [
// Mock Next.js navigation imports that nextstepjs might try to access
{
find: 'next/navigation',
replacement: path.join(process.cwd(), 'src/mocks/next-navigation.ts'),
},
]
}
})
自定义导航适配器
通过执行 NavigationAdapter 接口 :
import { NextStepReact } from 'nextstepjs';
import type { NavigationAdapter } from 'nextstepjs';
const useCustomAdapter = (): NavigationAdapter => {
return {
push: (path: string) => {
// Your navigation logic here
// Example: history.push(path)
},
getCurrentPath: () => {
// Your path retrieval logic here
// Example: window.location.pathname
return window.location.pathname;
},
};
};
const App = () => {
return (
<NextStepReact navigationAdapter={useCustomAdapter} steps={steps}>
{children}
</NextStepReact>
);
};
解决问题
如果您在使用 Pages 路由器时遇到与模块导出有关的错误, 可能是由于 ES 模块( 使用) 之间的不匹配 export 语句)和通用JS模块(使用 module.exports) (中文(简体) ). 这个 nextstepjs 软件包使用 ES 模块语法, 但是您的 Next.js 项目可能会被设置为使用 CommunityJS .
要解决这个问题,请确保您的 Next.js 项目配置支持ES模块 。 你可以通过更新您的 next.config.js 包含以下配置的文件 :
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
experimental: {
esmExternals: true,
},
transpilePackages: ['nextstepjs'],
};
export default nextConfig;
自定义卡
您可以创建自定义卡组件, 以更好地控制设计 :
| Prop | 类型 | 说明 |
|---|---|---|
step | Object | 当前 Step 对象,包括内容、标题等. |
currentStep | number | 步骤数组中当前步骤的索引. |
totalSteps | number | 入职过程的步数总数. |
nextStep | 推进入职过程下一步的函数 . | |
prevStep | 返回登入过程中的前一步的函数 . | |
arrow | 返回 SVG 对象,方向由步骤侧道具控制 | |
skipTour | 跳过巡演的函数 |
'use client';
import type { CardComponentProps } from 'nextstepjs';
export const CustomCard = ({
step,
currentStep,
totalSteps,
nextStep,
prevStep,
skipTour,
arrow,
}: CardComponentProps) => {
return (
<div>
<h1>
{step.icon} {step.title}
</h1>
<h2>
{currentStep} of {totalSteps}
</h2>
<p>{step.content}</p>
<button onClick={prevStep}>Previous</button>
<button onClick={nextStep}>Next</button>
<button onClick={skipTour}>Skip</button>
{arrow}
</div>
);
};
旅游阵列
NextStep 支持多个"tours",允许您创建多个产品巡演:
import { Tour } from 'nextstepjs';
const steps: Tour[] = [
{
tour: 'firstTour',
steps: [
// Step objects
],
},
{
tour: 'secondTour',
steps: [
// Step objects
],
},
];
步骤对象
| Prop | 类型 | 说明 |
|---|---|---|
icon | React.ReactNode, (中文(简体) ), string, (中文(简体) ), null | 与步骤标题并列显示的图标或元素 . |
title | string | 你台阶的头衔 |
content | React.ReactNode | 步骤的主要内容或正文. |
selector | string | 可选的 用于瞄准的字符串 id 这一步指的是。 如果不提供卡片,卡片将显示在文档正文的正中央. |
side | "top", (中文(简体) ), "bottom", (中文(简体) ), "left", (中文(简体) ), "right" | 可选的 确定工具提示相对于选择器的显示位置. |
showControls | boolean | 可选的 确定如果使用默认的卡片,是否显示控制按钮(next, prev). |
showSkip | boolean | 可选的 确定如果使用默认卡,是否显示跳过按钮. |
blockKeyboardControl | boolean | 可选的 确定是否应当屏蔽键盘控制 |
pointerPadding | number | 可选的 指针(键孔)周围的粘贴会突出目标元素. |
pointerRadius | number | 可选的 指针(keyhole)的边-射线突出出目标元素. |
nextRoute | string | 可选的 移动到下一步时的导航路线 . |
prevRoute | string | 可选的 移动到上一步时要导航的路径 . |
viewportID | string | 可选的 用于定位的取景点元素的ID. 如果不提供,则使用文件正文. |
说明
NextStep处理屏幕边的卡片截取。 如果侧面是右或左,卡片是从取景口出,则侧面将切换到top。如果侧为上下,而卡片则出自取景口,则侧会从上到下翻转.
目标任何东西
用元素瞄准应用程序中的任何内容 id 属性.
<div id="nextstep-step1">Onboard Step</div>
巡回赛期间的路线
NextStep 允许您在使用 nextRoute 财务报告和审定财务报表 prevRoute 属性。 这些属性可以在应用程序的不同页面或部分之间实现无缝过渡.
nextRoute: 指定在单击“ Next” 按钮时要导航的路径.prevRoute: 指定在单击“上”按钮时要导航的路径.
何时 nextRoute 或者说 prevRoute 中提供, NextStep 将使用 Next.js 的 next/navigation 以导航到指定的路径.
使用 NextStepViewport 和视图端口ID
当选择者处于可滚动区域时,最好将可滚动区域的内容以 NextStepViewport。本部分需要 children 还有一个 id 作为道具。 通过提供 viewportID 到该步骤,NextStep将在视图端口内瞄准此元素。 这保证了即使容器可滚动,步骤仍被固定在元素上.
这里有一个如何使用的例子 NextStepViewport数字 :
<div className="relative overflow-auto h-64">
<NextStepViewport id="scrollable-viewport">{children}</NextStepViewport>
</div>
示例 steps
[
{
tour: 'firsttour',
steps: [
{
icon: <>👋</>,
title: 'Tour 1, Step 1',
content: <>First tour, first step</>,
selector: '#tour1-step1',
side: 'top',
showControls: true,
showSkip: true,
pointerPadding: 10,
pointerRadius: 10,
nextRoute: '/foo',
prevRoute: '/bar',
},
{
icon: <>🎉</>,
title: 'Tour 1, Step 2',
content: <>First tour, second step</>,
selector: '#tour1-step2',
side: 'top',
showControls: true,
showSkip: true,
pointerPadding: 10,
pointerRadius: 10,
viewportID: 'scrollable-viewport',
},
],
},
{
tour: 'secondtour',
steps: [
{
icon: <>🚀</>,
title: 'Second tour, Step 1',
content: <>Second tour, first step!</>,
selector: '#nextstep-step1',
side: 'top',
showControls: true,
showSkip: true,
pointerPadding: 10,
pointerRadius: 10,
nextRoute: '/foo',
prevRoute: '/bar',
},
],
},
];
下一步骤和下一步骤反应
| 财产 | 类型 | 说明 |
|---|---|---|
children | React.ReactNode | 您的网站或应用程序内容 |
steps | Array[] | 定义入职每一步骤的旅游对象阵列 |
navigationAdapter | NavigationAdapter | 可选的 导航的路由器适配器( NextStep 上的默认为 Next.js , NextStep React 上的窗口适配器) |
showNextStep | boolean | 控制上载覆盖的能见度 |
shadowRgb | string | 目标区域的阴影颜色的 RGB 值 |
shadowOpacity | string | 目标区域的阴影不透明值 |
cardComponent | React.ComponentType | 自定义取代默认的卡组件 |
cardTransition | Transition | 步骤过渡的运动过渡对象 |
onStart | (tourName: string | null) => void | 当巡演开始时触发回调功能 |
onStepChange | (step: number, tourName: string | null) => void | 当步骤改变时触发回调函数 |
onComplete | (tourName: string | null) => void | 当巡演结束时触发回调功能 |
onSkip | (step: number, tourName: string | null) => void | 当用户跳过巡演时触发回调功能 |
clickThroughOverlay | boolean | 可选的 如果真实, 覆盖背景可以点击, 默认为虚假 |
disableConsoleLogs | boolean | 可选的 如果选中的话, 控制台日志已被禁用, 默认为虚假 |
scrollToTop | boolean | 可选的 如果选中的话, 页面会滚动到顶端, 默认为真实 |
noInViewScroll | boolean | 可选的 如果选中, 页面将不会滚动到目标元素, 默认为虚假 |
<NextStep
steps={steps}
showNextStep={true}
shadowRgb="55,48,163"
shadowOpacity="0.8"
cardComponent={CustomCard}
cardTransition={{ duration: 0.5, type: 'spring' }}
onStepChange={(step, tourName) => console.log(`Step changed to ${step} in ${tourName}`)}
onComplete={(tourName) => console.log(`Tour completed: ${tourName}`)}
onSkip={(step, tourName) => console.log(`Tour skipped: ${step} in ${tourName}`)}
clickThroughOverlay={false}
>
{children}
</NextStep>
使用NextStep 钩
使用"NextStep"钩子可以控制从应用程序中任意位置的出行.
import { useNextStep } from 'nextstepjs';
....
const { startNextStep, closeNextStep } = useNextStep();
const onClickHandler = (tourName: string) => {
startNextStep(tourName);
};
键盘导航
NextStep 支持键盘导航 :
- 右箭头:下一步
- 左箭头:上一个步骤
- 越狱:跳过巡演
本地化
NextStep 是一个轻量级库,不附带本地化支持. 不过,您可以通过提供 steps 以地方为基础的数组.
捐款
欢迎捐款! 请随意提交拉力请求.
许可证
这个项目根据麻省理工学院的许可证获得许可.
贷项
- 奥诺瓦 对于灵感和一些代码片段.