Skip to content

Instantly share code, notes, and snippets.

@Stanko
Last active July 12, 2022 20:25
Show Gist options
  • Save Stanko/b900960b0f51ffc1c83d98a63444a6a9 to your computer and use it in GitHub Desktop.
Save Stanko/b900960b0f51ffc1c83d98a63444a6a9 to your computer and use it in GitHub Desktop.
React Storybook - React to HTML addon
const ADDON_NAME = 'react-to-html';
const PARAM_NAME = 'reactToHtml';
const PANEL_NAME = `${ADDON_NAME}/panel`;
const MARKUP_EVENT = `${ADDON_NAME}/markup`;
import ReactDOMServer from 'react-dom/server';
import addons, { makeDecorator } from '@storybook/addons';
import { html_beautify } from 'js-beautify';
import { ADDON_NAME, MARKUP_EVENT, PARAM_NAME } from './constants';
export default makeDecorator({
name: ADDON_NAME,
parameterName: PARAM_NAME,
skipIfNoParametersOrOptions: false,
wrapper: (getStory, context, { parameters }) => {
const channel = addons.getChannel();
const component = getStory();
// Use your preferred HTML beautifier
const markup = html_beautify(ReactDOMServer.renderToStaticMarkup(component), {
indent_size: 2,
inline: [],
});
channel.emit(MARKUP_EVENT, markup);
return getStory(context);
}
});
import React from 'react';
import addons from '@storybook/addons';
import SyntaxHighlighter from 'react-syntax-highlighter';
import { monokai } from 'react-syntax-highlighter/dist/esm/styles/hljs';
import { ADDON_NAME, PANEL_NAME, MARKUP_EVENT } from './constants';
class HTMLPanel extends React.Component {
constructor(props) {
super(props);
this.state = {
markup: ''
};
this.setMarkup = this.setMarkup.bind(this);
}
setMarkup(markup) {
this.setState({
markup
});
}
componentDidMount() {
const { api } = this.props;
api.on(MARKUP_EVENT, this.setMarkup);
}
componentWillUnmount() {
const { api } = this.props;
api.off(MARKUP_EVENT, this.setMarkup);
}
render() {
const { active } = this.props;
const { markup } = this.state;
// Use your preferred syntax highlighting library
return active ? (
<SyntaxHighlighter
language='html'
style={monokai}
customStyle={{
borderRadius: 0,
margin: 0,
padding: 16
}}
codeTagProps={{
style: {
fontFamily: '"DejaVu Sans Mono", Menlo, monospace',
fontSize: 16,
lineHeight: `20px`
}
}}
>
{markup}
</SyntaxHighlighter>
) : null;
}
}
addons.register(ADDON_NAME, api => {
addons.addPanel(PANEL_NAME, {
title: 'HTML',
render: ({ active, key }) => <HTMLPanel key={key} api={api} active={active} channel={api.getChannel()} />
});
});
@Stanko
Copy link
Author

Stanko commented Jul 31, 2019

Usage:

// Regular storybook setup
import { configure, addDecorator } from '@storybook/react';

// Register our addon and import decorator
import './addons/react-to-html/register';
import withHTML from './addons/react-to-html';

// Apply the decorator
addDecorator(withHTML);


// Rest of the regular setup
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment