The base every Pine UI component is built on.
defmodule MyComponent do
use PineUiPhoenix.Component
attr :class, :string, default: nil
attr :rest, :global
slot :inner_block, required: true
def thing(assigns) do
~H|<div class={cx("p-4 rounded-md", @class)} {@rest}><%= render_slot(@inner_block) %></div>|
end
endWhy this exists rather than plain use Phoenix.Component
LiveView's default global-attribute prefixes are exactly phx-, aria- and data-
(see Phoenix.Component's :global_prefixes option). x- is not among them, so
writing <.dropdown x-on:keydown.escape="open = false"> produces
warning: undefined attribute "x-on:click" for component ...This macro registers x- so that call sites inside Pine UI's own modules compile
cleanly — one component invoking another, as pagination/1 does with its internal
page_link/1.
Global prefixes are resolved against the caller
Phoenix.Component.Declarative's __global__?/3 is passed the module containing the call
site, not the module defining the component. Registering x- here therefore does
nothing for application code that calls Pine UI components.
use PineUiPhoenix handles that for consuming applications by defining __global__?/1
on the caller. See PineUiPhoenix.__using__/1.
Note the attribute is still forwarded to @rest either way — the consequence of a
missing registration is a compiler warning, not a dropped attribute. But a library that
makes every consumer's build noisy is not one people keep.
Alpine shorthands are not supported
Alpine accepts @click as shorthand for x-on:click and :class for x-bind:class.
Neither works in HEEx: @ introduces an assign and : introduces a special attribute like
:if, so they cannot be registered as global prefixes. Always write the long form:
x-on:click="open = !open" # not @click
x-bind:class="open && 'rotate-180'" # not :classDeclared attributes shadow global ones
class, id, title, type, role, style and placeholder are all global attributes.
Because an explicitly declared attr takes precedence over :rest, declaring
attr :title, :string for a component's heading text means the caller can no longer set the
HTML title tooltip attribute directly. Pass it through :rest instead:
<.card title="Billing" rest={%{title: "Tooltip text"}} />