elm-mdl/examples/Demo/Snackbar.elm

294 lines
7 KiB
Elm
Raw Normal View History

2016-03-17 19:56:04 +00:00
module Demo.Snackbar where
import Effects exposing (Effects, none)
import Html exposing (..)
import Html.Attributes exposing (class, style, key)
import Array exposing (Array)
2016-04-08 13:51:45 +00:00
import Time exposing (Time, millisecond)
2016-03-17 19:56:04 +00:00
2016-04-08 13:51:45 +00:00
import Material.Helpers exposing (map1st, map2nd, delay)
2016-03-19 22:47:21 +00:00
import Material.Color as Color
2016-04-08 13:51:45 +00:00
import Material.Style exposing (styled, cs, css)
2016-03-17 19:56:04 +00:00
import Material.Snackbar as Snackbar
import Material.Button as Button exposing (Action(..))
import Material.Grid exposing (..)
2016-03-30 07:19:18 +00:00
import Material.Elevation as Elevation
import Material
2016-03-17 19:56:04 +00:00
2016-03-30 07:19:18 +00:00
import Demo.Page as Page
2016-03-17 19:56:04 +00:00
-- MODEL
2016-04-07 07:52:11 +00:00
type alias Mdl =
Material.Model Action
2016-04-08 13:51:45 +00:00
type Square'
= Appearing
| Idle
| Disappearing
type alias Square =
(Int, Square')
2016-03-17 19:56:04 +00:00
type alias Model =
{ count : Int
2016-04-08 13:51:45 +00:00
, squares : List Square
, mdl : Mdl
2016-03-17 19:56:04 +00:00
}
model : Model
model =
{ count = 0
2016-04-08 13:51:45 +00:00
, squares = []
, mdl = Material.model
2016-03-17 19:56:04 +00:00
}
-- ACTION, UPDATE
type Action
2016-04-08 13:51:45 +00:00
= AddSnackbar
| AddToast
2016-04-08 13:51:45 +00:00
| Appear Int
| Disappear Int
| Gone Int
| MDL (Material.Action Action)
2016-03-17 19:56:04 +00:00
2016-04-07 07:52:11 +00:00
add : Model -> (Int -> Snackbar.Contents Action) -> (Model, Effects Action)
add model f =
let
(mdl', fx) =
2016-04-08 13:51:45 +00:00
Snackbar.add (f model.count) snackbar model.mdl
model' =
{ model
| mdl = mdl'
, count = model.count + 1
2016-04-08 13:51:45 +00:00
, squares = (model.count, Appearing) :: model.squares
}
in
2016-04-08 13:51:45 +00:00
( model'
, Effects.batch
[ Effects.tick (always (Appear model.count))
, fx
]
)
mapSquare : Int -> (Square' -> Square') -> Model -> Model
mapSquare k f model =
{ model
| squares =
List.map
( \((k', sq) as s) -> if k /= k' then s else (k', f sq) )
model.squares
}
2016-03-17 19:56:04 +00:00
update : Action -> Model -> (Model, Effects Action)
update action model =
case action of
AddSnackbar ->
2016-04-07 07:52:11 +00:00
add model
2016-04-08 13:51:45 +00:00
<| \k -> Snackbar.snackbar ("Snackbar message #" ++ toString k) "UNDO" (Disappear k)
2016-03-17 19:56:04 +00:00
2016-04-07 07:52:11 +00:00
AddToast ->
add model
<| \k -> Snackbar.toast <| "Toast message #" ++ toString k
2016-03-17 19:56:04 +00:00
2016-04-08 13:51:45 +00:00
Appear k ->
( model |> mapSquare k (always Idle)
, none
)
Disappear k ->
( model |> mapSquare k (always Disappearing)
, delay transitionLength (Gone k)
)
Gone k ->
2016-03-17 19:56:04 +00:00
({ model
2016-04-08 13:51:45 +00:00
| squares = List.filter (fst >> (/=) k) model.squares
2016-03-17 19:56:04 +00:00
}
, none)
MDL action' ->
Material.update MDL action' model.mdl
|> map1st (\m -> { model | mdl = m })
2016-03-17 19:56:04 +00:00
2016-04-07 07:52:11 +00:00
2016-04-08 13:51:45 +00:00
-- VIEW
2016-03-17 19:56:04 +00:00
2016-04-07 07:52:11 +00:00
addSnackbarButton : Button.Instance Mdl Action
addSnackbarButton =
Button.instance 0 MDL
Button.raised (Button.model True)
[ Button.fwdClick AddSnackbar ]
2016-04-07 07:52:11 +00:00
addToastButton : Button.Instance Mdl Action
addToastButton =
Button.instance 1 MDL
Button.raised (Button.model True)
[ Button.fwdClick AddToast ]
2016-04-08 13:51:45 +00:00
-- TODO: Bad name
snackbar : Snackbar.Instance Mdl Action
snackbar =
2016-04-07 07:52:11 +00:00
Snackbar.instance MDL Snackbar.model
2016-03-17 19:56:04 +00:00
2016-04-08 13:51:45 +00:00
boxHeight : String
boxHeight = "48px"
boxWidth : String
boxWidth = "64px"
transitionLength : Time
transitionLength = 150 * millisecond
transitions : (String, String)
transitions =
("transition"
, "box-shadow 333ms ease-in-out 0s, "
++ "width " ++ toString transitionLength ++ "ms, "
++ "height " ++ toString transitionLength ++ "ms"
)
clickView : Model -> Square -> Html
clickView model (k, square) =
2016-03-17 19:56:04 +00:00
let
color =
2016-03-19 22:47:21 +00:00
Array.get ((k + 4) % Array.length Color.palette) Color.palette
|> Maybe.withDefault Color.Teal
|> flip Color.color Color.S500
2016-04-08 13:51:45 +00:00
selected' =
Snackbar.activeAction (snackbar.get model.mdl) == Just (Disappear k)
2016-04-08 13:51:45 +00:00
(width, height, margin, selected) =
case square of
Idle ->
(boxWidth, boxHeight, "16px 16px", selected')
_ ->
("0", "0", "16px 0", False)
2016-03-17 19:56:04 +00:00
in
2016-04-08 13:51:45 +00:00
div
[ style
[ ("height", boxHeight)
, ("width", width)
, ("position", "relative")
2016-03-17 19:56:04 +00:00
, ("display", "inline-block")
2016-04-08 13:51:45 +00:00
, ("margin", margin)
, ("transition",
"width " ++ toString transitionLength ++ "ms ease-in-out 0s, "
++ "margin " ++ toString transitionLength ++ "ms ease-in-out 0s"
)
, ("z-index", "0")
2016-03-17 19:56:04 +00:00
]
2016-04-08 13:51:45 +00:00
, key <| toString k
2016-03-17 19:56:04 +00:00
]
2016-04-08 13:51:45 +00:00
[ styled div
[ Color.background color
, Color.text Color.primaryContrast
, Elevation.shadow (if selected then 8 else 2)
]
[ style
[ ("display", "inline-flex")
, ("align-items", "center")
, ("justify-content", "center")
, ("height", height)
, ("width", width)
, ("border-radius", "2px")
, transitions
, ("overflow", "hidden")
, ("box-sizing", "border-box")
, ("flex", "0 0 auto")
, ("position", "absolute")
, ("bottom", "0")
, ("left", "0")
]
]
[ div [] [ text <| toString k ] ]
]
2016-03-17 19:56:04 +00:00
2016-03-19 22:47:21 +00:00
2016-03-17 19:56:04 +00:00
view : Signal.Address Action -> Model -> Html
view addr model =
2016-03-31 19:58:30 +00:00
Page.body "Snackbar & Toast" srcUrl intro references
[ p []
[ text """Click the buttons below to activate the snackbar. Note that
multiple activations are automatically queued."""
]
, grid [ ] --css "margin-top" "32px" ]
2016-04-08 13:51:45 +00:00
[ cell
[ size All 2, size Phone 2, align Top ]
[ addToastButton.view addr model.mdl
[ Button.colored
, css "margin" "16px"
]
[ text "Toast" ]
2016-03-17 19:56:04 +00:00
]
2016-03-31 19:58:30 +00:00
, cell
[ size All 2, size Phone 2, align Top ]
2016-04-08 13:51:45 +00:00
[ addSnackbarButton.view addr model.mdl
[ Button.colored
, css "margin" "16px"
]
[ text "Snackbar" ]
2016-03-17 19:56:04 +00:00
]
, cell
2016-04-08 13:51:45 +00:00
[ size Desktop 7, offset Desktop 1
, size Tablet 3, offset Tablet 1
, size Phone 4
, align Top
]
(model.squares |> List.reverse |> List.map (clickView model))
2016-03-17 19:56:04 +00:00
]
2016-04-08 13:51:45 +00:00
, snackbar.view addr model.mdl
2016-03-17 19:56:04 +00:00
]
intro : Html
2016-03-30 07:19:18 +00:00
intro =
Page.fromMDL "https://www.getmdl.io/components/index.html#snackbar-section" """
2016-03-17 19:56:04 +00:00
> The Material Design Lite (MDL) __snackbar__ component is a container used to
> notify a user of an operation's status. It displays at the bottom of the
> screen. A snackbar may contain an action button to execute a command for the
> user. Actions should undo the committed action or retry it if it failed for
> example. Actions should not be to close the snackbar. By not providing an
> action, the snackbar becomes a __toast__ component.
2016-03-30 07:19:18 +00:00
"""
2016-03-17 19:56:04 +00:00
2016-03-31 19:58:30 +00:00
2016-03-30 07:19:18 +00:00
srcUrl : String
srcUrl =
"https://github.com/debois/elm-mdl/blob/master/examples/Demo/Snackbar.elm"
2016-03-17 19:56:04 +00:00
2016-03-31 19:58:30 +00:00
2016-03-30 07:19:18 +00:00
references : List (String, String)
references =
2016-03-31 19:58:30 +00:00
[ Page.package "http://package.elm-lang.org/packages/debois/elm-mdl/latest/Material-Snackbar"
2016-03-30 07:19:18 +00:00
, Page.mds "https://www.google.com/design/spec/components/snackbars-toasts.html"
, Page.mdl "https://www.getmdl.io/components/index.html#snackbar-section"
]
2016-03-17 19:56:04 +00:00