diff --git a/site/mobile/mobile.config.js b/site/mobile/mobile.config.js index f5d9055ee..efd28a318 100644 --- a/site/mobile/mobile.config.js +++ b/site/mobile/mobile.config.js @@ -235,7 +235,7 @@ export default { { title: 'Steps 步骤条', name: 'steps', - component: () => import('tdesign-mobile-react/steps/_example/index.jsx'), + component: () => import('tdesign-mobile-react/steps/_example/index.tsx'), }, { title: 'TabBar 标签栏', diff --git a/src/_common b/src/_common index 001b9dc74..0e8be532c 160000 --- a/src/_common +++ b/src/_common @@ -1 +1 @@ -Subproject commit 001b9dc746ef42b3ebf738d643a006e3518731b9 +Subproject commit 0e8be532cf8cf49b79f73de578f1f58557900a5d diff --git a/src/steps/StepItem.tsx b/src/steps/StepItem.tsx index 2947854d8..d17b17657 100644 --- a/src/steps/StepItem.tsx +++ b/src/steps/StepItem.tsx @@ -1,11 +1,13 @@ -import React, { FC, useContext, useMemo } from 'react'; -import classnames from 'classnames'; -import { Icon } from 'tdesign-icons-react'; +import React, { FC, useContext, useEffect, useMemo, useRef, MouseEvent } from 'react'; +import classNames from 'classnames'; +import { CheckIcon, CloseIcon } from 'tdesign-icons-react'; import withNativeProps, { NativeProps } from '../_util/withNativeProps'; +import parseTNode from '../_util/parseTNode'; +import useDefaultProps from '../hooks/useDefaultProps'; +import { usePrefixClass } from '../hooks/useClass'; import { TdStepItemProps } from './type'; -import useConfig from '../_util/useConfig'; import { stepItemDefaultProps } from './defaultProps'; -import StepsContext from './StepsContext'; +import { StepsContext } from './StepsContext'; export enum StepItemStatusEnum { DEFAULT = 'default', @@ -19,106 +21,164 @@ export enum StepThemeEnum { DOT = 'dot', } -export enum StepLayoutEnum { - VERTICAL = 'vertical', - HORIZONTAL = 'horizontal', -} - -export interface StepItemProps extends TdStepItemProps, NativeProps { - index: number; -} +export interface StepItemProps extends TdStepItemProps, NativeProps {} const StepItem: FC = (props) => { - const { title, content, icon, status, index, children } = props; - - const { value, readonly, theme, layout, onChange } = useContext(StepsContext); + const { title, content, icon, status, children, titleRight, extra } = useDefaultProps(props, stepItemDefaultProps); + + const stepItemClass = usePrefixClass('step-item'); + const stepItemRef = useRef(null); + + const { + childrenNodes, + current, + relation, + removeRelation, + onClickItem, + currentStatus: stepsStatus, + layout, + readonly, + theme, + sequence, + } = useContext(StepsContext); + + useEffect(() => { + relation(stepItemRef.current); + const stepItemCur = stepItemRef.current; + return () => { + removeRelation(stepItemCur); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const index = useMemo(() => childrenNodes.indexOf(stepItemRef.current), [childrenNodes]); + const isLastChild = useMemo( + () => index === (sequence === 'positive' ? childrenNodes.length - 1 : 0), + [index, sequence, childrenNodes], + ); - const { classPrefix } = useConfig(); + const dot = useMemo(() => theme === StepThemeEnum.DOT, [theme]); + const currentStatus = useMemo(() => { + if (status !== 'default') return status; + if (index === current) return stepsStatus; + if (index < +current) return 'finish'; + return status; + }, [index, current, stepsStatus, status]); + + const rootClassName = useMemo( + () => + classNames(stepItemClass, `${stepItemClass}--${layout}`, { + [`${stepItemClass}--default`]: readonly, + [`${stepItemClass}--${currentStatus}`]: currentStatus, + }), + [stepItemClass, layout, readonly, currentStatus], + ); - const name = `${classPrefix}-step`; + const iconWrapperClassName = useMemo( + () => classNames(`${stepItemClass}__anchor`, `${stepItemClass}__anchor--${layout}`), + [stepItemClass, layout], + ); + const dotClassName = useMemo( + () => classNames(`${stepItemClass}__dot`, `${stepItemClass}__dot--${currentStatus}`), + [stepItemClass, currentStatus], + ); + const iconClassName = useMemo( + () => + classNames({ + [`${stepItemClass}__icon`]: icon, + [`${stepItemClass}__icon--${currentStatus}`]: icon, + [`${stepItemClass}__circle`]: !icon, + [`${stepItemClass}__circle--${currentStatus}`]: !icon, + }), + [stepItemClass, currentStatus, icon], + ); + const contentClassName = useMemo( + () => + classNames(`${stepItemClass}__content`, `${stepItemClass}__content--${layout}`, { + [`${stepItemClass}__content--last`]: isLastChild, + }), + [stepItemClass, layout, isLastChild], + ); - const dot = useMemo(() => theme === StepThemeEnum.DOT && layout === StepLayoutEnum.VERTICAL, [theme, layout]); + const titleClassName = useMemo( + () => + classNames( + `${stepItemClass}__title`, + `${stepItemClass}__title--${currentStatus}`, + `${stepItemClass}__title--${layout}`, + ), + [stepItemClass, currentStatus, layout], + ); + const descriptionClassName = useMemo( + () => + classNames( + `${stepItemClass}__description`, + `${stepItemClass}__description--${currentStatus}`, + `${stepItemClass}__description--${layout}`, + ), + [stepItemClass, currentStatus, layout], + ); + const extraClassName = useMemo( + () => + classNames( + `${stepItemClass}__extra`, + `${stepItemClass}__extra--${currentStatus}`, + `${stepItemClass}__extra--${layout}`, + ), + [stepItemClass, currentStatus, layout], + ); + const separatorClassName = useMemo( + () => + classNames( + `${stepItemClass}__line`, + `${stepItemClass}__line--${currentStatus}`, + `${stepItemClass}__line--${sequence}`, + `${stepItemClass}__line--${layout}`, + `${stepItemClass}__line--${theme}`, + ), + [stepItemClass, currentStatus, layout, sequence, theme], + ); - const onStepClick = (e) => { - if (readonly || dot) return; - const currentValue = index; - onChange(currentValue, value, { e }); + const onStepClick = (e: MouseEvent) => { + if (readonly) return; + onClickItem(index, current, { e }); }; - const innerClassName = useMemo(() => { - if (typeof icon === 'boolean') { - return `${name}__inner`; + const renderIconContent = () => { + if (icon) { + return parseTNode(icon); } - return classnames(`${name}__inner`, `${name}__inner__icon`); - }, [name, icon]); - const iconContent = useMemo(() => { - if (dot) { - return ''; + if (currentStatus === StepItemStatusEnum.ERROR) { + return ; } - if (status === StepItemStatusEnum.ERROR) { - return ; + if (currentStatus === StepItemStatusEnum.FINISH) { + return ; } - if (index < value && readonly) { - return ; - } - - if (typeof icon === 'boolean') { - return index + 1; - } - - if (typeof icon === 'string') { - return ; - } - - return icon; - }, [status, index, value, readonly, icon, dot]); - - const currentStatus = useMemo(() => { - if (status !== StepItemStatusEnum.DEFAULT) { - return status; - } - if (+value === index) { - return StepItemStatusEnum.PROCESS; - } - if (+value > index) { - return StepItemStatusEnum.FINISH; - } - return ''; - }, [value, index, status]); + return index + 1; + }; return withNativeProps( props, -
-
-
-
- {iconContent} -
-
-
-
{title}
-
{content || children}
-
+
+
+ {dot ?
:
{renderIconContent()}
} +
+
+
+ {parseTNode(title)} + {layout === 'vertical' && parseTNode(titleRight)}
+
{parseTNode(content) || parseTNode(children)}
+
{parseTNode(extra)}
+ {!isLastChild &&
}
, ); }; StepItem.displayName = 'StepItem'; -StepItem.defaultProps = stepItemDefaultProps; export default StepItem; diff --git a/src/steps/Steps.tsx b/src/steps/Steps.tsx index 9d38aa467..a413a313b 100644 --- a/src/steps/Steps.tsx +++ b/src/steps/Steps.tsx @@ -1,12 +1,13 @@ -import React, { FC, useMemo } from 'react'; -import classnames from 'classnames'; +import React, { FC, useCallback, useMemo, useState } from 'react'; +import classNames from 'classnames'; import withNativeProps, { NativeProps } from '../_util/withNativeProps'; import useDefault from '../_util/useDefault'; +import parseTNode from '../_util/parseTNode'; +import { usePrefixClass } from '../hooks/useClass'; +import useDefaultProps from '../hooks/useDefaultProps'; import { TdStepsProps } from './type'; -import useConfig from '../_util/useConfig'; import { stepsDefaultProps } from './defaultProps'; -import StepsContext from './StepsContext'; -import StepItem from './StepItem'; +import { StepsProvider } from './StepsContext'; export interface StepsProps extends TdStepsProps, NativeProps {} @@ -16,51 +17,66 @@ const Steps: FC = (props) => { layout, readonly, theme, - separator, current, defaultCurrent, + sequence, + currentStatus, onChange: onCurrentChange, - options, - } = props; + } = useDefaultProps(props, stepsDefaultProps); - const { classPrefix } = useConfig(); - - const name = `${classPrefix}-steps`; + const stepsClass = usePrefixClass('steps'); const [value, onChange] = useDefault(current, defaultCurrent, onCurrentChange); - const stepItemList = useMemo(() => { - if (options) { - return options.map((item, index: number) => ); - } - return React.Children.map(children, (child: JSX.Element, index: number) => - React.cloneElement(child, { - index, + const [childrenNodes, setChildrenNodes] = useState([]); + + const stepsClassName = useMemo( + () => + classNames(stepsClass, `${stepsClass}--${layout}`, `${stepsClass}--${sequence}`, { + [`${stepsClass}--readonly`]: readonly, }), - ); - }, [children, options]); + [stepsClass, layout, sequence, readonly], + ); + + const relation = useCallback((ele: HTMLElement) => { + ele && setChildrenNodes((prev) => [...prev, ele]); + }, []); + + const removeRelation = useCallback((ele: HTMLElement) => { + setChildrenNodes((prev) => prev.filter((item) => item !== ele)); + }, []); + + const onClickItem = useCallback( + (cur, prev, context) => { + onChange(cur, prev, context); + }, + [onChange], + ); + + const memoProviderValues = useMemo( + () => ({ + childrenNodes, + current: value, + relation, + removeRelation, + onClickItem, + currentStatus, + layout, + readonly, + theme, + sequence, + }), + [childrenNodes, value, relation, removeRelation, onClickItem, currentStatus, layout, readonly, theme, sequence], + ); return withNativeProps( props, - -
- {stepItemList} -
-
, + +
{parseTNode(children)}
+
, ); }; Steps.displayName = 'Steps'; -Steps.defaultProps = stepsDefaultProps; export default Steps; diff --git a/src/steps/StepsContext.ts b/src/steps/StepsContext.ts deleted file mode 100644 index d1f13485f..000000000 --- a/src/steps/StepsContext.ts +++ /dev/null @@ -1,19 +0,0 @@ -import React, { MouseEvent } from 'react'; - -interface StepsContextProps { - value: string | number; - readonly: boolean; - theme: 'default' | 'dot'; - layout: 'horizontal' | 'vertical'; - onChange: (current: string | number, previous: string | number, context?: { e?: MouseEvent }) => void; -} - -const StepsContext = React.createContext({ - value: 0, - readonly: false, - onChange: null, - theme: 'default', - layout: 'horizontal', -}); - -export default StepsContext; diff --git a/src/steps/StepsContext.tsx b/src/steps/StepsContext.tsx new file mode 100644 index 000000000..c01aecfc5 --- /dev/null +++ b/src/steps/StepsContext.tsx @@ -0,0 +1,22 @@ +import React, { createContext, useMemo } from 'react'; +import { TdStepsProps } from './type'; + +interface StepsContextProps { + childrenNodes: HTMLElement[]; + current: TdStepsProps['current']; + relation: (ele: HTMLElement) => void; + removeRelation: (ele: HTMLElement) => void; + onClickItem: TdStepsProps['onChange']; + sequence: TdStepsProps['sequence']; + currentStatus: TdStepsProps['currentStatus']; + readonly: boolean; + theme: TdStepsProps['theme']; + layout: TdStepsProps['layout']; +} + +export const StepsContext = createContext(null); + +export function StepsProvider({ value, children }) { + const memoValue = useMemo(() => value, [value]); + return {children}; +} diff --git a/src/steps/__tests__/__snapshots__/demo.test.tsx.snap b/src/steps/__tests__/__snapshots__/demo.test.tsx.snap new file mode 100644 index 000000000..5510b23e6 --- /dev/null +++ b/src/steps/__tests__/__snapshots__/demo.test.tsx.snap @@ -0,0 +1,1892 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`Steps > Steps horizontalDemo demo 1`] = ` +
+
+ 水平带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+`; + +exports[`Steps > Steps specialDemo demo 1`] = ` +
+
+ 垂直自定义步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + + + +
+
+
+
+
+
+ +
+
+ 纯展示步骤条 +
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+`; + +exports[`Steps > Steps statusDemo demo 1`] = ` +
+
+ 选项卡状态 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+`; + +exports[`Steps > Steps verticalDemo demo 1`] = ` +
+
+ 垂直带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带可自定义此处内容步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+
+ 图标 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+`; diff --git a/src/steps/__tests__/demo.test.tsx b/src/steps/__tests__/demo.test.tsx new file mode 100644 index 000000000..426e1a581 --- /dev/null +++ b/src/steps/__tests__/demo.test.tsx @@ -0,0 +1,24 @@ +import { describe, expect, render, it } from '@test/utils'; +import React from 'react'; + +import horizontalDemo from '../_example/horizontal'; +import verticalDemo from '../_example/vertical'; +import statusDemo from '../_example/status'; +import specialDemo from '../_example/special'; + +const mapper = { + horizontalDemo, + verticalDemo, + statusDemo, + specialDemo, +}; + +describe('Steps', () => { + Object.keys(mapper).forEach((item) => { + it(`Steps ${item} demo`, () => { + const DemoComponent = mapper[item]; + const { container } = render(); + expect(container.firstChild).toMatchSnapshot(); + }); + }); +}); diff --git a/src/steps/__tests__/index.test.tsx b/src/steps/__tests__/index.test.tsx new file mode 100644 index 000000000..fc7ca631a --- /dev/null +++ b/src/steps/__tests__/index.test.tsx @@ -0,0 +1,270 @@ +import React from 'react'; +import { describe, expect, it, render, fireEvent, vi } from '@test/utils'; +import { Icon } from 'tdesign-icons-react'; +import { Steps, StepItem, StepStatus } from '../index'; +import { Image } from '../../image'; + +const prefix = 't'; +const steps = `${prefix}-steps`; +const stepItem = `${prefix}-step-item`; + +const items = [ + { + title: '步骤描述1', + content: '辅助信息文字最多两行1', + }, + { + title: '步骤描述2', + content: '辅助信息文字最多两行2', + }, + { + title: '步骤描述3', + content: '辅助信息文字最多两行3', + }, +]; +const itemStatus = [ + { + title: '步骤描述1', + content: '辅助信息文字最多两行1', + status: 'error', + }, + { + title: '步骤描述2', + content: '辅助信息文字最多两行2', + status: 'process', + }, +]; + +describe('Steps', () => { + describe('props', () => { + it('layout & theme', () => { + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + expect(container.querySelector(`.${steps}`).classList.contains(`${steps}--vertical`)).toBeTruthy(); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + expect($stepItems.length).toEqual(items.length); + $stepItems.forEach((item, index) => { + expect(item.querySelector(`.${stepItem}__dot`)).toBeTruthy(); + if (index === $stepItems.length - 1) { + expect(item.querySelector(`.${stepItem}__line`)).toBeNull(); + } else { + expect(item.querySelector(`.${stepItem}__line`)).toBeTruthy(); + } + }); + }); + + it('readonly', () => { + const onClick = vi.fn(); + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + fireEvent.click($stepItems[1]); + expect(onClick).toHaveBeenCalledTimes(0); + }); + + it('currentStatus', () => { + const current = 1; + const { container } = render( + + {items.map((item, index) => ( + } /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + const getStatus = (index) => { + if (index < current) { + return 'finish'; + } + if (index === current) { + return 'error'; + } + return 'default'; + }; + $stepItems.forEach((item, index) => { + expect(item.classList.contains(`${stepItem}--${getStatus(index)}`)); + }); + }); + + it('sequence', () => { + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item, index) => { + if (index === 0) { + expect(item.querySelector(`.${stepItem}__line`)).toBeNull(); + } else { + expect(item.querySelector(`.${stepItem}__line`)).toBeTruthy(); + } + }); + }); + + it('change steps', () => { + const stepItems = [...items]; + const { container, rerender } = render( + + {stepItems.map((item, index) => ( + + ))} + , + ); + stepItems.pop(); + rerender( + + {stepItems.map((item, index) => ( + + ))} + , + ); + expect(container.querySelectorAll(`.${stepItem}`).length).toEqual(stepItems.length); + }); + }); + + describe('events', () => { + it('onChange', () => { + const onClick = vi.fn(); + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + fireEvent.click($stepItems[1]); + expect(onClick).toHaveBeenCalledTimes(1); + expect(onClick).toHaveBeenCalledWith( + 1, + 0, + expect.objectContaining({ + e: expect.objectContaining({ + type: 'click', + }), + }), + ); + }); + }); +}); + +describe('StepItem', () => { + describe('props', () => { + it('title and content', () => { + const { container } = render( + + {items.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + + $stepItems.forEach((item, index) => { + expect(item.querySelector(`.${stepItem}__title`).textContent).toBe(items[index].title); + expect(item.querySelector(`.${stepItem}__description`).textContent).toBe(items[index].content); + }); + }); + + it('icon', () => { + const { container } = render( + + {items.map((item, index) => ( + } /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item) => { + expect(item.querySelector(`.${stepItem}__icon`)).toBeTruthy(); + expect(item.querySelector(`.${prefix}-icon-cart`)).toBeTruthy(); + }); + }); + + it('extra', () => { + const { container } = render( + + {items.map((item, index) => ( + + ) + } + /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + const $extra = $stepItems[1].querySelector(`.${stepItem}__extra`); + expect($extra).toBeTruthy(); + expect($extra.querySelector('img')).toBeTruthy(); + }); + + it('status', () => { + const current = 1; + const { container } = render( + + {itemStatus.map((item, index) => ( + + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item, index) => { + expect(item.classList.contains(`${stepItem}--${itemStatus[index].status}`)); + }); + }); + + it('titleRight', () => { + const { container } = render( + + {items.map((item, index) => ( + } + /> + ))} + , + ); + const $stepItems = container.querySelectorAll(`.${stepItem}`); + $stepItems.forEach((item) => { + expect(item.querySelector(`.${prefix}-icon.${prefix}-icon-chevron-right`)).toBeTruthy(); + }); + const { container: container2 } = render( + + {items.map((item, index) => ( + } + /> + ))} + , + ); + const $stepItems2 = container2.querySelectorAll(`.${stepItem}`); + $stepItems2.forEach((item) => { + expect(item.querySelector(`.${prefix}-icon`)).toBeNull(); + }); + }); + }); +}); diff --git a/src/steps/_example/click.jsx b/src/steps/_example/click.jsx deleted file mode 100644 index 403b33ac0..000000000 --- a/src/steps/_example/click.jsx +++ /dev/null @@ -1,54 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Click() { - const [current1, setCurrent1] = useState(1); - const [current2] = useState(1); - const [current3] = useState(1); - const stepItemList = [ - { - title: '步骤描述', - content: '辅助信息文字最多两行', - }, - { - title: '步骤描述', - content: '辅助信息文字最多两行', - }, - ]; - return ( - <> - { - setCurrent1(value); - }} - > - - - - - - - - - - - - - - - - - - - - - - - - - - - - ); -} diff --git a/src/steps/_example/content.jsx b/src/steps/_example/content.jsx deleted file mode 100644 index ea1733aeb..000000000 --- a/src/steps/_example/content.jsx +++ /dev/null @@ -1,29 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Content() { - const [current] = useState(1); - return ( - <> - - - 可自定义此处内容,可自定义此处内容,可自定义此处内容可自定义此处内容可自定义此处内容。 - -
- } - /> - - - - - ); -} diff --git a/src/steps/_example/horizontal.jsx b/src/steps/_example/horizontal.jsx deleted file mode 100644 index 1760f7c20..000000000 --- a/src/steps/_example/horizontal.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Horizontal() { - return ( - <> -
- - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - -
-
- - - - - - - - - - - - - - - - - - -
- - ); -} diff --git a/src/steps/_example/horizontal.tsx b/src/steps/_example/horizontal.tsx new file mode 100644 index 000000000..03f97ccaf --- /dev/null +++ b/src/steps/_example/horizontal.tsx @@ -0,0 +1,71 @@ +import React, { useState } from 'react'; +import { Steps, StepItem } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(1); + const [second, setSecond] = useState(1); + const [third, setThird] = useState(1); + const options = { + first, + second, + third, + }; + + const count = 4; + const onFirstChange = (current: number) => { + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + const onThirdChange = (current: number) => { + setThird(current); + }; + + const getTitle = (type: 'first' | 'second' | 'third', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成'; + } + }; + + return ( +
+
水平带序号步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
水平带图标步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
水平简略步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
+ ); +} diff --git a/src/steps/_example/icon.jsx b/src/steps/_example/icon.jsx deleted file mode 100644 index b13617540..000000000 --- a/src/steps/_example/icon.jsx +++ /dev/null @@ -1,76 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; -import { UserIcon, LocationIcon, TimeIcon } from 'tdesign-icons-react' - -export default function Icon() { - const [current, setCurrent] = useState(1); - return ( - <> - { - setCurrent(value); - }} - > - - - - } - /> - - - - } - /> - - - - } - /> - - { - setCurrent(value); - }} - > - - - - } - /> - - - - } - /> - - - - } - /> - - - ); -} diff --git a/src/steps/_example/index.jsx b/src/steps/_example/index.jsx deleted file mode 100644 index 8cff8ef16..000000000 --- a/src/steps/_example/index.jsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import TDemoBlock from '../../../site/mobile/components/DemoBlock'; -import TDemoHeader from '../../../site/mobile/components/DemoHeader'; -import Click from './click'; -import Icon from './icon'; -import Horizontal from './horizontal'; -import Content from './content'; - -import './style/index.less'; -import Vertical from './vertical'; -import VerticalReadonly from './vertical-readonly'; - -export default function StepsDemo() { - return ( -
- - -
- -
-
- -
- -
-
- - - - -
- -
-
- -
- -
-
- -
- -
-
-
- ); -} diff --git a/src/steps/_example/index.tsx b/src/steps/_example/index.tsx new file mode 100644 index 000000000..13172208b --- /dev/null +++ b/src/steps/_example/index.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import TDemoBlock from '../../../site/mobile/components/DemoBlock'; +import TDemoHeader from '../../../site/mobile/components/DemoHeader'; +import Horizontal from './horizontal'; + +import './style/index.less'; +import Vertical from './vertical'; +import Status from './status'; +import Special from './special'; + +export default function StepsDemo() { + return ( +
+ + + + + + + + + + + +
+ ); +} diff --git a/src/steps/_example/special.tsx b/src/steps/_example/special.tsx new file mode 100644 index 000000000..45b8d94dc --- /dev/null +++ b/src/steps/_example/special.tsx @@ -0,0 +1,72 @@ +import React, { useState } from 'react'; +import { Steps, StepItem, Button } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(3); + const [second, setSecond] = useState(4); + const options = { + first, + second, + }; + + const [count1, setCount1] = useState(4); + const count = 4; + const onFirstChange = (current: number) => { + setCount1(current + 1); + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + + const toNext = () => { + setCount1((prev) => prev + 1); + setFirst(count1); + }; + + const getTitle = (type: 'first' | 'second', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成'; + } + }; + + return ( +
+
垂直自定义步骤条
+
+ + {Array.from({ length: count1 }).map((_, index) => ( + } + /> + ))} + + +
+
纯展示步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
+ ); +} diff --git a/src/steps/_example/status.tsx b/src/steps/_example/status.tsx new file mode 100644 index 000000000..786ae9ce5 --- /dev/null +++ b/src/steps/_example/status.tsx @@ -0,0 +1,69 @@ +import React, { useState } from 'react'; +import { Steps, StepItem } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(1); + const [second, setSecond] = useState(1); + const [third, setThird] = useState(1); + const options = { + first, + second, + third, + }; + + const count = 4; + const onFirstChange = (current: number) => { + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + const onThirdChange = (current: number) => { + setThird(current); + }; + + const getTitle = (type: 'first' | 'second' | 'third', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成'; + } + }; + + return ( +
+
选项卡状态
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
+ ); +} diff --git a/src/steps/_example/style/index.less b/src/steps/_example/style/index.less index d9b5deba2..e8c56380b 100644 --- a/src/steps/_example/style/index.less +++ b/src/steps/_example/style/index.less @@ -1,17 +1,10 @@ -.tdesign-mobile-block { - background-color: #ffffff; - padding: 40px 12px; - - & + & { - margin-top: 12px; - } - - .t-steps:not(:last-child) { - margin-bottom: 40px; - } - - &-icon { - width: 24px; - height: 24px; - } +.steps-horizontal-demo-block { + margin: 16px 0 24px; + padding: 16px 0; + background-color: var(--bg-color-demo, #fff); +} +.steps-vertical-demo-block { + margin: 16px 0 24px; + padding: 16px; + background-color: var(--bg-color-demo, #fff); } diff --git a/src/steps/_example/vertical-readonly.jsx b/src/steps/_example/vertical-readonly.jsx deleted file mode 100644 index 988236e9a..000000000 --- a/src/steps/_example/vertical-readonly.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Vertical() { - const [current] = useState(1); - return ( - <> - - - - - - - - - - - - ); -} diff --git a/src/steps/_example/vertical.jsx b/src/steps/_example/vertical.jsx deleted file mode 100644 index 2c343cbdc..000000000 --- a/src/steps/_example/vertical.jsx +++ /dev/null @@ -1,14 +0,0 @@ -import React, { useState } from 'react'; -import { Steps } from 'tdesign-mobile-react'; - -export default function Vertical() { - const [current] = useState(1); - // 竖向简化只读步骤条 - return ( - - - - - - ); -} diff --git a/src/steps/_example/vertical.tsx b/src/steps/_example/vertical.tsx new file mode 100644 index 000000000..29cc1ac86 --- /dev/null +++ b/src/steps/_example/vertical.tsx @@ -0,0 +1,93 @@ +import React, { useState } from 'react'; +import { Steps, StepItem, Image } from 'tdesign-mobile-react'; +import { Icon } from 'tdesign-icons-react'; + +export default function StepsDemo() { + const [first, setFirst] = useState(1); + const [second, setSecond] = useState(1); + const [third, setThird] = useState(1); + const [four, setFour] = useState(1); + const options = { + first, + second, + third, + four, + }; + + const count = 4; + const onFirstChange = (current: number) => { + setFirst(current); + }; + const onSecondChange = (current: number) => { + setSecond(current); + }; + const onThirdChange = (current: number) => { + setThird(current); + }; + const onFourChange = (current: number) => { + setFour(current); + }; + + const getTitle = (type: 'first' | 'second' | 'third' | 'four', index: number) => { + if (index === options[type]) { + return '当前步骤'; + } + if (index < options[type]) { + return '已完成'; + } + if (index > options[type]) { + return '未完成步骤'; + } + }; + + return ( +
+
垂直带序号步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
垂直带图标步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + } + > + ))} + +
+
垂直简略步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ))} + +
+
垂直带可自定义此处内容步骤条
+
+ + {Array.from({ length: count }).map((_, index) => ( + + ) + } + /> + ))} + +
+
+ ); +} diff --git a/src/steps/defaultProps.ts b/src/steps/defaultProps.ts index 05ab65024..f4e602a9c 100644 --- a/src/steps/defaultProps.ts +++ b/src/steps/defaultProps.ts @@ -5,10 +5,11 @@ import { TdStepsProps, TdStepItemProps } from './type'; export const stepsDefaultProps: TdStepsProps = { + currentStatus: 'process', layout: 'horizontal', readonly: false, - separator: 'line', + sequence: 'positive', theme: 'default', }; -export const stepItemDefaultProps: TdStepItemProps = { icon: true, status: 'default' }; +export const stepItemDefaultProps: TdStepItemProps = { content: '', status: 'default', title: '', titleRight: '' }; diff --git a/src/steps/index.tsx b/src/steps/index.tsx index 797cd5dde..b3df6df62 100644 --- a/src/steps/index.tsx +++ b/src/steps/index.tsx @@ -9,5 +9,6 @@ export * from './type'; export const Steps = _Steps; (Steps as any).StepItem = _StepItem; +export const StepItem = _StepItem; export default Steps; diff --git a/src/steps/steps.en-US.md b/src/steps/steps.en-US.md new file mode 100644 index 000000000..c2a243947 --- /dev/null +++ b/src/steps/steps.en-US.md @@ -0,0 +1,33 @@ +:: BASE_DOC :: + +## API + +### Steps Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +current | String / Number | - | \- | N +defaultCurrent | String / Number | - | uncontrolled property | N +currentStatus | String | process | options: default/process/finish/error | N +layout | String | horizontal | options: horizontal/vertical | N +readonly | Boolean | false | \- | N +sequence | String | positive | options: positive/reverse | N +theme | String | default | options: default/dot | N +onChange | Function | | Typescript:`(current: string \| number, previous: string \| number, context?: { e?: MouseEvent }) => void`
| N + + +### StepItem Props + +name | type | default | description | required +-- | -- | -- | -- | -- +className | String | - | className of component | N +style | Object | - | CSS(Cascading Style Sheets),Typescript:`React.CSSProperties` | N +children | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +content | TNode | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +extra | TNode | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +icon | TNode | - | Typescript:`boolean \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +status | String | default | options: default/process/finish/error。Typescript:`StepStatus` `type StepStatus = 'default' \| 'process' \| 'finish' \| 'error'`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/steps/type.ts) | N +title | TNode | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +titleRight | TNode | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N diff --git a/src/steps/steps.md b/src/steps/steps.md index 6775b0708..79b778241 100644 --- a/src/steps/steps.md +++ b/src/steps/steps.md @@ -1,29 +1,33 @@ :: BASE_DOC :: ## API + ### Steps Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N current | String / Number | - | 当前步骤,即整个步骤条进度。默认根据步骤下标判断步骤的完成状态,当前步骤为进行中,当前步骤之前的步骤为已完成,当前步骤之后的步骤为未开始。如果每个步骤没有设置 value,current 值为步骤长度则表示所有步骤已完成。如果每个步骤设置了自定义 value,则 current = 'FINISH' 表示所有状态完成 | N defaultCurrent | String / Number | - | 当前步骤,即整个步骤条进度。默认根据步骤下标判断步骤的完成状态,当前步骤为进行中,当前步骤之前的步骤为已完成,当前步骤之后的步骤为未开始。如果每个步骤没有设置 value,current 值为步骤长度则表示所有步骤已完成。如果每个步骤设置了自定义 value,则 current = 'FINISH' 表示所有状态完成。非受控属性 | N +currentStatus | String | process | 用于控制 current 指向的步骤条的状态。可选项:default/process/finish/error | N layout | String | horizontal | 步骤条方向,有两种:横向和纵向。可选项:horizontal/vertical | N -options | Array | - | 步骤条数据列表(作用和 StepItem 效果一样)。TS 类型:`Array` | N readonly | Boolean | false | 只读状态 | N -separator | String | line | 步骤条分割符。可选项:line/dashed/arrow | N +sequence | String | positive | 步骤条顺序。可选项:positive/reverse | N theme | String | default | 步骤条风格。可选项:default/dot | N -onChange | Function | | TS 类型:`(current: string | number, previous: string | number, context?: { e?: MouseEvent }) => void`
当前步骤发生变化时触发 | N +onChange | Function | | TS 类型:`(current: string \| number, previous: string \| number, context?: { e?: MouseEvent }) => void`
当前步骤发生变化时触发 | N + ### StepItem Props -名称 | 类型 | 默认值 | 说明 | 必传 +名称 | 类型 | 默认值 | 描述 | 必传 -- | -- | -- | -- | -- className | String | - | 类名 | N style | Object | - | 样式,TS 类型:`React.CSSProperties` | N -children | TNode | - | 步骤描述,同 content。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -content | TNode | '' | 步骤描述。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -icon | TNode | true | 图标,默认显示内置图标,也可以自定义图标,值为 false 则不显示图标。优先级大于 `status` 定义的图标。TS 类型:`boolean | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N -status | String | default | 当前步骤的状态。可选项:default/process/finish/error。TS 类型:`StepStatus` `type StepStatus = 'default' | 'process' | 'finish' | 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/steps/type.ts) | N -title | TNode | '' | 标题。TS 类型:`string | TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +children | TNode | - | 步骤描述,同 content。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +content | TNode | '' | 步骤描述。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +extra | TNode | - | 显示在步骤描述下方的额外内容,比如:操作项。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +icon | TNode | - | 图标,默认显示内置图标,也可以自定义图标,值为 false 则不显示图标。优先级大于 `status` 定义的图标。TS 类型:`boolean \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +status | String | default | 当前步骤的状态:默认状态(未开始)、进行中状态、完成状态、错误状态。可选项:default/process/finish/error。TS 类型:`StepStatus` `type StepStatus = 'default' \| 'process' \| 'finish' \| 'error'`。[详细类型定义](https://github.com/Tencent/tdesign-mobile-react/tree/develop/src/steps/type.ts) | N +title | TNode | '' | 标题。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N +titleRight | TNode | '' | 标题右侧数据 仅支持 layout = 'vertical' 时。TS 类型:`string \| TNode`。[通用类型定义](https://github.com/Tencent/tdesign-mobile-react/blob/develop/src/common.ts) | N diff --git a/src/steps/style/index.js b/src/steps/style/index.js index 6156d9cfe..5ce6b9cda 100644 --- a/src/steps/style/index.js +++ b/src/steps/style/index.js @@ -1 +1,2 @@ -import '../../_common/style/mobile/components/steps/_index.less'; +import '../../_common/style/mobile/components/steps/v2/_index.less'; +import '../../_common/style/mobile/components/step-item/v2/_index.less'; diff --git a/src/steps/type.ts b/src/steps/type.ts index e2641c221..68435e743 100644 --- a/src/steps/type.ts +++ b/src/steps/type.ts @@ -16,25 +16,26 @@ export interface TdStepsProps { * 当前步骤,即整个步骤条进度。默认根据步骤下标判断步骤的完成状态,当前步骤为进行中,当前步骤之前的步骤为已完成,当前步骤之后的步骤为未开始。如果每个步骤没有设置 value,current 值为步骤长度则表示所有步骤已完成。如果每个步骤设置了自定义 value,则 current = 'FINISH' 表示所有状态完成,非受控属性 */ defaultCurrent?: string | number; + /** + * 用于控制 current 指向的步骤条的状态 + * @default process + */ + currentStatus?: 'default' | 'process' | 'finish' | 'error'; /** * 步骤条方向,有两种:横向和纵向 * @default horizontal */ layout?: 'horizontal' | 'vertical'; - /** - * 步骤条数据列表(作用和 StepItem 效果一样) - */ - options?: Array; /** * 只读状态 * @default false */ readonly?: boolean; /** - * 步骤条分割符 - * @default line + * 步骤条顺序 + * @default positive */ - separator?: 'line' | 'dashed' | 'arrow'; + sequence?: 'positive' | 'reverse'; /** * 步骤条风格 * @default default @@ -60,13 +61,16 @@ export interface TdStepItemProps { * @default '' */ content?: TNode; + /** + * 显示在步骤描述下方的额外内容,比如:操作项 + */ + extra?: TNode; /** * 图标,默认显示内置图标,也可以自定义图标,值为 false 则不显示图标。优先级大于 `status` 定义的图标 - * @default true */ icon?: TNode; /** - * 当前步骤的状态 + * 当前步骤的状态:默认状态(未开始)、进行中状态、完成状态、错误状态 * @default default */ status?: StepStatus; @@ -75,6 +79,11 @@ export interface TdStepItemProps { * @default '' */ title?: TNode; + /** + * 标题右侧数据 仅支持 layout = 'vertical' 时 + * @default '' + */ + titleRight?: TNode; } export type StepStatus = 'default' | 'process' | 'finish' | 'error'; diff --git a/test/snap/__snapshots__/csr.test.jsx.snap b/test/snap/__snapshots__/csr.test.jsx.snap index e0bcada2d..17ad00991 100644 --- a/test/snap/__snapshots__/csr.test.jsx.snap +++ b/test/snap/__snapshots__/csr.test.jsx.snap @@ -54459,6 +54459,3858 @@ exports[`csr snapshot test > csr test src/stepper/_example/theme.tsx 1`] = `
`; +exports[`csr snapshot test > csr test src/steps/_example/horizontal.tsx 1`] = ` +
+
+
+ 水平带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/index.tsx 1`] = ` +
+
+
+

+ Steps 步骤条 +

+

+ 用于任务步骤展示或任务进度展示。 +

+
+
+
+

+ 01 组件类型 +

+
+
+
+
+ 水平带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+ 水平简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+ 垂直带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带可自定义此处内容步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+
+ 图标 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+

+ 02 组件状态 +

+
+
+
+
+ 选项卡状态 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+

+ 03 特殊类型 +

+
+
+
+
+ 垂直自定义步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + + + +
+
+
+
+
+
+ +
+
+ 纯展示步骤条 +
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/special.tsx 1`] = ` +
+
+
+ 垂直自定义步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 + + + +
+
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + + + +
+
+
+
+
+
+ +
+
+ 纯展示步骤条 +
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 步骤展示 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/status.tsx 1`] = ` +
+
+
+ 选项卡状态 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 已完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+
+
+
+ 未完成 +
+
+ 辅助信息 +
+
+
+
+
+
+
+
+`; + +exports[`csr snapshot test > csr test src/steps/_example/vertical.tsx 1`] = ` +
+
+
+ 垂直带序号步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 2 +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 3 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ 4 +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带图标步骤条 +
+
+
+
+
+
+ + + +
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+ + + +
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直简略步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+ 垂直带可自定义此处内容步骤条 +
+
+
+
+
+
+
+
+
+ 已完成 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 当前步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+
+ 图标 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+
+
+
+ 未完成步骤 + +
+
+ 可自定义此处内容 +
+
+
+
+
+
+
+
+`; + exports[`csr snapshot test > csr test src/sticky/_example/base.tsx 1`] = `
ssr test src/stepper/_example/status.tsx 1`] = `" ssr test src/stepper/_example/theme.tsx 1`] = `"
"`; +exports[`ssr snapshot test > ssr test src/steps/_example/horizontal.tsx 1`] = `"
水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/index.tsx 1`] = `"

Steps 步骤条

用于任务步骤展示或任务进度展示。

01 组件类型

水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容

02 组件状态

选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息

03 特殊类型

垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/special.tsx 1`] = `"
垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/status.tsx 1`] = `"
选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/vertical.tsx 1`] = `"
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
"`; + exports[`ssr snapshot test > ssr test src/sticky/_example/base.tsx 1`] = `"
"`; exports[`ssr snapshot test > ssr test src/sticky/_example/container.tsx 1`] = `"
"`; diff --git a/test/snap/__snapshots__/ssr.test.jsx.snap b/test/snap/__snapshots__/ssr.test.jsx.snap index 952773290..c0ea3d7e2 100644 --- a/test/snap/__snapshots__/ssr.test.jsx.snap +++ b/test/snap/__snapshots__/ssr.test.jsx.snap @@ -442,6 +442,16 @@ exports[`ssr snapshot test > ssr test src/stepper/_example/status.tsx 1`] = `" ssr test src/stepper/_example/theme.tsx 1`] = `"
"`; +exports[`ssr snapshot test > ssr test src/steps/_example/horizontal.tsx 1`] = `"
水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/index.tsx 1`] = `"

Steps 步骤条

用于任务步骤展示或任务进度展示。

01 组件类型

水平带序号步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平带图标步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
水平简略步骤条
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容

02 组件状态

选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息

03 特殊类型

垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/special.tsx 1`] = `"
垂直自定义步骤条
已完成
已完成
已完成
当前步骤
纯展示步骤条
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
步骤展示
可自定义此处内容
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/status.tsx 1`] = `"
选项卡状态
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
已完成
辅助信息
当前步骤
辅助信息
未完成
辅助信息
未完成
辅助信息
"`; + +exports[`ssr snapshot test > ssr test src/steps/_example/vertical.tsx 1`] = `"
垂直带序号步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带图标步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直简略步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
垂直带可自定义此处内容步骤条
已完成
可自定义此处内容
当前步骤
可自定义此处内容
图标
未完成步骤
可自定义此处内容
未完成步骤
可自定义此处内容
"`; + exports[`ssr snapshot test > ssr test src/sticky/_example/base.tsx 1`] = `"
"`; exports[`ssr snapshot test > ssr test src/sticky/_example/container.tsx 1`] = `"
"`;