View Source Surface (surface v0.11.0)
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
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
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 aroundPhoenix.LiveView
.Surface.MacroComponent
- A low-level component which is responsible for translating its own content at compile time.
example
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.
Link to this section Summary
Functions
Embeds an .sface
template as a function component.
Retrieve all component's config
Retrieve the component's config based on the key
Retrieve a component's config based on the key
Initialize surface state in the socket
Converts the given code into Surface's AST.
Translates Surface code into Phoenix templates.
Tests if a slot has been filled in.
Link to this section Functions
Embeds an .sface
template as a function component.
example
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.
Retrieve all component's config
Retrieve the component's config based on the key
Retrieve a component's config based on the key
Initialize surface state in the socket
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
Example
iex> [tag] =
...> quote_surface do
...> ~F"<div>content</div>"
...> end
...>
...> tag.children
[%Surface.AST.Literal{directives: [], value: "content"}]
Translates Surface code into Phoenix templates.
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
Examples
<div :if={slot_assigned?(:header)}>
<#slot {@header}/>
</div>