Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
notification
Toast-style notifications, triggered from anywhere in a bubbletea program via an exported
tea.Msg (ShowMsg/Show) rather than a direct reference to the Model that ends up rendering
them - standard Elm architecture, no IPC between processes.
It composites over an already-rendered string, so it has no dependency on
github.com/anotherhadi/ilovetui/layout: the same Model works whether the host uses layout
for its main content or not.
Quick start
import (
"github.com/anotherhadi/ilovetui/notification"
)
type model struct {
notif notification.Model
width, height int
}
func newModel() model {
return model{notif: notification.New()}
}
func (m model) Init() tea.Cmd { return m.notif.Init() }
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
switch msg := msg.(type) {
case tea.KeyPressMsg:
if msg.String() == "s" {
return m, notification.Show("Saved", "Config written to disk", notification.Success)
}
}
var cmd tea.Cmd
m.notif, cmd = m.notif.Update(msg)
return m, cmd
}
func (m model) View() tea.View {
background := renderYourUI(m.width, m.height)
view := tea.NewView(m.notif.Render(background))
view.AltScreen = true
return view
}
Any component in the same bubbletea program can trigger a toast via notification.Show, without
holding a reference to the notification.Model that will actually render it - that Model just
needs to see every tea.Msg the program produces (i.e. get its Update called from the top-level
Update), same as any other child model.
Showing and dismissing
return m, notification.Show("Saved", "Config written to disk", notification.Success)
return m, notification.Show("Sticky", "Stays until dismissed",
notification.Info, notification.WithID("sticky-demo"), notification.WithDuration(0))
return m, notification.Dismiss("sticky-demo")
Four kinds: Info, Success, Warning, Error, each with its own color preset (see Styling
below). By default a toast auto-dismisses after notification.DefaultDuration (3s);
WithDuration(0) makes it sticky - it stays until Dismiss(id) removes it, so a sticky toast
needs WithID to be dismissable later (an auto-generated id is never returned to the caller).
Showing again with the same id replaces the toast in place, resetting its position and timer,
instead of stacking a duplicate.
Position and stacking
n := notification.New(notification.WithPosition(notification.TopRight))
Six anchors: Top, TopLeft, TopRight, Bottom, BottomLeft, BottomRight - toasts always
hug an edge or corner, never the middle of the screen. Multiple toasts stack along the anchored
edge, newest closest to it; a stack that overflows the background's height clips the oldest
toasts first, so the newest ones stay visible.
Styling
n := notification.New(notification.WithMaxWidth(40), notification.WithStyles(myStyles))
return m, notification.Show("Title", "Message", notification.Success,
notification.WithToastStyle(oneOffStyle))
WithMaxWidth caps how wide a toast box can grow before its message wraps; a toast narrower than
the cap shrinks to fit its content instead of padding out to it. A toast can also never overflow
past the edge of whatever background it's rendered on, regardless of this cap. WithStyles sets
the default per-Kind look for every toast shown by this Model; WithToastStyle (a Show
option) overrides it for one toast alone. DefaultStyles() builds from style.S: Info uses
Primary (no dedicated "info" color in the theme), Success/Warning/Error use their matching
style.S alias.
Examples
examples/notification- all four kinds, a sticky toast with manual dismiss, cycling through all six positions.