Properties
You can pass information from a parent component down to a child using properties.
In order to declare a property, you must use the prop
macro:
prop name, type, options
Where:
-
name
- is the name of the property. -
type
- an atom defining the type of the property. See all available types in section "Components Basics > Types available". -
options
- a keyword list of options for additional customization.
Supported options
-
required
- declares the property as required. Default isfalse
. -
default
- defines a default value for an optional property. -
values
- the list or range of values suggested for the property. -
values!
- the list or range of all possible values for the property. Unlikevalues
, this option enforces validation of the default value against the given list. -
from_context
- if the prop is not passed or the value isnil
, sets the value to the one stored in the context under the given key. -
accumulate
- instructs Surface to group all different values provided for that property into a single list. Default isfalse
, i.e. only the last value is passed. -
css_variant
- Tailwind only. If set totrue
, instructs the Surface compiler to generate CSS variants based on the related assign's type and value. Default isfalse
. For further information, see "Generating CSS variants ".
CSS class property
In order to avoid working with string concatenation, which is annoying and error-prone,
Surface allows passing keyword lists directly to the class
property and improves
developer experience by automatically handling conditional classes.
Let's see how it works.
Imagine you want to create a button component that sets CSS classes based on the following rules:
-
button
- always set -
is-info
- always set -
is-loading
- set if@loading
is truthy -
is-rounded
- set if@rounded
is truthy
We can define our component like this:
defmodule MyButton do
use Surface.Component
prop loading, :boolean
prop rounded, :boolean
slot default
def render(assigns) do
~F"""
<button class={"button", "is-info", "is-loading": @loading, "is-rounded": @rounded}>
<#slot />
</button>
"""
end
end
Let's try it out.
Note: For regular HTML tags like
<button>
, theclass
attribute will be handled automatically as expected. For custom components, you need to instruct Surface to do so by setting the type of the property as:css_class
.
Event property
In order to declare an event property, you must use the prop
macro and
define the type as :event
:
prop name, :event, options
Where:
-
name
- is the name of the event. -
options
- a keyword list of options for additional customization.
Supported options
-
required
- declares the event as required. Default isfalse
. -
default
- defines a default value for an optional event.
Example:
defmodule MyButton do
use Surface.Component
@doc "Triggers on click"
prop click, :event
slot default
def render(assigns) do
~F"""
<button class="button" :on-click={@click}>
<#slot />
</button>
"""
end
end