Storybook: https://storybook.js.org/
First, setup Storybook according to the official guide.
Note1: For coconut.vdom support, use the npm package "storybook-coconut" instead of "@storybook/react".
Note2: Multiple coconut target is not supported, that's limitation of storybook's architecture.
Then...
Main.hx
:
import coconut.storybook.*;
static function main() {
Storybook.add(new Button(), new AnotherComponent());
}
@:title('foo/Button') // optional title, default to full path of the class separated by a slash ("/")
class Button extends Component {
@:story // functions tagged with @:story will be added to storybook
function withText() '
<button>Hello Button</button>
';
@:story('with emoji') // custom story name
@:decorator(this.wrap) // decorators
@:parameter({note: 'component note'}, foo = 1) // parameters, expressions will be forwarded to `tink.Anon.merge`
function withEmoji() '
<button>
<span role="img" aria-label="so cool">
😀 😎 👍 💯
</span>
</button>
';
@:story
@:state(var value:Int = 0) // add state to a story
function withState() '
<button onclick=${value += 1}>
Clicked ${value} time(s)
</button>
';
function wrap(f:()->ReactSingleFragment) '
<div style=${{backgroundColor: 'black'}}>${f()}</div>
';
}
class AnotherComponent extends Component {
// ...
}
.storybook/main.js
:
module.exports = {
stories: ['path/to/haxe/generated/output.js'],
// ....
};
@:decorator
and @:parameter
are supported at both component (class) and story (method) level.
In all the metadata, you can use explicit this
to reference fields of the class instance. e.g.
@:title('Button: ' + this.variant)
class Button {
public final variant:String;
}