mirror of
https://github.com/ant-design/ant-design.git
synced 2026-02-09 02:49:18 +08:00
feat(steps): Support better customization with semantic classNames/styles as function (#54956)
* feat(steps): Support better customization with semantic classNames/styles as function * test: update demo snapshot --------- Co-authored-by: 二货机器人 <smith3816@gmail.com>
This commit is contained in:
@@ -6282,6 +6282,281 @@ Array [
|
||||
|
||||
exports[`renders components/steps/demo/steps-in-steps.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/steps/demo/style-class.tsx extend context correctly 1`] = `
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
|
||||
>
|
||||
<div
|
||||
class="ant-steps ant-steps-vertical ant-steps-title-horizontal ant-steps-filled css-var-test-id acss-1tcbvg1"
|
||||
style="--steps-items-offset: 0;"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-finish"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
style="border-radius: 30%;"
|
||||
>
|
||||
<span
|
||||
aria-label="check"
|
||||
class="anticon anticon-check ant-steps-item-icon-finish"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="check"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Finished
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-process"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
style="font-style: italic;"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-process ant-steps-item-active"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
style="border-radius: 30%;"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
In Progress
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-wait"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
style="font-style: italic;"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-wait"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
style="border-radius: 30%;"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
3
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Waiting
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
style="font-style: italic;"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps ant-steps-vertical ant-steps-title-horizontal ant-steps-filled ant-steps-navigation css-var-test-id acss-1tcbvg1"
|
||||
style="--steps-items-offset: 0; border-color: rgb(24, 144, 255);"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-finish"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
>
|
||||
<span
|
||||
aria-label="check"
|
||||
class="anticon anticon-check ant-steps-item-icon-finish"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="check"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Finished
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-process"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-process ant-steps-item-active"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
In Progress
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-wait"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-wait"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
3
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Waiting
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/steps/demo/style-class.tsx extend context correctly 2`] = `[]`;
|
||||
|
||||
exports[`renders components/steps/demo/title-placement.tsx extend context correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
|
||||
@@ -5640,6 +5640,279 @@ Array [
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`renders components/steps/demo/style-class.tsx correctly 1`] = `
|
||||
<div
|
||||
class="ant-flex css-var-test-id ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
|
||||
>
|
||||
<div
|
||||
class="ant-steps ant-steps-horizontal ant-steps-title-horizontal ant-steps-filled css-var-test-id acss-1tcbvg1"
|
||||
style="--steps-items-offset:0"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-finish"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
style="border-radius:30%"
|
||||
>
|
||||
<span
|
||||
aria-label="check"
|
||||
class="anticon anticon-check ant-steps-item-icon-finish"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="check"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Finished
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-process"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
style="font-style:italic"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-process ant-steps-item-active"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
style="border-radius:30%"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
In Progress
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-wait"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
style="font-style:italic"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-wait"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
style="border-radius:30%"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
3
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Waiting
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
style="font-style:italic"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps ant-steps-horizontal ant-steps-title-horizontal ant-steps-filled ant-steps-navigation css-var-test-id acss-1tcbvg1"
|
||||
style="--steps-items-offset:0;border-color:#1890ff"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-finish"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
>
|
||||
<span
|
||||
aria-label="check"
|
||||
class="anticon anticon-check ant-steps-item-icon-finish"
|
||||
role="img"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
data-icon="check"
|
||||
fill="currentColor"
|
||||
focusable="false"
|
||||
height="1em"
|
||||
viewBox="64 64 896 896"
|
||||
width="1em"
|
||||
>
|
||||
<path
|
||||
d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Finished
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-process"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-process ant-steps-item-active"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
2
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
In Progress
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-rail ant-steps-item-rail-wait"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item ant-steps-item-wait"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-icon ant-wave-target"
|
||||
>
|
||||
<span
|
||||
class="ant-steps-item-icon-number"
|
||||
>
|
||||
3
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-section"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-header"
|
||||
>
|
||||
<div
|
||||
class="ant-steps-item-title"
|
||||
>
|
||||
Waiting
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-steps-item-content"
|
||||
>
|
||||
This is a content.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders components/steps/demo/title-placement.tsx correctly 1`] = `
|
||||
Array [
|
||||
<div
|
||||
|
||||
@@ -77,4 +77,34 @@ describe('Steps.Semantic', () => {
|
||||
expect(element).toHaveStyle(style);
|
||||
});
|
||||
});
|
||||
|
||||
it('semantic structure with function classNames and styles', () => {
|
||||
const classNamesFn: StepsProps['classNames'] = (info) => {
|
||||
if (info.props.type === 'navigation') {
|
||||
return { root: 'custom-navigation-root' };
|
||||
}
|
||||
return { root: 'custom-default-root' };
|
||||
};
|
||||
|
||||
const stylesFn: StepsProps['styles'] = (info) => {
|
||||
if (info.props.current === 1) {
|
||||
return { root: { backgroundColor: 'rgb(255, 0, 0)' } };
|
||||
}
|
||||
return { root: { backgroundColor: 'rgb(0, 255, 0)' } };
|
||||
};
|
||||
|
||||
const { container } = render(
|
||||
renderSteps({
|
||||
type: 'navigation',
|
||||
current: 1,
|
||||
classNames: classNamesFn,
|
||||
styles: stylesFn,
|
||||
}),
|
||||
);
|
||||
|
||||
const rootElement = container.querySelector<HTMLElement>('.custom-navigation-root');
|
||||
expect(rootElement).toBeTruthy();
|
||||
expect(rootElement).toHaveClass('ant-steps');
|
||||
expect(rootElement).toHaveStyle({ backgroundColor: 'rgb(255, 0, 0)' });
|
||||
});
|
||||
});
|
||||
|
||||
7
components/steps/demo/style-class.md
Normal file
7
components/steps/demo/style-class.md
Normal file
@@ -0,0 +1,7 @@
|
||||
## zh-CN
|
||||
|
||||
通过 `classNames` 和 `styles` 传入对象/函数可以自定义 Steps 的[语义化结构](#semantic-dom)样式。
|
||||
|
||||
## en-US
|
||||
|
||||
You can customize the [semantic dom](#semantic-dom) style of Steps by passing objects/functions through `classNames` and `styles`.
|
||||
60
components/steps/demo/style-class.tsx
Normal file
60
components/steps/demo/style-class.tsx
Normal file
@@ -0,0 +1,60 @@
|
||||
import React from 'react';
|
||||
import { Flex, Steps } from 'antd';
|
||||
import type { StepsProps } from 'antd';
|
||||
import { createStyles } from 'antd-style';
|
||||
|
||||
const useStyles = createStyles(({ token }) => ({
|
||||
root: {
|
||||
border: `2px dashed ${token.colorBorder}`,
|
||||
borderRadius: token.borderRadius,
|
||||
padding: token.padding,
|
||||
},
|
||||
}));
|
||||
|
||||
const stylesObject: StepsProps['styles'] = {
|
||||
itemIcon: { borderRadius: '30%' },
|
||||
itemContent: { fontStyle: 'italic' },
|
||||
};
|
||||
|
||||
const stylesFn: StepsProps['styles'] = (info) => {
|
||||
if (info.props.type === 'navigation') {
|
||||
return {
|
||||
root: { borderColor: '#1890ff' },
|
||||
};
|
||||
}
|
||||
return {};
|
||||
};
|
||||
|
||||
const App: React.FC = () => {
|
||||
const { styles } = useStyles();
|
||||
|
||||
const sharedProps: StepsProps = {
|
||||
items: [
|
||||
{
|
||||
title: 'Finished',
|
||||
content: 'This is a content.',
|
||||
},
|
||||
{
|
||||
title: 'In Progress',
|
||||
content: 'This is a content.',
|
||||
},
|
||||
{
|
||||
title: 'Waiting',
|
||||
content: 'This is a content.',
|
||||
},
|
||||
],
|
||||
current: 1,
|
||||
classNames: {
|
||||
root: styles.root,
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Flex vertical gap="middle">
|
||||
<Steps {...sharedProps} styles={stylesObject} />
|
||||
<Steps {...sharedProps} type="navigation" styles={stylesFn} />
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -30,6 +30,7 @@ When a given task is complicated or has a certain sequence in the series of subt
|
||||
<code src="./demo/steps-in-steps.tsx" debug>Steps inside Steps</code>
|
||||
<code src="./demo/inline.tsx">Inline Steps</code>
|
||||
<code src="./demo/inline-variant.tsx">Inline Style Combination</code>
|
||||
<code src="./demo/style-class.tsx" version="6.0.0">Custom semantic dom styling</code>
|
||||
<code src="./demo/variant-debug.tsx" debug>Variant Debug</code>
|
||||
<code src="./demo/component-token.tsx" debug>Component Token</code>
|
||||
|
||||
@@ -43,7 +44,7 @@ The whole of the step bar.
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| classNames | Semantic DOM class | [Record<SemanticDOM, string>](#semantic-dom) | - | |
|
||||
| classNames | Customize class for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
|
||||
| current | To set the current step, counting from 0. You can overwrite this state by using `status` of `Step` | number | 0 | |
|
||||
| ~~direction~~ | To specify the direction of the step bar, `horizontal` or `vertical` | string | `horizontal` | |
|
||||
| iconRender | Custom render icon, please use `items.icon` first | (oriNode, info: { index, active, item }) => ReactNode | - | |
|
||||
@@ -55,7 +56,7 @@ The whole of the step bar.
|
||||
| responsive | Change to vertical direction when screen width smaller than `532px` | boolean | true | |
|
||||
| size | To specify the size of the step bar, `default` and `small` are currently supported | string | `default` | |
|
||||
| status | To specify the status of current step, can be set to one of the following values: `wait` `process` `finish` `error` | string | `process` | |
|
||||
| styles | Semantic DOM style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | |
|
||||
| styles | Customize inline style for each semantic structure inside the component. Supports object or function. | Record<[SemanticDOM](#semantic-dom), CSSProperties> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), CSSProperties> | - | |
|
||||
| titlePlacement | Place title and content with `horizontal` or `vertical` direction | string | `horizontal` | |
|
||||
| type | Type of steps, can be set to one of the following values: `default` `dot` `inline` `navigation` `panel` | string | `default` | |
|
||||
| variant | Config style variant | `filled` \| `outlined` | `filled` | |
|
||||
|
||||
@@ -6,6 +6,7 @@ import type { StepsProps as RcStepsProps } from '@rc-component/steps/lib/Steps';
|
||||
import cls from 'classnames';
|
||||
|
||||
import useMergeSemantic from '../_util/hooks/useMergeSemantic';
|
||||
import type { SemanticClassNamesType, SemanticStylesType } from '../_util/hooks/useMergeSemantic';
|
||||
import type { GetProp } from '../_util/type';
|
||||
import { devUseWarning } from '../_util/warning';
|
||||
import Wave from '../_util/wave';
|
||||
@@ -26,6 +27,21 @@ export type IconRenderType = (
|
||||
info: Pick<RcIconRenderTypeInfo, 'index' | 'active' | 'item' | 'components'>,
|
||||
) => React.ReactNode;
|
||||
|
||||
export type StepsSemanticName =
|
||||
| 'root'
|
||||
| 'item'
|
||||
| 'itemWrapper'
|
||||
| 'itemIcon'
|
||||
| 'itemSection'
|
||||
| 'itemHeader'
|
||||
| 'itemTitle'
|
||||
| 'itemSubtitle'
|
||||
| 'itemContent'
|
||||
| 'itemRail';
|
||||
|
||||
export type StepsClassNamesType = SemanticClassNamesType<StepsProps, StepsSemanticName>;
|
||||
export type StepsStylesType = SemanticStylesType<StepsProps, StepsSemanticName>;
|
||||
|
||||
interface StepItem {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
@@ -55,14 +71,12 @@ export type ProgressDotRender = (
|
||||
},
|
||||
) => React.ReactNode;
|
||||
|
||||
export interface StepsProps {
|
||||
export interface BaseStepsProps {
|
||||
// Style
|
||||
prefixCls?: string;
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
rootClassName?: string;
|
||||
classNames?: RcStepsProps['classNames'];
|
||||
styles?: RcStepsProps['styles'];
|
||||
classNames?: StepsClassNamesType;
|
||||
styles?: StepsStylesType;
|
||||
variant?: 'filled' | 'outlined';
|
||||
size?: 'default' | 'small';
|
||||
|
||||
@@ -97,6 +111,11 @@ export interface StepsProps {
|
||||
onChange?: (current: number) => void;
|
||||
}
|
||||
|
||||
export interface StepsProps extends BaseStepsProps {
|
||||
prefixCls?: string;
|
||||
style?: React.CSSProperties;
|
||||
}
|
||||
|
||||
const waveEffectClassNames: StepsProps['classNames'] = {
|
||||
itemIcon: TARGET_CLS,
|
||||
};
|
||||
@@ -171,12 +190,6 @@ const Steps = (props: StepsProps) => {
|
||||
// ============================= Item =============================
|
||||
const mergedItems = React.useMemo(() => (items || []).filter(Boolean), [items]);
|
||||
|
||||
// ============================ Styles ============================
|
||||
const [mergedClassNames, mergedStyles] = useMergeSemantic(
|
||||
[waveEffectClassNames, contextClassNames, classNames],
|
||||
[contextStyles, styles],
|
||||
);
|
||||
|
||||
// ============================ Layout ============================
|
||||
const { xs } = useBreakpoint(responsive);
|
||||
|
||||
@@ -225,6 +238,29 @@ const Steps = (props: StepsProps) => {
|
||||
// ========================== Percentage ==========================
|
||||
const mergedPercent = isInline ? undefined : percent;
|
||||
|
||||
// =========== Merged Props for Semantic ===========
|
||||
const mergedProps: StepsProps = {
|
||||
...props,
|
||||
variant,
|
||||
size: mergedSize,
|
||||
type: mergedType,
|
||||
orientation: mergedOrientation,
|
||||
titlePlacement: mergedTitlePlacement,
|
||||
current,
|
||||
percent: mergedPercent,
|
||||
responsive,
|
||||
offset,
|
||||
};
|
||||
|
||||
// ============================ Styles ============================
|
||||
const [mergedClassNames, mergedStyles] = useMergeSemantic<
|
||||
StepsClassNamesType,
|
||||
StepsStylesType,
|
||||
StepsProps
|
||||
>([waveEffectClassNames, contextClassNames, classNames], [contextStyles, styles], undefined, {
|
||||
props: mergedProps,
|
||||
});
|
||||
|
||||
// ============================= Icon =============================
|
||||
const internalIconRender: RcStepsProps['iconRender'] = (_, info) => {
|
||||
const {
|
||||
|
||||
@@ -33,6 +33,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cFsBQLA0b7UAAA
|
||||
<code src="./demo/inline-variant.tsx">内联样式组合</code>
|
||||
<code src="./demo/variant-debug.tsx" debug>变体 Debug</code>
|
||||
<code src="./demo/component-token.tsx" debug>组件 Token</code>
|
||||
<code src="./demo/style-class.tsx" version="6.0.0">自定义各种语义结构的样式和类</code>
|
||||
|
||||
## API
|
||||
|
||||
@@ -44,7 +45,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cFsBQLA0b7UAAA
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| classNames | 语义化结构 className | [Record<SemanticDOM, string>](#semantic-dom) | - | |
|
||||
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<[SemanticDOM](#semantic-dom), string> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), string> | - | |
|
||||
| current | 指定当前步骤,从 0 开始记数。在子 Step 元素中,可以通过 `status` 属性覆盖状态 | number | 0 | |
|
||||
| ~~direction~~ | 指定步骤条方向。目前支持水平(`horizontal`)和竖直(`vertical`)两种方向 | string | `horizontal` | |
|
||||
| iconRender | 自定义渲染图标,请优先使用 `items.icon` | (oriNode, info: { index, active, item }) => ReactNode | - | |
|
||||
@@ -56,7 +57,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_7uahnr/afts/img/A*cFsBQLA0b7UAAA
|
||||
| responsive | 当屏幕宽度小于 `532px` 时自动变为垂直模式 | boolean | true | |
|
||||
| size | 指定大小,目前支持普通(`default`)和迷你(`small`) | string | `default` | |
|
||||
| status | 指定当前步骤的状态,可选 `wait` `process` `finish` `error` | string | `process` | |
|
||||
| styles | 语义化结构 style | [Record<SemanticDOM, CSSProperties>](#semantic-dom) | - | |
|
||||
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<[SemanticDOM](#semantic-dom), CSSProperties> \| (info: { props })=> Record<[SemanticDOM](#semantic-dom), CSSProperties> | - | |
|
||||
| titlePlacement | 指定标签放置位置,默认水平放图标右侧,可选 `vertical` 放图标下方 | string | `horizontal` | |
|
||||
| type | 步骤条类型,可选 `default` `dot` `inline` `navigation` `panel` | string | `default` | |
|
||||
| variant | 设置样式变体 | `filled` \| `outlined` | `filled` | |
|
||||
|
||||
Reference in New Issue
Block a user