storytempl
About
This package runs a Storybook server for Templ components so that you can preview them during development. This is possible because the Storybook server renderer supports components that are rendered on a web server.
We take advantage of this by wrapping our components in HTTP handlers. Storybook provides parameters in the query string of the request and this package passes them into your component function.
You must have "pnpm" or "npm" on your system so that the appropriate Storybook packages can be installed when the server runs.
All of the Storybook arg types are supported.
Example Usage
Here we have a simple Templ component that can show a button in a few different styles.
package main
templ StyledButton(label string, className string) {
<style>
button.primary {
background-color: #007bff;
color: white;
}
button.secondary {
background-color: #6c757d;
color: white;
}
button.danger {
background-color: #dc3545;
color: white;
}
</style>
<div class="box">
<button class={ className }>{label}</button>
</div>
}
Next we create a function that sets up the argument types, default values, and stories for this component.
package main
import "gitlab.com/joeslazaro/storytempl"
func StyledButtonStories() *storytempl.Conf {
return storytempl.NewConf("Example/Button").
AddArgTypes(
storytempl.TextArgType("label"),
storytempl.SelectArgType("className", []string{"primary", "secondary", "danger"}),
).
AddDefaultArgs(
storytempl.TextArg("label", "Click Me"),
storytempl.SelectArg("className", "primary"),
).
AddStory("Default").
AddStory("Secondary",
storytempl.SelectArg("className", "secondary"),
).
AddStory("Danger",
storytempl.SelectArg("label", "Danger button"),
storytempl.SelectArg("className", "danger"),
)
}
Then we create a storybook config, add our components + stories, and start the server.
package main
import "gitlab.com/joeslazaro/storytempl"
func main() {
sbook := storytempl.New().AddComponent(StyledButton, StyledButtonStories())
if err := sbook.ListenAndServe(); err != nil {
panic(err)
}
}
Here is what it looks like when we connect to the server on localhost:60606.
Further examples
As mentioned before, all of the Storybook arg types are supported, and you can look at the _examples subdirectory to see an example of each one. You can also look at args.go, which is where they are defined.
You can also clone this repository and run task example
to run a server with all of the examples, assuming that you have the Taskfile and Templ executables in your path.
Organizing your story files
In my example I could have created the StyledButtonStories() in the same file as the templ component, however then I would have lost out on the assistance I get in VSCode from the Go language server. That's why, in my examples, I've chosen to have separate *_stories.go files for each of the examples.
If you're using VSCode, I recommend that you configure file nesting for "*.templ" files so that you can fold related files under it. I'm using $(capture)_templ.go, $(capture)_templ.txt, $(capture)_stories.go
Hot reloading?
I spent about five minutes testing this with templ's --watch and --proxy flags, but I wasn't able to get Storybook to see the changes. If anyone happens to figure it out, please let me know :)
History
The initial code was based on a more basic Storybook wrapper that I found in the Templ repository. I wanted to expand upon this work to supporting the full capabilities of Storybook argument types and allowing multiple stories per component