@onewelcome/storybook-addon-basestyling
v2.2.0
Published
To have easy configuration of our CSS variables.
Downloads
32
Maintainers
Readme
Storybook BaseStyling addon
This addon is written so that end-users can easily change global color variables without having to do into the browser' devtools.
Technical explanation
The addon works by exporting the global decorator withBaseStyling
inside of src/preset/preview.ts
. This decorator export will be plugged into the react-lib-component
Storybook instance by adding it to the addons
array in main.js
file inside of /.storybook/main.js
.
The withBaseStyling
decorator creates a global variable called baseStyling
. On initial render of the withBaseStyling
decorator, the .basestyling-wrapper
element with all the style
variables hasn't loaded yet, so we use a setTimeout
, which waits 1ms
, to make sure everything is loaded.
After everything is loaded we parse all the style
variables that are added to the .basestyling-wrapper
element.
This means, that this package WILL BREAK when we add anything else to the style
attribute of the .basestyling-wrapper
element.
Currently, there's no other way to easily grab all the CSS variables dynamically. We also cannot import the object from our BaseStyling
component, because Storybook will complain that you're trying to access something outside of this addon. We would have to duplicate all the properties and keep updating this package whenever we add a new variable. I wanted it to be dynamic, so for now we're parsing the .basestyling-wrapper
element's style
attribute within the Story
's iframe
.
After we've parsed all the CSS properties into an object, we update the baseStyling
global (which works just as state). This is when the addon Panel
will get filled. If you go into addon/src/Panel.tsx
, you'll see we import the same useGlobals
hook.
No, importing it in PanelContent
does not work, because it's not a direct child that gets rendered inside manager.ts
perhaps this will change in future versions of Storybook.
We therefor let PanelContent.tsx
accept two props:
- All the actual
baseStyling
props - An
updateProperties
function
Inside the PanelContent.tsx
file we simply have a React state variable that keeps track of all of our table rows. Whenever a property value changes, we execute the renderContent
function to update all of our table rows. We only trigger a complete update of our sessionStorage
variable if an input
fires the onBlur
event (for performance' sake).
As soon as an onBlur
event gets fired, we fire the propertyChanged
function that was passed as a prop to PanelContent.tsx
. If you go back to Panel.tsx
you see it actually updates the baseStyling
global variable.
Going back to withBaseStyling.ts
you'll see we have a useEffect
which listens to any changes made to the baseStyling
global. If anything changes, we fire the updateCSSPropertiesOnHTMLElement
function, and pass this baseStyling
global.
We convert the object back to a valid style
tag value, JSON.stringify
it, and set it as sessionStorage
. After that, we fire a custom event called updated-styling
. The file that actually listens to this event is /.storybook/preview.js
.
There's a Preview
component which has a properties
state. This state variable gets used to force the inner Story
to rerender whenever you change anything inside the BaseStyling
addon. This is needed, because otherwise the story will always be one step behind in rendering the correct values passed to the BaseStyling
addon.
For example the initial value is yellow
. If you change the value to red
, the sessionStorage
variable will be updated, but the actual story still rendered with the previous sessionStorage
. So imagine you change the red
to blue
now, it'll render with the red
variable intact. This makes sure the Story and BaseStyling
addon are synced up properly.
Development
Development for this plugin is quite easy. Either use yarn
or npm
for the following commands.
Installation
Go into the addon
folder and type:
npm install
Active development
For a storybook instance execute:
npm run start
To build and watch the addon execute:
npm run build:watch
This will rebuild the entire addon whenever you make changes to any files in the src
directory. You will have to completely refresh our the storybook page. There is no hot reloading.
Build for production
npm run build