pablen / toasty / Toasty

This package lets you easily show customizable toast notifications in your Elm apps following The Elm Architecture. You will be able to trigger toasts as a side-effect of model updates by piping your update function return value through this library addToast function.

While this package lets you configure each part of the rendering and behaviour of the notification stack, you can use a nice default theme configuration provided in Toasty.Defaults. See a demo using default styling.

Example

Setting things up

To use the package, let's look at an example that shows a simple text notification.

First you add the toast stack to your model, wrapping the toast model you want in Stack. You must do it in a field called toasties:

type alias Model =
    { toasties : Toasty.Stack String }

Note that in this example we are modelling our toasts as a simple String, but we can model our toasts however we need.

Add the stack initial state in your init function:

init : ( Model, Cmd Msg )
init =
    ( { toasties = Toasty.initialState }, Cmd.none )

Then add a message that will handle toasts messages:

type alias Msg =
    ToastyMsg (Toasty.Msg String)

You can use the default configuration as-is or tweak it to your needs by piping configuration helpers:

myConfig : Toasty.Config msg
myConfig =
    Toasty.config
        |> Toasty.transitionOutDuration 100
        |> Toasty.delay 8000

Handle the toasts message in your app update function using the library update function:

update msg model =
    case msg of
        ToastyMsg subMsg ->
            Toasty.update myConfig ToastyMsg subMsg model

As a last step, render the toast stack in you view function. You will need to provide a special view function that knows how to render your toast model:

view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text "Toasty example" ]
        , Toasty.view myConfig renderToast ToastyMsg model.toasties
        ]

renderToast : String -> Html Msg
renderToast toast =
    div [] [ text toast ]

Triggering toasts

A pretty common scenario is to trigger toasts as side-effect of some other app event, e.g. show a message when an asynchronous response was received. In order to do that, just pipe your update function return value through the addToast function passing your configuration, tag and toast.

    update msg model =
        case msg of
            SomeAppMsg ->
                ( newModel, Cmd.none )
                    |> Toasty.addToast myConfig ToastyMsg "Entity successfully created!"

That's all!

Definition


type Stack a

Represents the stack of current toasts notifications. You can model a toast to be as complex or simple as you want.

type alias Model =
    { toasties : Toasty.Stack MyToast
    }


-- Defines a toast model that has three different variants
type MyToast
    = Success String
    | Warning String
    | Error String String


type Msg a

The internal message type used by the library. You need to tag and add it to your app messages.

type Msg
    = ToastyMsg (Toasty.Msg MyToast)

Configuration

The notifications appearance and behaviour can be fully customized. To do this, you need to import the default configuration and tweak it by piping the provided helper functions.

Note that as you can set container and items HTML attributes the library remains agnostic about how to style your toasts, enabling you to use inline styles or classes.

myConfig : Toasty.Config msg
myConfig =
    Toasty.config
        |> Toasty.transitionOutDuration 700
        |> Toasty.delay 8000
        |> Toasty.containerAttrs containerAttrs

containerAttrs =
    [ style "max-width" "300px"
    , style "position" "fixed"
    , style "right" "0"
    , style "top" "0"
    ]

config : Config msg

Some basic configuration defaults: Toasts are visible for 5 seconds with no animations or special styling.

delay : Basics.Float -> Config msg -> Config msg

Changes the amount of time (in milliseconds) the toast will be visible. After this time, the transition out begins.

transitionOutDuration : Basics.Float -> Config msg -> Config msg

Changes the amount of time (in milliseconds) to wait after transition out begins and before actually removing the toast node from the DOM. This lets you author fancy animations when a toast is removed.

containerAttrs : List (Html.Attribute msg) -> Config msg -> Config msg

Lets you set the HTML attributes to add to the toasts stack container. This will help you style and position the toast stack however you like by adding classes or inline styles.

itemAttrs : List (Html.Attribute msg) -> Config msg -> Config msg

Lets you set the HTML attributes to add to each toast container. This will help you style and arrange the toasts however you like by adding classes or inline styles.

transitionInAttrs : List (Html.Attribute msg) -> Config msg -> Config msg

Lets you set the HTML attributes to add to the toast container when transitioning in.

transitionOutAttrs : List (Html.Attribute msg) -> Config msg -> Config msg

Lets you set the HTML attributes to add to the toast container when transitioning out.


type Config msg

The base configuration type.

Other functions

view : Config msg -> (a -> Html msg) -> (Msg a -> msg) -> Stack a -> Html msg

Renders the stack of toasts. You need to add it to your app view function and give it a function that knows how to render your toasts model.

view model =
    div []
        [ h1 [] [ text "Toasty example" ]
        , Toasty.view myConfig (\txt -> div [] [ text txt ]) ToastyMsg model.toasties
        ]

update : Config msg -> (Msg a -> msg) -> Msg a -> { m | toasties : Stack a } -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg )

Handles the internal messages. You need to wire it to your app update function

update msg model =
    case msg of
        ToastyMsg subMsg ->
            Toasty.update Toasty.config ToastyMsg subMsg model

addToast : Config msg -> (Msg a -> msg) -> a -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg ) -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg )

Adds a toast to the stack and schedules its removal. It receives and returns a tuple of type '(model, Cmd msg)' so that you can easily pipe it to your app update function branches.

update msg model =
    case msg of
        SomeAppMsg ->
            ( newModel, Cmd.none )
                |> Toasty.addToast myConfig ToastyMsg (MyToast "Entity successfully created!")

        ToastyMsg subMsg ->
            Toasty.update myConfig ToastyMsg subMsg model

addPersistentToast : Config msg -> (Msg a -> msg) -> a -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg ) -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg )

Similar to addToast but doesn't schedule the toast removal, so it will remain visible until clicked.

addToastIf : Config msg -> (Msg a -> msg) -> (List a -> Basics.Bool) -> a -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg ) -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg )

Similar to addToast but also receives a condition parameter List toast -> Bool so that the toast will only be added if the condition returns True.

addToastIfUnique : Config msg -> (Msg a -> msg) -> a -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg ) -> ( { m | toasties : Stack a }, Platform.Cmd.Cmd msg )

Similar to addToast but only effectively adds the toast if it's not already present in the stack. This is a convenience addToastIf function using not << List.member toast as a condition parameter.

hasToast : a -> Stack a -> Basics.Bool

Figure out whether a stack contains a specific toast. Similar to List.member.

initialState : Stack a

An empty stack of toasts to initialize your model with.