Biji UI

Toast

Ephemeral notifications that slide in from the corner of the screen, auto-dismiss after a configurable duration, and pause on hover.

Installation

biji-ui = { version = "0.5.0", features = ["toast"] }

Usage

Wrap your app (or any subtree) with <Toaster>. This provides ToasterContext to all descendants. Access it anywhere with expect_context::<ToasterContext>() and call add() with your own type string to show a toast.

use leptos::prelude::*;
use biji_ui::components::toast::{Toaster, ToasterContext};

// 1. Wrap your app (or any subtree) with <Toaster>.
//    This provides ToasterContext to all descendants.
#[component]
pub fn App() -> impl IntoView {
    view! {
        <Toaster>
            <MyApp />
        </Toaster>
    }
}

// 2. Anywhere inside, grab the context and call add() with your own type string.
#[component]
pub fn SaveButton() -> impl IntoView {
    let toaster = expect_context::<ToasterContext>();

    view! {
        <button on:click=move |_| {
            toaster.add("Changes saved successfully.", None, Some("success".to_string()), None);
        }>
            "Save"
        </button>
    }
}

Styling

The component is fully headless — no styles are applied by default. Pass a toast_class string to <Toaster> and use data-[type=…], data-[entering=true], data-[dismissed=true], and data-[paused=true] Tailwind arbitrary-variant selectors to control each state. Enable the progress bar with show_progress=true and style it with progress_class.

// Pass a toast_class to style individual toasts.
// Use data-[type=…], data-[entering=…], data-[dismissed=…], data-[paused=…] selectors.
// The type value is whatever string you pass to add() — define your own vocabulary.
<Toaster
    pause_on_hover=PauseOnHover::Single
    show_progress=true
    progress_class="absolute bottom-0 left-0 h-0.5 bg-current opacity-30 rounded-full"
    toast_class="relative flex items-start gap-3 w-full rounded-lg border px-4 py-3 \
        shadow-md text-sm font-medium bg-background border-border text-foreground \
        overflow-hidden transition-all duration-300 ease-in-out \
        data-[entering=true]:opacity-0 data-[entering=true]:translate-y-2 \
        data-[dismissed=true]:opacity-0 data-[dismissed=true]:translate-x-[calc(100%+1rem)] \
        data-[type=success]:border-green-500/30 data-[type=success]:bg-green-50 \
        data-[type=success]:text-green-900 dark:data-[type=success]:bg-green-950/30 \
        dark:data-[type=success]:text-green-100"
>
    <MyApp />
</Toaster>

API Reference

Toaster

NameTypeDefaultDescription
childrenChildrenThe app subtree. ToasterContext is available to all descendants.
default_durationOption<Duration>4000 msHow long a toast stays visible before auto-dismissing.
hide_delayOption<Duration>300 msTime between data-dismissed="true" and the toast being removed from the DOM. Should match your CSS exit-animation duration.
positionToastPositionBottomRightViewport corner where the toast stack appears. One of TopLeft, TopCenter, TopRight, BottomLeft, BottomCenter, BottomRight.
max_toastsusize5Maximum number of toasts shown at once. Toasts beyond this limit are immediately dismissed (and animate out).
pause_on_hoverPauseOnHoverSingleSingle — only the hovered toast pauses. All — hovering any toast pauses all. Disable — hover has no effect.
show_progressboolfalseWhen true, renders a countdown progress bar inside each toast. The bar's width transitions from 100% to 0% over the toast duration. Style it with progress_class.
progress_classString""CSS class for the progress bar element. Control height, color, and position here — the inline style handles width.
classString""Extra CSS class on the stack container div.
toast_classString""CSS class applied to every individual toast element. Style via data-[type=…], data-[entering=…], data-[dismissed=…], data-[paused=…] selectors.

ToasterContext methods

NameTypeDefaultDescription
toast(title)impl Into<String>Add a toast with no type string.
add(title, description, toast_type, duration)String, Option<String>, Option<String>, Option<Duration>Full control: title, optional description, optional type string (emitted as data-type), and optional custom duration.
dismiss(id)u32Start the exit animation for a specific toast.
dismiss_all()Dismiss all active toasts.

Data Attributes

AttributeDescription
data-typeThe user-supplied type string passed to add(). Absent when no type was given. Use any value you want — e.g. "success", "error", or your own custom variants.
data-entering"true" for ~1 ms after mount so CSS transitions fire from the hidden state. Use data-[entering=true]:… to define your enter-from state.
data-dismissed"true" once the toast starts its exit animation. Use data-[dismissed=true]:… to define your exit state.
data-paused"true" while the toast's countdown is paused (e.g. on hover). Use data-[paused=true]:… to show a visual indicator.

Keyboard Navigation

KeyDescription
TabMove focus to the dismiss button.
Enter / SpaceActivate the focused dismiss button, triggering the exit animation.