# `Surface`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L1)

Surface is a component based library for **Phoenix LiveView**.

Built on top of the new `Phoenix.LiveComponent` API, Surface provides
a more declarative way to express and use components in Phoenix.

Full documentation and live examples can be found at [surface-ui.org](https://surface-ui.org)

This module defines the `~F` sigil that should be used to translate Surface
code into Phoenix templates.

In order to have `~F` available for any Phoenix view, add the following import to your web
file in `lib/my_app_web.ex`:

    # lib/my_app_web.ex

    ...

    def view do
      quote do
        ...
        import Surface
      end
    end

Additionally, use `Surface.init/1` in your mount function to initialize assigns used internally by surface:

    # A LiveView using surface templates

    defmodule PageLive do
      use Phoenix.LiveView
      import Surface

      def mount(_params, _session, socket) do
        socket = Surface.init(socket)
        ...
        {:ok, socket}
      end

      def render(assigns) do
        ~F"""
        ...
        """
      end
    end

    # A LiveComponent using surface templates

    defmodule NavComponent do
      use Phoenix.LiveComponent
      import Surface

      def mount(socket) do
        socket = Surface.init(socket)
        ...
        {:ok, socket}
      end

      def render(assigns) do
        ~F"""
        ...
        """
      end
    end

## Defining components

To create a component you need to define a module and `use` one of the available component types:

  * `Surface.Component` - A stateless component.
  * `Surface.LiveComponent` - A live stateful component.
  * `Surface.LiveView` - A wrapper component around `Phoenix.LiveView`.
  * `Surface.MacroComponent` - A low-level component which is responsible for translating its own content at compile time.

## Example

    # A functional stateless component

    defmodule Button do
      use Surface.Component

      prop click, :event
      prop kind, :string, default: "is-info"

      def render(assigns) do
        ~F"""
        <button class={"button", @kind} :on-click={@click}>
          <#slot/>
        </button>
        """
      end
    end

You can visit the documentation of each type of component for further explanation and examples.

# `embed_sface`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L144)
*macro* 

Embeds an `.sface` template as a function component.

## Example

    defmodule MyAppWeb.Layouts do
      use MyAppWeb, :html

      embed_sface "layouts/root.sface"
      embed_sface "layouts/app.sface"
    end

The code above generates two functions, `root` and `app`. You can use both
as regular function components or as layout templates.

# `event_to_opts`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L373)

# `get_components_config`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L249)

Retrieve all component's config

# `get_config`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L240)
*macro* 

Retrieve the component's config based on the `key`

# `get_config`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L234)

Retrieve a component's config based on the `key`

# `init`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L254)

Initialize surface state in the socket

# `quote_surface`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L203)
*macro* 

Converts the given code into Surface's AST.

The code must be passed with the `do` block using the `~F` sigil.

Optional `line`, `file` and `caller` metadata can be passed using `opts`.

## Example

    iex> [tag] =
    ...>   quote_surface do
    ...>     ~F"<div>content</div>"
    ...>   end
    ...>
    ...> tag.children
    [%Surface.AST.Literal{directives: [], value: "content"}]

# `sigil_F`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L106)
*macro* 

Translates Surface code into Phoenix templates.

# `slot_assigned?`
[🔗](https://github.com/surface-ui/surface/blob/v0.12.3/lib/surface.ex#L414)
*macro* 

Tests if a slot has been filled in.

Useful to avoid rendering unnecessary html tags that are used to wrap an optional slot
in combination with `:if` directive.

## Examples

  ```
  <div :if={slot_assigned?(:header)}>
    <#slot {@header}/>
  </div>
  ```

---

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