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; }