Selkie--Widget--Toast

NAME

Selkie::Widget::Toast - Transient overlay notification

SYNOPSIS

You normally use $app.toast(...) which manages the widget for you:

$app.toast('Settings saved');
$app.toast('Connection lost', duration => 5e0);

Direct construction is rarely needed.

DESCRIPTION

A centered single-line message bar that auto-dismisses. By convention rendered near the bottom of the screen.

Unlike most widgets, Toast does not own a backing plane covering its full area β€” that would obscure the widgets behind it. Instead it manages a small inline plane, created on show and destroyed on hide, attached directly to the parent stdplane via attach.

The Selkie::App.toast wrapper hides these details: it lazily constructs the widget, calls attach, and ensures the correct size on each invocation.

Fading

Off by default. Selkie::App.new(:animate-toast) turns it on, at which point Selkie::App hands the toast its tween group via enable-fade and every show resolves the bar up out of the screen background over fade-in-seconds and dissolves it back over fade-out-seconds before it disappears.

my $app = Selkie::App.new(theme => $theme, :animate-toast);
$app.toast('Saved');          # fades in, holds, fades out

# Driving a detached Toast yourself:
$toast.enable-fade($app.tweens);
$toast.show('Saved', duration => 2e0);

What ramps is colour, not alpha β€” notcurses alpha is a two-bit enum with no intermediate states (Selkie::Alpha), so a fade is a walk between two RGB values. The far end is theme.base.bg for both the foreground and the background, i.e. a bar the same colour as the screen behind it. A theme whose base carries no bg has no colour to fade from, and the toast simply appears and disappears as it always has.

The out-fade is armed from inside tick, which Selkie::App already calls once per frame: when the remaining lifetime drops below fade-out-seconds the toast adds one reversed tween to the group and never looks at the clock again. Both tweens are bounded, and the toast cancels whatever is in flight on the next show, on dismissal, and in destroy β€” so a fade can never outlive the plane it paints into.

Timings are fade-in-seconds (0.1) and fade-out-seconds (0.2), settable at construction. A toast whose whole duration is shorter than fade-out-seconds gets an out-fade clamped to the time it actually has left rather than one that would run past its own dismissal.

EXAMPLES

Custom styling

# Red warning style
$app.store.subscribe-with-callback(
    'errors',
    -> $s { $s.get-in('error') // '' },
    -> $msg {
        if $msg.chars > 0 {
            $app.toast($msg);   # default blue-highlight style
        }
    },
    $some-widget,
);

SEE ALSO

  • Selkie::App β€” toast(...) wrapper is the normal entry point

  • Selkie::Tween β€” the interpolation the fade runs on

  • Selkie::Alpha β€” why a fade is a colour ramp and never an alpha ramp

has Num $.fade-in-seconds

Seconds the toast takes to resolve up out of the screen background. Only consulted once enable-fade has been called.

has Num $.fade-out-seconds

Seconds the toast takes to dissolve back into it, ending as the duration expires. Clamped to the lifetime actually remaining.

method attach

method attach(
    Notcurses::Native::Types::NcplaneHandle $parent-plane,
    Int :$rows where { ... },
    Int :$cols where { ... }
) returns Mu

Attach to the standard plane. Called once by Selkie::App in place of the usual init-plane β€” Toast lives outside the widget tree (so it can paint on top of any screen and any modal) so it doesn't adopt a plane of its own; the toast-plane is created lazily in render on first show.

method handle-resize

method handle-resize(
    Int $rows where { ... },
    Int $cols where { ... }
) returns Mu

Toast lives at screen-top, outside the widget tree, so it doesn't receive the normal handle-resize cascade from containers. App calls this directly when the terminal resizes so the toast-plane sits at the correct width.

method resize-screen

method resize-screen(
    Int $rows where { ... },
    Int $cols where { ... }
) returns Mu

Back-compat alias. Deprecated β€” prefer handle-resize.

method show

method show(
    Str:D $message,
    Num :$duration = 2e0,
    Selkie::Style :$style,
    Instant :$at = Code.new
) returns Mu

Show a toast message for :duration seconds. Re-callable while a toast is already showing β€” the new message replaces the old and the duration restarts from :at. Apps don't usually call this directly; prefer $app.toast(...) which routes here. :at is the toast's zero point, defaulting to now; pass it explicitly to drive the lifetime (and the fades) from a test clock rather than the wall clock.

method is-visible

method is-visible() returns Bool

True while a toast is currently being shown (between show and the next tick that observes the duration has expired).

method enable-fade

method enable-fade(
    Selkie::Tween::TweenGroup:D $group
) returns Nil

Turn fading on and hand the toast the Selkie::Tween::TweenGroup its fades run on β€” normally Selkie::App.tweens, wired automatically when the app was built with CΒ«:animate-toastΒ». Idempotent, and takes effect from the next show: a toast already on screen keeps whatever it is doing.

method disable-fade

method disable-fade() returns Nil

Go back to appearing and vanishing. Any fade in flight is cancelled and the toast drops straight to its own style, so a "reduce motion" preference flipped mid-fade lands somewhere sane rather than freezing a half-transparent bar on screen.

method fade-enabled

method fade-enabled() returns Bool

True once enable-fade has been called and disable-fade hasn't.

method fading

method fading() returns Bool

True while a fade-in or fade-out is actually running. A testing hook.

method render-style

method render-style() returns Selkie::Style

The style render paints with right now: the fade's current interpolation while one is in flight, and the toast's own style otherwise. Public so a fade can be asserted without a plane.

method fade-from

method fade-from(
    Selkie::Style:D $to
) returns Selkie::Style

The colour a fade starts from (and ends at): the theme's base background on both channels, with every discrete attribute copied from $to so nothing snaps at the midpoint. Returns $to unchanged when the theme's base has no background β€” there is no colour to fade from, so there is no fade.

method tick

method tick(
    Instant $at = Code.new
) returns Bool

Advance the toast's lifetime clock. Called once per frame by Selkie::App. When the duration has elapsed, the toast flips to invisible and its plane is destroyed. Returns True when visibility just transitioned from visible to invisible this tick β€” the caller (Selkie::App) treats that as a signal to force one more composite render so the toast is actually erased from the terminal. Returns False otherwise (toast is still visible, or was never visible this tick). $at defaults to now; pass it to drive the lifetime from a test clock. This is also where the out-fade is armed, once, when the remaining lifetime drops under fade-out-seconds β€” a check that costs one subtraction on a toast that isn't fading.

method destroy

method destroy() returns Mu

Tear down the toast plane and cancel any fade still running against it. Called by Selkie::App.shutdown; apps don't usually call this directly.

Selkie v0.11.1

High-level TUI framework built on Notcurses

Authors

  • Matt Doughty

License

Artistic-2.0

Dependencies

Notcurses::Native:ver<0.4.1+>:auth<zef:apogee>

Test Dependencies

Provides

  • Selkie
  • Selkie::Align
  • Selkie::Alpha
  • Selkie::App
  • Selkie::App::Internal::Animation
  • Selkie::App::Internal::Dispatch
  • Selkie::App::Internal::ErrorLog
  • Selkie::App::Internal::FocusTree
  • Selkie::App::Internal::HitTest
  • Selkie::App::Internal::IdleBudget
  • Selkie::App::Internal::OverlayTree
  • Selkie::App::Internal::RenderLoop
  • Selkie::App::Internal::ScreenModalLifecycle
  • Selkie::App::Internal::Terminal
  • Selkie::App::Internal::TerminalSequences
  • Selkie::BorderStyle
  • Selkie::Container
  • Selkie::EffectiveBounds
  • Selkie::Event
  • Selkie::Gradient
  • Selkie::Layout::Allocate
  • Selkie::Layout::HBox
  • Selkie::Layout::Split
  • Selkie::Layout::VBox
  • Selkie::Plot::Palette
  • Selkie::Plot::Scaler
  • Selkie::Plot::Ticks
  • Selkie::ScreenManager
  • Selkie::Sizing
  • Selkie::Store
  • Selkie::Style
  • Selkie::Test::Focus
  • Selkie::Test::Keys
  • Selkie::Test::Snapshot
  • Selkie::Test::Snapshot::Harness
  • Selkie::Test::Store
  • Selkie::Test::Supply
  • Selkie::Test::Tree
  • Selkie::Theme
  • Selkie::Trace
  • Selkie::Tree
  • Selkie::Tween
  • Selkie::Widget
  • Selkie::Widget::Axis
  • Selkie::Widget::BarChart
  • Selkie::Widget::Border
  • Selkie::Widget::Button
  • Selkie::Widget::CardList
  • Selkie::Widget::Checkbox
  • Selkie::Widget::CommandPalette
  • Selkie::Widget::ConfirmModal
  • Selkie::Widget::FileBrowser
  • Selkie::Widget::FocusableByDefault
  • Selkie::Widget::GradientFill
  • Selkie::Widget::Heatmap
  • Selkie::Widget::HelpOverlay
  • Selkie::Widget::Histogram
  • Selkie::Widget::Image
  • Selkie::Widget::Legend
  • Selkie::Widget::LineChart
  • Selkie::Widget::ListView
  • Selkie::Widget::Modal
  • Selkie::Widget::MultiLineInput
  • Selkie::Widget::PasswordStrength
  • Selkie::Widget::Plot
  • Selkie::Widget::ProgressBar
  • Selkie::Widget::RadioGroup
  • Selkie::Widget::RichText
  • Selkie::Widget::RichText::Span
  • Selkie::Widget::ScatterPlot
  • Selkie::Widget::ScrollView
  • Selkie::Widget::Select
  • Selkie::Widget::Sparkline
  • Selkie::Widget::Spinner
  • Selkie::Widget::TabBar
  • Selkie::Widget::Table
  • Selkie::Widget::Text
  • Selkie::Widget::TextInput
  • Selkie::Widget::TextInput::HighlightSpan
  • Selkie::Widget::TextStream
  • Selkie::Widget::Toast
  • Selkie::Widget::ViewportedCardList

Documentation

The Camelia image is copyright 2009 by Larry Wall. "Raku" is trademark of the Yet Another Society. All rights reserved.

Built with Podlite β€” the markup and publishing tools behind this site.