# `PhoenixStorybook.Story`
[🔗](https://github.com/phenixdigital/phoenix_storybook/blob/v1.2.0/lib/phoenix_storybook/stories/story.ex#L1)

A story designates any kind of content in your storybook. For now only following kinds of stories
are supported `:component`, `:live_component`, and `:page`.

In order to populate your storybook, just create _story_ scripts under your content path, and
implement their required behaviour.

Stories must be created as `story.exs` files.

In dev environment, stories are lazily compiled when reached from the UI.

## Usage

### Component

Implement your component as such.
Confer to:
- `PhoenixStorybook.Variation` documentation for variations.
- `PhoenixStorybook.Attr` documentation for attributes.

```elixir
# storybook/my_component.exs
defmodule MyAppWeb.Storybook.MyComponent do
  use PhoenixStorybook.Story, :component

  # required
  def function, do: &MyAppWeb.MyComponent.my_component/1

  # By default (`:module` value), it will render the full component's mode source code.
  # - when set on `:function`, it will render only function's source code
  # - when set on `false`, the source tab will be unavailable
  def render_source, do: :function

  def attributes, do: []
  def slots, do: []
  def variations, do: []
end
```

### Live Component

Very similar to components, except that you need to define a `component/0` function instead of
`function/0`.

```elixir
# storybook/my_live_component.exs
defmodule MyAppWeb.Storybook.MyLiveComponent do
  use PhoenixStorybook.Story, :live_component

  # required
  def component, do: MyAppWeb.MyLiveComponent

  def attributes, do: []
  def slots, do: []
  def variations, do: []
end
```

You can also define an optional `handle_info/2` in your live component story. It will be called
by the storybook LiveView when your component sends messages to its parent (useful for `send_update/2`).

ℹ️ Learn more on components in the [components guide](guides/components.md).

### Page

A page is a fairly simple story that can be used to write whatever content you want. We use it to
provide some UI guidelines.

You should implement the render function and an optional navigation function, if you want a tab
based sub-navigation. Current tab is passed as `:tab` in `render/1` assigns.

```elixir
# storybook/my_page.exs
defmodule MyAppWeb.Storybook.MyPage do
  use PhoenixStorybook.Story, :page

  def doc, do: "My page description"

  def navigation do
    [
      {:tab_one, "Tab One", {:fa, "book"}},
      {:tab_two, "Tab Two", {:fa, "cake", :solid}}
    ]
  end

  def render(assigns) do
    ~H"<div>Your HEEX template</div>"
  end
end
```

### Example

An example is a real-world UI showcasing how your components can be used and mixed in complex UI
interfaces.

Examples are rendered as a child LiveView, so you can implement `mount/3`, `render/1` or any
`handle_event/3` callback. Unfortunately `handle_params/3` cannot be defined in a child LiveView.

Examples render inline by default. If you need full document isolation, implement `container/0`
and return `:iframe` or `{:iframe, opts}` to render the example in a dedicated iframe.

By default, your example story's source code will be shown in a dedicated tab. But you can show
additional files source code by implementing the `extra_sources/0` function which should return a
list of relative paths to your example related files.

```elixir
# storybook/my_example.story.exs
defmodule MyAppWeb.Storybook.MyPage do
  use PhoenixStorybook.Story, :example

  def doc, do: "My page description"

  def container, do: :iframe

  def extra_sources do
    [
      "./template.html.heex",
      "./my_page_html.ex"
    ]
  end

  def mount(_, _, socket), do: {:ok, socket}

  def render(assigns) do
    ~H"<div>Your HEEX template</div>"
  end
end
```

# `__using__`
*macro* 

Convenience helper for using the functions above.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
