-
-
Notifications
You must be signed in to change notification settings - Fork 9.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4622 from nm123github/addon-cssresources
Resources addon to dynamically add/remove css
- Loading branch information
Showing
16 changed files
with
369 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
# Storybook Addon Cssresources | ||
|
||
Storybook Addon Cssresources to switch between css resources at runtime for your story [Storybook](https://storybook.js.org). | ||
|
||
[Framework Support](https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md) | ||
|
||
![Storybook Addon Cssresources Demo](docs/demo.gif) | ||
|
||
## Installation | ||
|
||
```sh | ||
yarn add -D @storybook/addon-cssresources | ||
``` | ||
|
||
## Configuration | ||
|
||
Then create a file called `addons.js` in your storybook config. | ||
|
||
Add following content to it: | ||
|
||
```js | ||
import '@storybook/addon-cssresources/register'; | ||
``` | ||
|
||
## Usage | ||
|
||
You need add the all the css resources at compile time using the `withCssResources` decorator. They can be added globally or per story. You can then choose which ones to load from the cssresources addon ui: | ||
|
||
```js | ||
// Import from @storybook/X where X is your framework | ||
import { configure, addDecorator, storiesOf } from '@storybook/react'; | ||
import { withCssResources } from '@storybook/addon-cssresources'; | ||
|
||
// global | ||
addDecorator( | ||
withCssResources({ | ||
cssresources: [{ | ||
name: `bluetheme`, | ||
code: `<style>body { background-color: lightblue; }</style>`, | ||
picked: false, | ||
}, | ||
], | ||
}) | ||
); | ||
|
||
// per story | ||
storiesOf('Addons|Cssresources', module) | ||
.addDecorator( | ||
withCssResources({ | ||
cssresources: [{ | ||
name: `fontawesome`, | ||
code: `<link rel="stylesheet" type="text/css" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"></link>`, | ||
picked: true, | ||
}, { | ||
name: `whitetheme`, | ||
code: `<style>.fa { color: #fff }</style>`, | ||
picked: true, | ||
}, | ||
], | ||
}) | ||
) | ||
.add('Camera Icon', () => <i className="fa fa-camera-retro"> Camera Icon</i>); | ||
``` |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"name": "@storybook/addon-cssresources", | ||
"version": "4.1.0-alpha.8", | ||
"description": "A storybook addon to switch between css resources at runtime for your story", | ||
"keywords": [ | ||
"addon", | ||
"cssresources", | ||
"react", | ||
"storybook" | ||
], | ||
"homepage": "https://storybook.js.org", | ||
"bugs": { | ||
"url": "https://github.com/storybooks/storybook/issues" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/storybooks/storybook.git" | ||
}, | ||
"license": "MIT", | ||
"author": "nm123github", | ||
"main": "dist/index.js", | ||
"jsnext:main": "src/index.js", | ||
"scripts": { | ||
"prepare": "node ../../scripts/prepare.js" | ||
}, | ||
"dependencies": { | ||
"@emotion/styled": "0.10.6", | ||
"@storybook/addons": "4.1.0-alpha.8", | ||
"@storybook/components": "4.1.0-alpha.8", | ||
"@storybook/core-events": "4.1.0-alpha.8", | ||
"global": "^4.3.2", | ||
"prop-types": "^15.6.2", | ||
"react-syntax-highlighter": "^10.0.0", | ||
"util-deprecate": "^1.0.2" | ||
}, | ||
"peerDependencies": { | ||
"react": "*" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
require('./dist/register.js'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
import { document, DOMParser } from 'global'; | ||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { monoFonts } from '@storybook/components'; | ||
import styled from '@emotion/styled'; | ||
|
||
import css from 'react-syntax-highlighter/dist/esm/languages/prism/css'; | ||
import { darcula } from 'react-syntax-highlighter/dist/esm/styles/prism'; | ||
import SyntaxHighlighter from 'react-syntax-highlighter/dist/esm/prism-light'; | ||
|
||
SyntaxHighlighter.registerLanguage('css', css); | ||
|
||
const storybookIframe = 'storybook-preview-iframe'; | ||
const addedElAttr = 'addedbycssresourcesaddon'; | ||
|
||
// Taken from StoryPanel.js | ||
const highlighterTheme = { | ||
...darcula, | ||
'pre[class*="language-"]': { | ||
...darcula['pre[class*="language-"]'], | ||
margin: 'auto', | ||
width: 'auto', | ||
height: 'auto', | ||
minHeight: '100%', | ||
overflow: 'hidden', | ||
boxSizing: 'border-box', | ||
display: 'flex', | ||
fontFamily: monoFonts.fontFamily, | ||
fontSize: 'inherit', | ||
}, | ||
'code[class*="language-"]': { | ||
...darcula['code[class*="language-"]'], | ||
margin: 0, | ||
fontFamily: 'inherit', | ||
}, | ||
}; | ||
|
||
const PanelWrapper = styled.div({ | ||
position: 'absolute', | ||
top: '10px', | ||
left: '10px', | ||
fontFamily: monoFonts.fontFamily, | ||
}); | ||
|
||
export default class CssResourcePanel extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { cssresources: `` }; | ||
this.onAddCssresources = this.onAddCssresources.bind(this); | ||
this.parser = new DOMParser(); | ||
} | ||
|
||
componentDidMount() { | ||
const { channel } = this.props; | ||
this.iframe = document.getElementById(storybookIframe); | ||
if (!this.iframe) { | ||
throw new Error('Cannot find Storybook iframe'); | ||
} | ||
channel.on('storybook/resources/add_cssresources', this.onAddCssresources); | ||
} | ||
|
||
componentWillUnmount() { | ||
const { channel } = this.props; | ||
channel.removeListener('storybook/resources/add_cssresources', this.onAddCssresources); | ||
} | ||
|
||
onAddCssresources(cssresources) { | ||
this.loadCssresources(cssresources.filter(res => res.picked)); | ||
this.setState(prevState => ({ ...prevState, cssresources })); | ||
} | ||
|
||
handleChange(i, { target }) { | ||
const { channel } = this.props; | ||
const { cssresources = [] } = this.state; | ||
cssresources[i].picked = target.checked; | ||
channel.emit('storybook/resources/add_cssresources', cssresources); | ||
} | ||
|
||
loadCssresources(cssresources) { | ||
// remove previously added elements! | ||
this.iframe.contentDocument.head.querySelectorAll(`[${addedElAttr}]`).forEach(eL => { | ||
if (eL) { | ||
eL.parentNode.removeChild(eL); | ||
} | ||
}); | ||
|
||
// add new elements! | ||
const str = cssresources.map(res => res.code).join(''); | ||
const parsedHtml = this.parser.parseFromString(str, 'text/html'); | ||
const elements = parsedHtml.querySelectorAll('head > *'); | ||
elements.forEach(eL => { | ||
// add addedElAttr to css elements | ||
eL.setAttribute(addedElAttr, ''); | ||
this.iframe.contentDocument.head.appendChild(eL); | ||
}); | ||
} | ||
|
||
render() { | ||
const { cssresources = [] } = this.state; | ||
const { active } = this.props; | ||
|
||
if (!active) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<PanelWrapper className="addon-cssresources-container"> | ||
{cssresources && | ||
cssresources.map(({ name, code, picked }, i) => ( | ||
<div key={name} style={{ padding: 10 }}> | ||
<div style={{ fontSize: '1.1em', marginBottom: 10 }}> | ||
<input | ||
id={`cssresource${i}`} | ||
style={{ fontSize: '1.5em' }} | ||
type="checkbox" | ||
checked={picked} | ||
onChange={this.handleChange.bind(this, i)} | ||
/> | ||
<label htmlFor={`cssresource${i}`}>#{name}</label> | ||
</div> | ||
<SyntaxHighlighter | ||
language="css" | ||
style={highlighterTheme} | ||
customStyle={{ opacity: picked ? 1 : 0.5 }} | ||
> | ||
{code} | ||
</SyntaxHighlighter> | ||
</div> | ||
))} | ||
</PanelWrapper> | ||
); | ||
} | ||
} | ||
|
||
CssResourcePanel.propTypes = { | ||
active: PropTypes.bool.isRequired, | ||
channel: PropTypes.shape({ | ||
on: PropTypes.func, | ||
emit: PropTypes.func, | ||
removeListener: PropTypes.func, | ||
}).isRequired, | ||
api: PropTypes.shape({ | ||
onStory: PropTypes.func, | ||
getQueryParam: PropTypes.func, | ||
setQueryParams: PropTypes.func, | ||
}).isRequired, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import addons, { makeDecorator } from '@storybook/addons'; | ||
|
||
export const withCssResources = makeDecorator({ | ||
name: 'withCssResources', | ||
parameterName: 'cssresources', | ||
skipIfNoParametersOrOptions: true, | ||
allowDeprecatedUsage: false, | ||
wrapper: (getStory, context, { options, parameters }) => { | ||
const channel = addons.getChannel(); | ||
const storyOptions = parameters || options; | ||
|
||
if (!Array.isArray(storyOptions) && !Array.isArray(storyOptions.cssresources)) { | ||
throw new Error('The `cssresources` parameter needs to be an Array'); | ||
} | ||
|
||
channel.emit( | ||
'storybook/resources/add_cssresources', | ||
Array.isArray(storyOptions) ? storyOptions : storyOptions.cssresources | ||
); | ||
|
||
return getStory(context); | ||
}, | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
import addons from '@storybook/addons'; | ||
import CssResourcePanel from './CssResourcePanel'; | ||
|
||
addons.register('storybook/cssresources', api => { | ||
const channel = addons.getChannel(); | ||
addons.addPanel('storybook/cssresources/panel', { | ||
title: 'Cssresources', | ||
// eslint-disable-next-line react/prop-types | ||
render: ({ active }) => <CssResourcePanel channel={channel} api={api} active={active} />, | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
18 changes: 18 additions & 0 deletions
18
examples/official-storybook/stories/__snapshots__/addon-cssresources.stories.storyshot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Storyshots Addons|Cssresources Camera Icon 1`] = ` | ||
<i | ||
class="fa fa-camera-retro" | ||
> | ||
Camera Icon | ||
</i> | ||
`; | ||
|
||
exports[`Storyshots Addons|Cssresources Primary Large Button 1`] = ` | ||
<button | ||
class="btn btn-lg btn-primary" | ||
type="button" | ||
> | ||
Primary Large Button | ||
</button> | ||
`; |
Oops, something went wrong.