Skip to content

ModernToast

ModernToast is an opinionated alternative to the core Bootstrap Toast. It is for polished app-style notifications with configurable position, duration, variant, and visual style.

Use core Toast when you want Bootstrap's native toast structure. Use ModernToast when you want a more modern product UI surface.

Import

from faststrap import ModernToast, ModernToastStack

Basic Usage

ModernToast(
    "Saved",
    "Your changes were applied.",
    variant="success",
)

With Position, Duration, And Style

ModernToast(
    "Invite sent",
    "We emailed the new team member.",
    variant="success",
    position="top-end",
    duration=4000,
    style="glass",
)

Toast Stack

ModernToastStack(
    ModernToast("Saved", variant="success"),
    ModernToast("Sync delayed", "Trying again soon.", variant="warning"),
    position="bottom-end",
)

With Action

ModernToast(
    "Project archived",
    "You can restore it from settings.",
    variant="warning",
    action=Button("Undo", variant="link"),
)

Parameters

ModernToast

Param Type Default Description
title str required Main toast title.
message str \| None None Optional message.
variant VariantType info Semantic Bootstrap variant.
position ToastPositionType top-end Preferred stack position metadata.
duration int 4000 Duration metadata in milliseconds.
style solid \| soft \| glass glass Visual style class.
icon str \| None None Bootstrap icon override.
action Any \| None None Optional action component.
dismissible bool True Shows the close button.
**kwargs Any Extra attributes.

ModernToastStack

Param Type Default Description
*toasts Any Toast children.
position ToastPositionType top-end Fixed stack position.
gap int 2 Bootstrap grid gap utility suffix.
**kwargs Any Extra attributes.

Behavior Notes

  • ModernToast is an opinionated static surface, not Bootstrap's native toast plugin.
  • The close button removes the toast with a tiny inline handler.
  • duration is emitted as metadata for app/runtime integrations; it does not auto-dismiss by itself unless your app adds that behavior.

faststrap.components.feedback.modern_toast.ModernToast(title, message=None, *, variant='info', position='top-end', duration=4000, style='glass', icon=None, action=None, dismissible=True, **kwargs)

Render an opinionated modern toast surface.

Source code in src/faststrap/components/feedback/modern_toast.py
@register(category="feedback")
@beta
def ModernToast(
    title: str,
    message: str | None = None,
    *,
    variant: VariantType = "info",
    position: ToastPositionType = "top-end",
    duration: int = 4000,
    style: ToastStyle = "glass",
    icon: str | None = None,
    action: Any | None = None,
    dismissible: bool = True,
    **kwargs: Any,
) -> Div:
    """Render an opinionated modern toast surface."""
    user_cls = kwargs.pop("cls", "")
    resolved_icon = icon if icon is not None else TOAST_ICONS.get(variant)
    attrs: dict[str, Any] = {
        "cls": merge_classes(
            "faststrap-modern-toast d-flex gap-3 rounded-4 border shadow-lg p-3",
            f"faststrap-modern-toast-{style}",
            f"border-{variant}",
            user_cls,
        ),
        "role": "status" if variant not in {"danger", "warning"} else "alert",
        "data_fs_modern_toast": "true",
        "data_variant": variant,
        "data_position": position,
        "data_duration": str(duration),
    }
    attrs.update(convert_attrs(kwargs))

    parts: list[Any] = []
    if resolved_icon:
        parts.append(
            Span(
                Icon(resolved_icon, cls=f"text-{variant}", aria_hidden="true"),
                cls="fs-5 lh-1 mt-1",
            )
        )

    body_parts: list[Any] = [Span(title, cls="fw-semibold d-block")]
    if message:
        body_parts.append(P(message, cls="small text-muted mb-0"))
    if action:
        body_parts.append(Div(action, cls="mt-2"))
    parts.append(Div(*body_parts, cls="flex-grow-1 min-w-0"))

    if dismissible:
        parts.append(
            FTButton(
                "",
                type="button",
                cls="btn-close",
                aria_label="Dismiss notification",
                onclick="this.closest('[data-fs-modern-toast]').remove()",
            )
        )

    return Div(*parts, **attrs)

faststrap.components.feedback.modern_toast.ModernToastStack(*toasts, position='top-end', gap=2, **kwargs)

Render a positioned stack of ModernToast components.

Source code in src/faststrap/components/feedback/modern_toast.py
@register(category="feedback")
@beta
def ModernToastStack(
    *toasts: Any,
    position: ToastPositionType = "top-end",
    gap: int = 2,
    **kwargs: Any,
) -> Div:
    """Render a positioned stack of ModernToast components."""
    user_cls = kwargs.pop("cls", "")
    position_classes = {
        "top-start": "top-0 start-0",
        "top-center": "top-0 start-50 translate-middle-x",
        "top-end": "top-0 end-0",
        "top-left": "top-0 start-0",
        "top-right": "top-0 end-0",
        "bottom-start": "bottom-0 start-0",
        "bottom-center": "bottom-0 start-50 translate-middle-x",
        "bottom-end": "bottom-0 end-0",
        "bottom-left": "bottom-0 start-0",
        "bottom-right": "bottom-0 end-0",
        "middle-start": "top-50 start-0 translate-middle-y",
        "middle-center": "top-50 start-50 translate-middle",
        "middle-end": "top-50 end-0 translate-middle-y",
    }
    attrs: dict[str, Any] = {
        "cls": merge_classes(
            "faststrap-modern-toast-stack position-fixed p-3 d-grid",
            f"gap-{gap}",
            position_classes.get(position, position_classes["top-end"]),
            user_cls,
        ),
        "data_fs_modern_toast_stack": "true",
        "data_position": position,
        "style": "z-index: 1080;",
    }
    attrs.update(convert_attrs(kwargs))
    return Div(*toasts, **attrs)