Lustre v5.2.0 released!
This release brings Lustre up to date with the wider Gleam ecosystem, making
Lustre compatible with the v1 releases of both gleam_erlang
and gleam_otp
.
We also have some improvements to event handling, testing, and the companion
lustre_dev_tools
package now uses Tailwind v4!
Better conditional event handling
With the release of v5 we moved event handlers to a declarative decoder-based
approach. Instead of handling the event object directly, you provide a decoder
for the message to produce and can use modifiers like event.prevent_default
to
prevent an event’s default behaviour. This worked well but we found that it made
some behaviour possible in v4 now no longer possible in v5. Specifically, you
could not conditionally choose to call event.prevent_default
based on the
event’s data.
This release adds a new event.advanced
handler that can be used to indicate
whether or not event.prevent_default
or event.stop_propagation
when the event
is handled, making it possible to implement handlers such as preventing the default
behaviour when the key
property of the event is "Enter"
but not other keys.
pub fn chat_input(
value value: String,
on_input handle_input: fn(String) -> msg,
on_submit handle_submit: msg,
) -> Element(msg) {
let on_keydown = event.advanced({
use key <- decode.field("key", decode.string)
use shift <- decode.field("shiftKey", decode.bool)
use value <- decode.subfield(["target", "value"], decode.string)
case key {
"Enter" if shift ->
decode.success(event.handler(
dispatch: handle_input(value <> "\n"),
prevent_default: True,
stop_propagation: False,
))
"Enter" ->
decode.success(event.handler(
dispatch: handle_submit,
prevent_default: True,
stop_propagation: False,
))
_ ->
decode.success(event.handler(
dispatch: handle_input(value),
prevent_default: False,
stop_propagation: False,
))
}
})
html.textarea([
attribute.value(value),
attribute.on_keydown(on_keydown),
])
}
In the above snippet we implement a chat input that supports submitting a message
when the user presses the Enter
key, and inserting a new line in the input when
the user presses Shift + Enter
.
Better assertion-based testing
Gleam v1.11 introduced the new assert
keyword that will panic if the condition
is not met and is now the de facto way to write tests in Gleam. To help write
better tests, Lustre v5.2 adds the query.matches
and query.has
functions for
making assertions about an element.
pub fn greeting_test() {
let element = greeting("Lucy")
let selector = query.text("Hello, Lucy!")
assert element |> query.matches(selector:)
}
pub fn dashboard_test() {
let element = dashboard(User("Lucy"))
let selector = query.tag("h2") |> query.and(query.text("Welcome, Lucy!"))
assert element |> query.has(selector:)
}
Tailwind v4 support
Lustre Dev Tools is a companion package you can use for zero-config development and building of Lustre applications. Part of that zero-config magic is automatic support and detection for projects using Tailwind CSS.
Tailwind v4 was released in January but up until now Dev Tools users have had to make do with v3. This release updates the binary that Lustre Dev Tools uses, which means a move to a CSS-based configuration and simpler support for Tailwind class detection.
Existing users can continue to use the JavaScript tailwind.config.js
config by
following the instructions in the Tailwind upgrade guide.
For most users adopting the new version will be painless, but there are a small
number of breaking changes you should make sure you check out before upgrading!
And the rest
Lustre’s dependency constraints for gleam_erlang
and gleam_otp
have been
brought up to date with the recent v1 releases of those packages, meaning apps
using server components can update and keep up with the latest core libraries.
We’ve also vendored happy-dom to
help us test Lustre’s client runtime: starting with tests of the reconciler. And,
of course, another round of bug fixes and docs improvements have been made!
Lustre is still largely maintained by me – Hayleigh – with the support of a small number of contributors. To my existing sponsors on GitHub, thank you! Your support has fueled me with both motivation and caffeine to keep the project growing 💕.
If you’re interested in supporting Lustre, one of the best things you can do is build something with it and tell everyone about it!
If you or your company are using Lustre in production, please consider supporting the project financially over on GitHub sponsors.