howdy/ui/toast
Toasts: short notifications in a corner of the screen that go away on their own.
toast.region(words.english(), [], [
toast.toast(toast.Info, [], [
toast.title([text("Saved")]),
toast.description([text("Your changes are live.")]),
toast.close([attribute.aria_label("Dismiss")]),
]),
])
Render the region once, on every page or in the live view, and put
toasts in it. It is a live region, so a screen reader reads a toast
when it appears. A toast fades out after five seconds, or the time set
with duration; hovering over it or focusing inside it pauses the
countdown. persistent keeps it until it is closed.
The countdown is a CSS animation, so it works the same for a flash
message rendered with a page and a toast a live view adds to its model.
When a toast fades, its close button is pressed for it, so a live view
hears it the same way as a click and can drop the toast from its model;
queue and view do this for you.
words name the region and, in view, the close buttons; see
howdy/ui/words.
Types
pub type Item {
Item(
id: Int,
variant: Variant,
title: String,
description: String,
shown_at: Int,
lasts: option.Option(Int),
round: Int,
held_since: option.Option(Int),
held_for: Int,
)
}
Constructors
-
Item( id: Int, variant: Variant, title: String, description: String, shown_at: Int, lasts: option.Option(Int), round: Int, held_since: option.Option(Int), held_for: Int, )Arguments
- round
-
How many times it has been updated; each update restarts its countdown.
- held_since
-
When the reader started holding it open, if they still are.
- held_for
-
How long it was held open before that, since it was last shown.
The toasts a live view is showing, by id, for keeping in its model. Push a toast when something happens; update it when a loading toast finishes, so it turns into a success or an error in place; and expire the queue now and then, so toasts that have faded are dropped.
let #(toasts, id) = toast.push(model.toasts, Loading, "Saving…", "", now)
// later, when the save is done:
let toasts = toast.update(toasts, id, Success, "Saved", "", now)
The browser decides when a toast has gone, since it pauses the countdown
while the toast is hovered or focused: when one fades, its close button
is pressed for it, so on_close in view hears it and the toast can be
dismissed. The browser also says when a toast is held open and let go,
through on_hold; pass that to hold, so the queue’s clock pauses with
the browser’s.
expire is a fallback for a fade the browser never reported, such as a
message lost in transit. It drops a toast a minute after its countdown
should have ended, counting only the time it was not held, so a toast
someone is reading is never taken away however long they read it.
Times are milliseconds from any clock that only moves forward, such as
erlang:monotonic_time(millisecond).
pub opaque type Queue
Values
pub fn close(
attributes: List(attribute.Attribute(msg)),
) -> element.Element(msg)
A button in the top corner that hides the toast. Give it an
aria-label; in a live view, add a click handler to drop the toast
from the model too.
pub fn close_class() -> css.Class
pub fn description(
children: List(element.Element(msg)),
) -> element.Element(msg)
pub fn description_class() -> css.Class
pub fn dismiss(queue: Queue, id: Int) -> Queue
Take a toast away, such as when its close button is clicked.
pub fn duration(milliseconds: Int) -> attribute.Attribute(msg)
How long the toast stays before fading, in milliseconds.
pub fn expire(queue: Queue, now: Int) -> Queue
Drop toasts whose countdown should have ended more than a minute before
now but were never closed by the browser. Time held open does not
count, and a toast being held now is always kept.
pub fn flashed(
words: words.Words,
messages: List(flash.Message),
) -> List(element.Element(msg))
A toast for each flash message, to put in a region. They fade like
any other toast, and each has a close button, labelled with the words’
dismiss.
use messages <- flash.take(ctx, flash)
let w = words.english()
page.new("Settings")
|> page.body([toast.region(w, [], toast.flashed(w, messages)), ..])
pub fn hold(queue: Queue, id: Int, held: Bool, now: Int) -> Queue
Note that the reader has started (True) or stopped (False) holding
a toast open, as view’s on_hold reports.
pub fn icon_class() -> css.Class
pub fn push(
queue: Queue,
variant: Variant,
title: String,
description: String,
now: Int,
) -> #(Queue, Int)
Show a toast; returns its id. A loading toast stays until updated; the others fade after five seconds.
pub fn push_flashed(
queue: Queue,
messages: List(flash.Message),
now: Int,
) -> Queue
Push each flash message onto a live view’s queue, oldest first.
pub fn region(
words: words.Words,
attributes: List(attribute.Attribute(msg)),
toasts: List(element.Element(msg)),
) -> element.Element(msg)
The corner toasts appear in. Keep it in the page even when it is empty, so a screen reader is already listening when a toast arrives.
pub fn region_class() -> css.Class
pub fn rules() -> List(#(String, String))
Every class this module uses, for howdy/ui/export.
The CSS this module registers with style.rule, for howdy/ui/export.
pub fn title(
children: List(element.Element(msg)),
) -> element.Element(msg)
pub fn title_class() -> css.Class
pub fn toast(
variant: Variant,
attributes: List(attribute.Attribute(msg)),
children: List(element.Element(msg)),
) -> element.Element(msg)
pub fn update(
queue: Queue,
id: Int,
variant: Variant,
title: String,
description: String,
now: Int,
) -> Queue
Change a toast in place, such as a loading one that has finished. Its countdown starts again.
pub fn view(
words: words.Words,
queue: Queue,
on_close on_close: fn(Int) -> List(attribute.Attribute(msg)),
on_hold on_hold: fn(Int, Bool) -> msg,
) -> element.Element(msg)
The queue’s toasts in a region. on_close gives the attributes of each
toast’s close button, such as a click handler that dismisses it; its
aria-label is the words’ dismiss. It is pressed for you when a toast fades.
on_hold hears a toast’s id when the reader starts (True) or stops
(False) holding it open by pointing at it or focusing inside it; pass
it on to hold. howdy/ui/behaviour presses a faded toast’s close
button and reports holds, so a live view keeping toasts in its model
hears both.