Skip to content

Commit 877f1cb

Browse files
author
James Baxley
committed
initial commit
0 parents  commit 877f1cb

File tree

9 files changed

+467
-0
lines changed

9 files changed

+467
-0
lines changed

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.DS_Store
2+
.merlin
3+
.bsb.lock
4+
npm-debug.log
5+
/node_modules/
6+
src/*.js
7+
lib
8+

README.md

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
# bs-storybook
2+
3+
BuckleScript bindings for Storybook.js! The goal of this project is to provide bindings for the main Storybook API, as well as the official add-ons. Currently it supports:
4+
* [actions](https://github.com/storybooks/storybook/tree/master/addons/actions)
5+
* [knobs](https://github.com/storybooks/storybook/tree/master/addons/knobs).
6+
7+
## Getting Started
8+
9+
After installing this package, add it to your `bsconfig.json` as a dependency.
10+
11+
Get Storybook up and running according to their docs. This library does not attempt to provide a way to configure storybook in Reason - just use the standard JS configs.
12+
13+
In your `/.storybook/config.js`, import your stories from wherever your compiled Reason modules end up. For example, if you're writing your stories inside a `__stories__` directory, and `bsb` is configured for a standard build, you might do something like:
14+
15+
```javascript
16+
const req = require.context('../lib/js', true, /\__stories__\/.*.js$/)
17+
configure(() => {
18+
req.keys().forEach(module => {
19+
req(module).default();
20+
})
21+
}, module)
22+
```
23+
24+
Note that in the above example, we're assuming the convention of each module containing a function as the `default` export. We'll account for that when writing our stories in the next section.
25+
26+
## Writing a story
27+
28+
Here's a basic story in its entirety:
29+
30+
```reason
31+
open BsStorybook.Main;
32+
33+
let _module = [%bs.raw "module"];
34+
35+
let default = () => {
36+
let myStory =
37+
createStory(~title="My First Reason Story", ~decorators=[], ~_module, ());
38+
myStory.add(
39+
"first chapter",
40+
() => <span> (ReasonReact.stringToElement("Hello bs-storybook!")) </span>
41+
)
42+
};
43+
```
44+
45+
Storybook uses a reference to the `module` global provided by webpack to facilitate hot-reloading. We'll access that via the `[%bs.raw]` decorator. We're also wrapping the story definition in a `default` function to make it work with the way we've configured storybook. There's nothing enforcing this convention - you can choose to use another export name if you'd like.
46+
47+
We create a story using `createStory`, and pass it the story's title, any decorators we'd like to use (in the above example, we're not using any), and the module reference we created.
48+
49+
From there, we can add to the story using essentially the same API as the JS version of storybook: call `add()` and pass a string + a function that returns a React element.
50+
51+
## The Actions Addon
52+
53+
The action addon's API is essentially unchanged from its JS implementation:
54+
55+
```reason
56+
let clickAction = Action.action("I Clicked The Button!");
57+
```
58+
59+
## The Knobs Addon
60+
61+
To use knobs, be sure to add the decorator to your story definition:
62+
63+
```reason
64+
let knobsStory =
65+
createStory(~title="Hey look, knobs!", ~decorators=[Knobs.withKnobs], ~_module, ());
66+
```
67+
68+
Each knob type is invoked using a function with labeled arguments, and each requires passing `unit` as the final argument. They all share a `~label` argument, and a `~defaultValue` argument (where appropriate);
69+
70+
### Text
71+
72+
```reason
73+
let myText = Knobs.text(~label="What should it say?", ~defaultValue="Sup?", ());
74+
```
75+
76+
### Boolean
77+
78+
```reason
79+
let myBoolean = Knobs.boolean(~label="Should Show?", ~defaultValue=true, ());
80+
```
81+
82+
Note: The boolean type will call the underlying JS knob with a defaultValue of `false` if one is not provided.
83+
84+
### Color
85+
86+
```reason
87+
let myColor = Knobs.color(~label="Color", ~defaultValue="#333" ());
88+
```
89+
90+
### Number
91+
92+
The number type works with floats. If no `defaultValue` is provided, it will pass `0`. It also takes an optional `rangeConfig` record, which allows for specifying a `min`, `max`, and `step` so that the knob is displayed as a range slider.
93+
94+
```reason
95+
let num1 = Knobs.number(~label="Number 1", ());
96+
let num2 =
97+
Knobs.number(
98+
~label="Number 2",
99+
~rangeConfiguration={min: 0., max: 10., step: 1.},
100+
()
101+
);
102+
```
103+
104+
### Select
105+
106+
To use the select knob, first define a record type that contains the shape of the options, then the actual options as a type of `selectConfig`, passing your shape as the constructor type:
107+
108+
```reason
109+
type selectOptions = {
110+
one: string,
111+
two: string
112+
};
113+
114+
let options : Knobs.selectConfig(selectOptions) = {
115+
one: "Hello",
116+
two: "Hi"
117+
};
118+
```
119+
120+
Then define the select knob like so:
121+
122+
```reason
123+
let greeting = Knobs.select(~label="Greeting", ~options, ~defaultValue=options.one, ());
124+
```
125+
126+
### Button
127+
128+
```reason
129+
Knobs.button(
130+
~label="Knob Button",
131+
~handler=Action.action("Clicked the knob button"),
132+
()
133+
)
134+
```
135+
136+
### Object
137+
138+
Not yet implemented.
139+
140+
### Array
141+
142+
Not yet implemented.

bsconfig.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "bs-storybook",
3+
"bsc-flags": ["-bs-super-errors"],
4+
"version": "0.1.0",
5+
"sources": ["src"],
6+
"bs-dependencies": ["reason-react"],
7+
"namespace": true,
8+
"refmt": 3
9+
}

package-lock.json

Lines changed: 158 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"name": "bs-storybook",
3+
"version": "0.1.0",
4+
"scripts": {
5+
"build": "bsb -make-world",
6+
"test": "echo XXX TODO",
7+
"dev": "bsb -make-world -w",
8+
"clean": "bsb -clean-world"
9+
},
10+
"keywords": ["BuckleScript"],
11+
"author": "",
12+
"license": "MIT",
13+
"devDependencies": {
14+
"bs-platform": "^2.1.0",
15+
"prettier": "^1.10.2"
16+
},
17+
"dependencies": {
18+
"reason-react": "^0.3.0"
19+
},
20+
"peerDependencies": {
21+
"@storybook/addon-actions": "^3.2.17",
22+
"@storybook/addon-knobs": "^3.3.3",
23+
"@storybook/react": "^3.2.17"
24+
}
25+
}

src/action.re

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
type actionHandler('a) = 'a => unit;
2+
3+
[@bs.val] [@bs.module "@storybook/addon-actions"]
4+
external action : string => actionHandler('a) = "";

0 commit comments

Comments
 (0)