Skip to content

Commit cfec1d0

Browse files
committed
Add support for React elements for Steps intro
1 parent f577b30 commit cfec1d0

File tree

4 files changed

+37
-4
lines changed

4 files changed

+37
-4
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## Unreleased
2+
3+
* Add support for React elements to Steps's `intro` parameter.
4+
15
## 0.2.0
26

37
* 💥 `onBeforeChange` is no longer called with the `nextElement` parameter.

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ const steps = [
106106
| Name | Description | Type | Required |
107107
| --- | --- | :---: | :---: |
108108
| `element` | CSS selector to use for the step. | String | |
109-
| `intro` | The tooltip text. | String ||
109+
| `intro` | The tooltip content. | String \| React element ||
110110
| `position` | Position of the tooltip. | String | |
111111
| `tooltipClass` | CSS class of the tooltip. | String | |
112112
| `highlightClass` | CSS class of the helperLayer. | String | | |

src/components/Steps/index.js

+15-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import introJs from 'intro.js';
22
import PropTypes from 'prop-types';
3-
import { Component } from 'react';
3+
import { Component, isValidElement } from 'react';
4+
import { renderToStaticMarkup } from 'react-dom/server';
45

56
import * as introJsPropTypes from '../../helpers/proptypes';
67
import * as introJsDefaultProps from '../../helpers/defaultProps';
@@ -19,7 +20,7 @@ export default class Steps extends Component {
1920
steps: PropTypes.arrayOf(
2021
PropTypes.shape({
2122
element: PropTypes.string,
22-
intro: PropTypes.string.isRequired,
23+
intro: PropTypes.node.isRequired,
2324
position: introJsPropTypes.tooltipPosition,
2425
tooltipClass: PropTypes.string,
2526
highlightClass: PropTypes.string,
@@ -232,7 +233,18 @@ export default class Steps extends Component {
232233
configureIntroJs() {
233234
const { options, steps } = this.props;
234235

235-
this.introJs.setOptions({ ...options, steps });
236+
const sanitizedSteps = steps.map(step => {
237+
if (isValidElement(step.intro)) {
238+
return {
239+
...step,
240+
intro: renderToStaticMarkup(step.intro),
241+
};
242+
}
243+
244+
return step;
245+
});
246+
247+
this.introJs.setOptions({ ...options, steps: sanitizedSteps });
236248

237249
this.isConfigured = true;
238250
}

src/components/Steps/index.test.js

+17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import React from 'react';
2+
import ReactDOMServer from 'react-dom/server';
23
import renderer from 'react-test-renderer';
34
import { shallow } from 'enzyme';
45

@@ -24,6 +25,22 @@ describe('Steps', () => {
2425
expect(tree).toMatchSnapshot();
2526
});
2627

28+
test('should render a React element using renderToStaticMarkup', () => {
29+
const Element = () => <div>react test</div>;
30+
31+
const spy = jest.spyOn(ReactDOMServer, 'renderToStaticMarkup');
32+
33+
const wrapper = shallow(
34+
<Steps initialStep={0} steps={[{ element: '.test', intro: <Element /> }]} onExit={() => {}} />,
35+
{
36+
lifecycleExperimental: true,
37+
}
38+
);
39+
wrapper.setProps({ enabled: true });
40+
41+
expect(spy).toHaveBeenCalledTimes(1);
42+
});
43+
2744
test('should not call the onStart callback at mount time if not enabled', () => {
2845
const onStart = jest.fn();
2946

0 commit comments

Comments
 (0)