Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resources addon to dynamically add/remove css #4622

Merged
merged 69 commits into from
Nov 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
570f509
rudimentary resources addon to dynamically add/remove css
Sep 10, 2018
80f9184
revert changes to official-storybook/config.js
Sep 10, 2018
130c8b4
no need for two react panels
Sep 13, 2018
83a32e1
Merge branch 'master' into pr/nm123github/4152
ndelangen Oct 14, 2018
6d26d8d
Merge branch 'master' into addon-resources
Hypnosphi Oct 15, 2018
eab5a76
add resources plugin complete refactor
Oct 20, 2018
593387b
Merge branch 'master' of github.com:storybooks/storybook into addon-r…
Oct 20, 2018
4e16dda
add styles to ace-editor, remove node_modules for resources addon
Oct 20, 2018
0cec564
Merge branch 'addon-resources' of github.com:nm123github/storybook in…
Oct 20, 2018
00fb800
revert unnecessary line break to manager-head
Oct 20, 2018
2e45657
add README, fix component style, add disable option
Oct 22, 2018
c594755
update ADDONS_SUPPORT.md for resources addon
Oct 22, 2018
e7d1199
Merge branch 'master' of github.com:storybooks/storybook into addon-r…
Oct 22, 2018
6182706
add resources __snapshots__
Oct 23, 2018
600795c
Merge branch 'master' of github.com:storybooks/storybook into addon-r…
Oct 23, 2018
eeb3d46
Merge branch 'master' of github.com:storybooks/storybook into addon-r…
Oct 24, 2018
7f3324b
regenerate yarn.lock
Oct 24, 2018
9d7cac9
regenerate yarn.lock from scratch
Oct 24, 2018
539d05b
Merge branch 'master' into addon-resources
nm123github Oct 24, 2018
6882660
revert yarn.lock update
Oct 24, 2018
ef239e3
Merge branch 'addon-resources' of github.com:nm123github/storybook in…
Oct 24, 2018
e5b6cdb
create cssresources addon
Oct 29, 2018
e2d6445
Merge branch 'master' of github.com:storybooks/storybook into addon-c…
Oct 29, 2018
194b943
updated readme's and storyshot
Oct 30, 2018
f3e9d14
update demo gif
Oct 30, 2018
bf20d28
update readme.md
Oct 30, 2018
c914942
update yarn.lock
Oct 30, 2018
38d7dd9
Merge branch 'master' into addon-cssresources
nm123github Oct 30, 2018
27f9411
update yarn.lock
Oct 30, 2018
4c9be49
update to latest yarn.lock
Oct 30, 2018
5c47716
Merge branch 'next' into addon-cssresources
nm123github Nov 6, 2018
47ad40b
Merge pull request #4750 from ximenean/patch-1
igor-dv Nov 8, 2018
d394d82
Merge pull request #4712 from mrmckeb/feature/custom-react-scripts
ndelangen Nov 9, 2018
aed1a75
Merge pull request #4706 from storybooks/node-path-loading-fix
igor-dv Nov 12, 2018
929fa6b
4.0.5 changelog
shilman Nov 13, 2018
4dcb56e
v4.0.5
shilman Nov 13, 2018
be05d10
4.0.6 changelog
shilman Nov 13, 2018
5d85f5d
v4.0.6
shilman Nov 13, 2018
ee0cf0f
Merge pull request #4767 from storybooks/angular-expose-force-rerender
shilman Nov 14, 2018
a2708a2
Upgrade pr-log to 3.0 + storybook-experimental
shilman Nov 15, 2018
e0933fa
Merge pull request #4785 from dandean/patch-2
igor-dv Nov 14, 2018
dfef65d
4.0.7 changelog
shilman Nov 15, 2018
5d5dfe0
v4.0.7
shilman Nov 15, 2018
58bdf3a
4.0.7 changelog
shilman Nov 15, 2018
4ac6d00
4.0.7 changelog feature area
shilman Nov 15, 2018
24cfb9b
Fixing webpack version
chris-lock Nov 15, 2018
4df0a49
Upgrade pr-log labels format
shilman Nov 16, 2018
2f4653b
Merge pull request #4795 from chris-lock/patch-1
shilman Nov 16, 2018
0778f28
Merge pull request #4804 from storybooks/patch-discord-link
ndelangen Nov 18, 2018
ccc37cd
Merge pull request #4779 from geoffreyd/patch-1
ndelangen Nov 17, 2018
643e1b6
Merge pull request #4800 from tobiasljungstrom/next
ndelangen Nov 17, 2018
be2037f
Merge pull request #4773 from storybooks/vue-knobs-optimize-on-force-…
igor-dv Nov 20, 2018
652b68f
4.0.8 changelog
shilman Nov 21, 2018
960bd59
v4.0.8
shilman Nov 21, 2018
3e3ff41
Docs: Fix internal deadlink
Nov 21, 2018
59e35b7
Merge pull request #4830 from aliceyoung9/patch-1
shilman Nov 22, 2018
fc01782
Merge branch 'master' of github.com:storybooks/storybook into addon-c…
Nov 22, 2018
8784677
Merge branch 'addon-cssresources' of github.com:nm123github/storybook…
Nov 23, 2018
0518549
Merge branch 'next' of github.com:storybooks/storybook into addon-css…
Nov 23, 2018
61d9492
revert unrelated changes
Nov 23, 2018
a2dac4d
revert change to guide-react doc
Nov 23, 2018
3edaffd
remove pretty-checkbox
Nov 24, 2018
4494373
circleci failing, update yarn.lock
Nov 24, 2018
d0f2cf4
revert yarn.lock
Nov 24, 2018
1a303b4
Merge remote-tracking branch 'upstream/next' into addon-cssresources
Nov 24, 2018
6d2369f
merge latest next, revert yarnlock
Nov 24, 2018
2691678
Fix yarn.lock
igor-dv Nov 24, 2018
8bab98d
update to 4.1.0-alpha.8
Nov 26, 2018
ca0f135
Fix snapshots
igor-dv Nov 26, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ADDONS_SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
|[links](addons/links) |+|+|+|+|+|+|+| |+|+|+|
|[notes](addons/notes) |+|+*|+|+|+|+|+| |+|+|+|
|[options](addons/options) |+|+|+|+|+|+|+| |+|+|+|
|[cssresources](addons/cssresources) |+| |+|+|+|+|+|+|+|+|+|
|[storyshots](addons/storyshots) |+|+|+|+| | |+| |+|+| |
|[storysource](addons/storysource) |+| |+|+|+|+|+|+|+|+|+|
|[viewport](addons/viewport) |+| |+|+|+|+|+|+|+|+|+|
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ For additional help, join us [in our Discord](https://discord.gg/sMFvFsG) or [Sl
| [actions](addons/actions/) | Log actions as users interact with components in the Storybook UI |
| [backgrounds](addons/backgrounds/) | Let users choose backgrounds in the Storybook UI |
| [centered](addons/centered/) | Center the alignment of your components within the Storybook UI |
| [cssresources](addons/cssresources/) | Dynamically add/remove css resources to the component iframe |
| [events](addons/events/) | Interactively fire events to components that respond to EventEmitter |
| [graphql](addons/graphql/) | Query a GraphQL server within Storybook stories |
| [google-analytics](addons/google-analytics) | Reports google analytics on stories |
Expand Down
63 changes: 63 additions & 0 deletions addons/cssresources/README.md
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>);
```
Binary file added addons/cssresources/docs/demo.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions addons/cssresources/package.json
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": "*"
}
}
1 change: 1 addition & 0 deletions addons/cssresources/register.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
require('./dist/register.js');
147 changes: 147 additions & 0 deletions addons/cssresources/src/CssResourcePanel.js
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,
};
23 changes: 23 additions & 0 deletions addons/cssresources/src/index.js
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);
},
});
12 changes: 12 additions & 0 deletions addons/cssresources/src/register.js
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} />,
});
});
1 change: 1 addition & 0 deletions addons/info/src/__snapshots__/index.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2880,6 +2880,7 @@ exports[`addon Info should render component description 1`] = `
</div>
</div>
<div
id="story-root"
style={Object {}}
>
<div>
Expand Down
1 change: 1 addition & 0 deletions examples/official-storybook/addons.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import '@storybook/addon-events/register';
import '@storybook/addon-notes/register';
import '@storybook/addon-options/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-cssresources/register';
import '@storybook/addon-backgrounds/register';
import '@storybook/addon-a11y/register';
import '@storybook/addon-jest/register';
Expand Down
15 changes: 15 additions & 0 deletions examples/official-storybook/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { configure, addDecorator } from '@storybook/react';
import { themes } from '@storybook/components';
import { withOptions } from '@storybook/addon-options';
import { configureViewport, INITIAL_VIEWPORTS } from '@storybook/addon-viewport';
import { withCssResources } from '@storybook/addon-cssresources';

import 'react-chromatic/storybook-addon';
import addHeadWarning from './head-warning';
Expand Down Expand Up @@ -34,6 +35,20 @@ addDecorator(
})
);

addDecorator(
withCssResources({
cssresources: [
{
name: `bluetheme`,
code: `<style>body {
background-color: lightblue;
}</style>`,
picked: false,
},
],
})
);

addDecorator(
(story, { kind }) =>
kind === 'Core|Errors' ? (
Expand Down
1 change: 1 addition & 0 deletions examples/official-storybook/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@storybook/addon-actions": "4.1.0-alpha.8",
"@storybook/addon-backgrounds": "4.1.0-alpha.8",
"@storybook/addon-centered": "4.1.0-alpha.8",
"@storybook/addon-cssresources": "4.1.0-alpha.8",
"@storybook/addon-events": "4.1.0-alpha.8",
"@storybook/addon-graphql": "4.1.0-alpha.8",
"@storybook/addon-info": "4.1.0-alpha.8",
Expand Down
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>
`;
Loading