phenixdigital/phoenix_storybook

allow passing additional options to story

woylie opened this issue ยท 4 comments

I'm trying to solve the following problem.

I'm working on a headless UI component library called Doggo. It ships with a storybook folder that you can reference in your own application, so that you can see the components with your own styles. To set this up, you have to reference that library folder in your application's storybook module:

defmodule MyAppWeb.Storybook.Doggo do
  use PhoenixStorybook,
    otp_app: :my_app_web,
    content_path: Path.join(:code.priv_dir(:doggo), "/storybook"),
    title: "Doggo Storybook",
    css_path: "/assets/storybook.css",
    js_path: "/assets/storybook.js",
    sandbox_class: "my-app-web"
end

So far, so good.

Currently, the components come with a fixed set of modifier attributes. For example, it comes with fixed values for sizes (small, normal, medium, large), and with fixed values for variants (primary, secondary, info, warning, etc.). Since not everybody will need all of those modifiers for all components, and some may need additional modifiers, I want to make them configurable in a future version.

I don't know exactly how I want to implement that yet. Maybe by adding a __using__ macro that generates customized components. But the details aren't important here. What's important is that the stories should automatically render all configured variations. I didn't find a way to pass additional options from the storybook configuration to the stories to achieve that.

What I imagine is something like this.

  1. Allow to pass an additional option to use PhoenixStorybook with arbitrary options. If I'm going to implement this with __using__ as described, I would need to pass the module name, but it might just be any other options I need to customize a pre-configured story. This would be in the application that uses my library:
defmodule MyAppWeb.Storybook.Doggo do
  use PhoenixStorybook,
    otp_app: :my_app_web,
    content_path: Path.join(:code.priv_dir(:doggo), "/storybook"),
    extra_opts: [
      doggo_module: MyAppWeb.Doggo
    ]
end
  1. Pass those options to the story functions. At the minimum, to stick with my example, I'd need to be able to read the options in the function and variations functions. Something similar to this would be in the storybook stories defined in the library:
defmodule Storybook.Components.Button do
  use PhoenixStorybook.Story, :component

  def function(opts) do
    module = Keyword.fetch!(opts, :doggo_module)
    &module.button/1
  end

  def variations(opts) do
    module = Keyword.fetch!(opts, :doggo_module)

    [
      %VariationGroup{
        id: :sizes,
        variations:
          for size <- module.sizes() do
            %Variation{
              id: size,
              attributes: %{size: size},
              slots: ["click me"]
            }
          end
      }
    ]
  end
end

Whether I'm going to use __using__ and just pass a module, or whether I pass the options directly, I'll need some way to pass options from use PhoenixStorybook to the story functions.

Does this feature make sense to you?

Hey Mathias, Doggo looks very cool!

I think your idea is good, can you open a PR?
One constraint tho: current stories using function/0 and variations/0 should still work

hey ๐Ÿ‘‹
still something you'd like to do?
or should we close the issue?

Hey ๐Ÿ‘‹

yes, I still would like to add this. Just didn't get to it yet.

I decided to go a different route here and implemented a story generator instead, so I won't need the proposed changes any more.