View Source Headless (headless v0.1.1)

Summary

Functions

Replace def with defc to optimize component rendering by inlining static attributes.

Render input for a form field.

Render input errors

Avatar component

Clipboard component.

Popover component

Toggle (switch) component.

Functions

Link to this macro

defc(head, list)

View Source (macro)

Replace def with defc to optimize component rendering by inlining static attributes.

Compile-time validation

Using defc will also check in compile-time if the referenced attributes are correct.

This definition (using def) will compile and crash in runtime due to undefined wrong node reference.

  def toggle(assigns) do
    ~H"""
    <.use_toggle :let={t}>
      <.input {t.wrong}/>
    </.use_toggle>
    """
  end

  # => ** (KeyError) key :wrong not found in: (...)

When using defc it will not compile:

  defc toggle(assigns) do
    ~H"""
    <.use_toggle :let={t}>
      <.input {t.wrong}/>
    </.use_toggle>
    """
  end

  # => ** (Phoenix.LiveView.Tokenizer.ParseError): Unknwon node "wrong" for component use_toggle

Example

defmodule ExampleAvatarComponents do
  use Phoenix.Component
  import Headless

  attr :src, :any
  attr :alt, :any
  attr :initials, :string

  defc avatar(assigns) do
    ~H"""
    <.use_avatar :let={a} src={@src}>
      <div {a.root}>
        <img {a.image} alt={@alt} />
        <div {a.fallback}><%= @initials %></div>
      </div>
    </.use_avatar>
    """
  end
end

Render input for a form field.

Heavily based on default Phoenix generated CoreComponents

Text input

<.input field={@form[:name]} type="text" placeholder="Name"/>

Checkbox

<.input field={@form[:is_admin]} type="checkbox"/>

Attributes

  • field (Phoenix.HTML.FormField) - a form field struct retrieved from the form, for example: <code>@form[:email]</code>.
  • id (:string) - Defaults to nil.
  • name (:string)
  • value (:string)
  • type (:string) - Defaults to "text".
  • checked (:boolean) - the checked flag for checkbox inputs.
  • Global attributes are accepted. additional attributes to be passed to the input element.

Slots

  • inner_block

Render input errors

Heavily based on default Phoenix generated CoreComponents

Storybook: No errors

<.input_error field={@form[:name]} :let={{msg, _opts}}>
  <%= msg %>
</.input_error>

Storybook: With errors

<.input_error field={@form[:email]} :let={{msg, _opts}}>
  <%= msg %>
</.input_error>

Attributes

  • field (Phoenix.HTML.FormField) (required) - a form field struct retrieved from the form, for example: <code>@form[:email]</code>.

Slots

  • inner_block (required) - The default slot will be rendered with <code>{message, options}</code> tuple.

Avatar component

Elements

  • root - root element
  • image - <img> element
  • fallback - fallback element

Example

defmodule ExampleAvatarComponents do
  use Phoenix.Component
  import Headless

  attr :src, :any
  attr :alt, :any
  attr :initials, :string

  def avatar(assigns) do
    ~H"""
    <.use_avatar :let={a} src={@src}>
      <div {a.root}>
        <img {a.image} alt={@alt} />
        <div {a.fallback}><%= @initials %></div>
      </div>
    </.use_avatar>
    """
  end

  def example(assigns) do
    ~H"""
    <.avatar src="https://example.com/avatar.jpg" alt="Avatar" initials="JD" />
    <.avatar src={nil} alt="Avatar" initials="JD" />
    """
  end
end

Attributes

  • src (:string) - Image source URL.

Slots

  • inner_block (required)

Clipboard component.

Provides copy to clipboard functionality.

Elements

  • root - root element
  • trigger - element that triggers the clipboard action
  • content - element that contains the clipboard content

Example

defmodule ExampleClipboardComponents do
  use Phoenix.Component
  import Headless

  attr :text, :string

  def copy_to_clipboard(assigns) do
    ~H"""
    <.use_clipboard :let={c}>
      <div {c.root}>
        <input {c.content} type="text" value={@text} readonly/>
        <button {c.trigger}>Copy</button>
      </div>
    </.use_clipboard>
    """
  end

  def example(assigns) do
    ~H"""
    <.copy_to_clipboard text="Secrets"/>
    """
  end
end

Slots

  • inner_block (required)

Popover component

Elements

  • root - root element
  • trigger - element that triggers the popover
  • content - element that contains the popover content

Example

defmodule ExamplePopoverComponents do
  use Phoenix.Component
  import Headless

  slot :trigger
  slot :content

  def popover(assigns) do
    ~H"""
    <.use_popover :let={p}>
      <div {p.root}>
        <button {p.trigger}>
          <%= render_slot(@trigger) %>
        </button>
        <div {p.content}>
          <%= render_slot(@content) %>
        </div>
      </div>
    </.use_popover>
    """
  end

  def example(assigns) do
    ~H"""
    <.popover>
      <:trigger>
        Open
      </:trigger>
      <:content>
        Hidden message
      </:content>
    </.popover>
    """
  end
end

Slots

  • inner_block (required)

Toggle (switch) component.

Uses regular checkbox input under the hood.

Elements

  • input - the underlying checkbox element

Example

defmodule ExampleToggleComponents do
  use Phoenix.Component
  import Headless

  def toggle(assigns) do
    ~H"""
    <.use_toggle :let={t}>
      <.input {t.input} field={@field}/>
    </.use_toggle>
    """
  end

  def example(assigns) do
    ~H"""
    <.toggle field={@form[:is_admin]}/>
    """
  end
end

Slots

  • inner_block (required)