VueやReactを使わないHTMLとscssだけでStorybookを使用するためにいろいろ調べました。
HTMLソース出力の部分がJSでベタに書くことになるので、コードがきたくなってしまうのが難点だけど、いったん運用がまわればそれなりに使いやすいと思いました。
導入手順
プロジェクトルートでセットアップ
npx -p @storybook/cli sb init --type html
セットアップが終わったら npm run storybook で立ち上げて確認。
(確認が終わったらCtrl+c でいったんとめて次)
scssが使えるようにする
まず、パッケージのインストール
npm i -D sass style-loader css-loader sass-loader@10.1.1 sass-resources-loader
※sass-loaderは最新版をいれたら動かず。
※LESSを使う場合は、sass-loader, sass-resources-loader がいらなくて、 less と less-loader がいる。
ただwebpack4 だと、less-loaderの最新のバージョンが動かず、less-loaderはバージョンを5に落として使用した。(どのバージョンならOKかまで詳細確認・テストはしてない)
.storybook\main.js にsass処理の記述を追加。
const path = require('path') // 1行めに追加
module.exports = {
// 元々あった設定は略、以下のwebpackFinal の設定を追加
webpackFinal: async(config, {configType}) => {
config.module.rules.push({
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
url: false // scss内のURLはコンパイルしない
}
},
'sass-loader',
{
loader: 'sass-resources-loader',
options: {
resources: ['./stories/assets/scss/_variables.scss'], // 全scss処理で必要となる変数設定のファイルを指定
}
}
],
})
return config
}
}
resetやbaseのスタイルは preview.js で読み込む
.storybook\preview.js
import '../stories/assets/scss/_reset.scss' // 1行目に追加
コンポーネント追加
最終的に別の環境にscssファイル群を持っていくことを考えて、以下のディレクトリ構造にした
├─.storybook │ ├ main.js │ └ preview.js ├─public │ └ 静的画像置き場 └─stories ├ assets │ └ scss │ └ 【コンポーネント名】.scss ├【コンポーネント名】.stories.js └【コンポーネント名】.html テンプレート置き場
追加カスタマイズ
ストーリーのレイアウト調整
paddingをなくす
// コンポーネントに対して
export default {
title: '【コンポーネント名】',
// 略
parameters:{
layout:'fullscreeen'
}
}
// Storyに対して
export const 【ストーリー名】= Template.bind({});
// 略
【ストーリー名】.parameters = {
layout:'fullscreeen'
}
デザイン切り替え処理追加
デザイン切り替え用のclassをbodyにつける処理。
.storybook\main.js に切り替えUIの追加と、bodyにclassを追加する
export const decorators = [
(story, context) => {
document.addEventListener("DOMContentLoaded", e => {
Array.prototype.forEach.call(document.body.classList, function (class_name, index) {
if(class_name.match(/^theme-/)){
document.body.classList.remove(class_name);
}
});
document.body.classList.add('theme-'+context.globals.Theme);
});
return story();
}
]
export const globalTypes = {
Theme: {
name: 'Theme',
description: 'Themeを設定します',
defaultValue: 'default',
toolbar: {
icon: 'circlehollow',
items: ['default', 'white', 'black']
}
}
}
HTMLソースコピペアドオン
パッケージのインストール
npm i -D @pickra/copy-code-block
HTMLのDOMを返す処理をしているソースで
// 最初で読み込んで
import copyCodeBlock from '@pickra/copy-code-block';
// 以下、 ret が戻すDOM だとして。
ret.appendChild(copyCodeBlock(【表示したいHTMLソーステキスト】,{
shouldReturnDomEl: true,
cssOverrides:`
.container {
margin-top:1rem;
padding:1rem;
}
.container code {
padding: 0;
white-space: break-spaces;
}
.container .copyButton{
text-align:center;
}
`
}));
※これ、実際に実装してみて、CreateXXXの中でこの処理をいれてしまうと、組み合わせたときによろしくないので、XX.stories.js の Template 処理の中でやったほうがよさそう。
JavaScriptの処理を差し込む
以下のファイルを追加し、JS処理をいれる。
.storybook\preview-head.html
var で宣言したら、グローバルとなるので、ストーリー内のイベントリスナー内から呼べる。
DOMが生成されてからでないと動かない処理は DOMContentLoaded を使えばよさそう。
document.addEventListener(“DOMContentLoaded”, e => { /* 処理 */});
静的ファイル置き場
package.json のscripts で指定
"scripts": {
"storybook": "start-storybook -p 6006 -s public",
"build-storybook": "build-storybook -s public"
},
public下のファイルがルートからのパスでとれるようになるので、
HTMLソースから、scssファイル内から “./画像名” で取得できる。
ローカルホストのドメイン名を変更
hostsファイルに以下の設定を追加。
#すでに127.0.0.1 の設定がある場合は半角スペースで ローカルのドメイン名を追加
127.0.0.1 local.hoge.com
package.json のscripts で -h オプション、 -p オプションをつける
"storybook": "start-storybook -h local.hoge.com -p 80 -s public",