Shorthand notation for assigning slots.
<Card>
<:header>
...
</:header>
<:footer>
...
</:footer>
</Card>
instead of:
<Card>
<template slot="header">
...
</template>
<template slot="footer">
...
</template>
</Card>
- deprecate
<template>
usage, then remove it in next minor version - fixable with converter
Approved ✅
Introduce the ability to define a prop
that can be passed without the attibute name.
By defining a prop
as root: true
, for instance:
prop condition, :boolean, root: true
you can use:
<MyComp {@var > 10}>
...
</MyComp>
instead of:
<MyComp condition={@var > 10}>
...
</MyComp>
Note: Only one prop
can be defined as root.
- no breaking change as it's an addition
Approved ✅
Allow injecting the new "function component" that will be introduced in Phoenix.
Local/imported functions:
<.my_func>
...
</.my_func>
Remote functions:
<Components.SomeComponent.some_func>
...
</Components.SomeComponent.some_func>
- fixable with converter
- although we'll accept this syntax, we'll keep the abstraction of
Surface.Component
as a wrapper for stateless components using the newcomponent/3
function. This means there will be no change in the syntax if the user wants to keep the implementation in a module. However, there will be nomount
callback for now (maybe we can keepupdate
), so we need to check which stateless components depend on those callbacks and adapt them.
Approved ✅
Make the syntax less verbose and allow some minimal compatibility with the new LV template language.
<div class={@class}>
- breaking change
- fixable with converter
Approved ✅
Support if...elseif...else
logic as built-in constructs instead of components.
{#if @var > 10}
...
{#elseif @var < 10}
...
{#else}
...
{/if}
- deprecate
<If>
usage, then remove it in next minor version - fixable with converter
Approved ✅
Support case
logic as built-in constructs.
{#case @var}
{#match [first | _ ]}
...
{#match _}
...
{/case}
- no breaking change as it's an addition
Approved ✅
Shorthand notation for passing dynamic attributes. It replaces both, :attrs
and :props
.
<div class="panel" {...@attrs}>
Note 1: The new Liveview template will introduce a new way to pass dynamic attributes. Probably:
<div class="panel" {@attrs}>If we use the same approach, it will conflict with the proposed "root property", which invalidate the way we can build our built-in constructs. So I think it's better to have a React-like approach using
{...attrs}
instead.
- deprecate
:attrs
and:props
, then remove them in next minor version - fixable with converter
Approved ✅
The new syntax will accept only literal strings or expressions as attribute values. There will be no auto-conversion of literals nor evaluation of embedded expressions like id="id_{{@id}}"
.
See discussion surface-ui/surface#319 (comment) for details.
Basically, the same but more strict when accepting literals.
Boolean: <div selected={true}>
instead of <div selected=true>
Integers: <div tabindex={1}>
instead of <div tabindex=1>
Atoms: <div some_atom_attr={:an_atom}>
instead of <div some_atom_attr="an_atom">
Embedded expressions: id={"id_#{@id}"}
instead of id="id_{{@id}}"
- breaking change (deprecation possible for some cases)
- fixable with converter (except the atom case)
Approved ✅
Add a prefix s-*
for directives to avoid conflicts with frontend libs like Alpine.js. The :
notation will be kept as a shorthand for s-
. The user can then choose which notation to use depending on the frontend.
<div s-on-click="click">
shorthand (the current notation)
<div :on-click="click">
- no breaking change as it's an addition
Approved ✅
Allow =
and ~
as built-in expression markers. Other markers can be customized by the user, namely $
and %
. We may include other symbols in the future as long as they are not a valid tokens at the begining of an elixir expression.
The =
marker would allow users to write:
<button
{=@type}
{=@aria_label}
{=@disabled}
{=@value}
...
</button>
as a shorthand for:
<button
type={@type}
aria-label={@aria_label}
disabled={@disabled}
value={@value}
...
</button>
This is similar to Svelte's <button {@type}>
syntax, but with explicit =
marker. We need to use a marker, othewise, it would conflic with the "root property" feature.
The ~
marker would allow users to write:
<h2>{~ "Welcome!"}</h2>
as a shorthand for:
<h2>{gettext "Welcome!"}</h2>
If we allow custom implemenations for tagged expressions, the user would be able to map those markers to specific formatter functions. Examples:
The $
marker would allow users to write:
<h2>{$ @total}</h2>
as a shorthand for:
<h2>{format_currency(@total)}</h2>
The %
marker would allow users to write:
<h2>{% @updated_at}</h2>
as a shorthand for:
<h2>{format_date(@updated_at)}</h2>
Allowing users to map markers to their own functions brings the same tradeoffs we have when overriding standard operators in general like +
or *
. It can be practical depending or the use case but can lead to more obscure code if the user maps those markers to something that might not be expected by other developers not familiar with the codebase.
- no breaking change as it's an addition
- require adjustments for the syntax highlighters
Waiting for approval.