elm-mdl/Material/Button.elm

235 lines
6.7 KiB
Elm
Raw Normal View History

2016-03-08 16:30:09 +00:00
module Material.Button
2016-03-13 21:47:00 +00:00
( Model, model, Action(Click), update
, Coloring(..)
, flat, raised, fab, minifab, icon
2016-03-08 16:30:09 +00:00
) where
{-| From the [Material Design Lite documentation](http://www.getmdl.io/components/#buttons-section):
> The Material Design Lite (MDL) button component is an enhanced version of the
> standard HTML `<button>` element. A button consists of text and/or an image that
> clearly communicates what action will occur when the user clicks or touches it.
> The MDL button component provides various types of buttons, and allows you to
> add both display and click effects.
2016-03-13 21:47:00 +00:00
>
2016-03-08 16:30:09 +00:00
> Buttons are a ubiquitous feature of most user interfaces, regardless of a
> site's content or function. Their design and use is therefore an important
> factor in the overall user experience. See the button component's Material
> Design specifications page for details.
2016-03-13 21:47:00 +00:00
>
2016-03-08 16:30:09 +00:00
> The available button display types are flat (default), raised, fab, mini-fab,
> and icon; any of these types may be plain (light gray) or colored, and may be
> initially or programmatically disabled. The fab, mini-fab, and icon button
> types typically use a small image as their caption rather than text.
See also the
[Material Design Specification]([https://www.google.com/design/spec/components/buttons.html).
# Component
2016-03-13 21:47:00 +00:00
@docs Model, model, Action, update
2016-03-08 16:30:09 +00:00
# View
2016-03-13 21:47:00 +00:00
Refer to the
[Material Design Specification](https://www.google.com/design/spec/components/buttons.html)
for details about what type of buttons are appropriate for which situations.
@docs Coloring, flat, raised, fab, minifab, icon
2016-03-08 16:30:09 +00:00
-}
import Html exposing (..)
import Html.Attributes exposing (..)
2016-03-13 21:47:00 +00:00
import Html.Events exposing (onClick)
import Effects exposing (Effects, none)
2016-03-08 16:30:09 +00:00
import Material.Aux as Aux
import Material.Ripple as Ripple
{-| MDL button.
-}
-- MODEL
2016-03-13 21:47:00 +00:00
{-| Model of the button; common to all kinds of button.
Use `model` to initalise it.
2016-03-08 16:30:09 +00:00
-}
type Model = S (Maybe Ripple.Model)
{-| Model initialiser. Call with `True` if the button should ripple when
clicked, `False` otherwise.
-}
model : Bool -> Model
model shouldRipple =
if shouldRipple then
S (Just Ripple.model)
else
S Nothing
-- ACTION, UPDATE
2016-03-13 21:47:00 +00:00
{-| Component action. The `Click` action fires when the button is clicked.
2016-03-08 16:30:09 +00:00
-}
2016-03-13 21:47:00 +00:00
type Action
= Ripple Ripple.Action
| Click
2016-03-08 16:30:09 +00:00
{-| Component update.
-}
update : Action -> Model -> (Model, Effects Action)
update action model =
2016-03-13 21:47:00 +00:00
case action of
Click ->
(model, none)
2016-03-08 16:30:09 +00:00
2016-03-13 21:47:00 +00:00
Ripple action' ->
case model of
S (Just ripple) ->
let (ripple', e) = Ripple.update action' ripple
in
(S (Just ripple'), Effects.map Ripple e)
S Nothing ->
(model, none)
2016-03-08 16:30:09 +00:00
2016-03-13 21:47:00 +00:00
-- VIEW
2016-03-08 16:30:09 +00:00
{-| Coloring of a button. `Plain` respectively `Colored` is the button's
uncolored respectively colored defaults.
`Primary` respectively `Accent` chooses a colored button with the indicated
color.
-}
type Coloring
= Plain
| Colored
| Primary
| Accent
2016-03-13 21:47:00 +00:00
view : String -> Signal.Address Action -> Model -> Coloring -> List Html -> Html
view kind addr model coloring html =
2016-03-08 16:30:09 +00:00
button
2016-03-13 21:47:00 +00:00
[ classList
2016-03-08 16:30:09 +00:00
[ ("mdl-button", True)
, ("mdl-js-button", True)
, ("mdl-js-ripple-effect", model /= S Nothing)
-- Color effect.
2016-03-13 21:47:00 +00:00
, ("mdl-button--colored", coloring == Colored)
, ("mdl-button--primary", coloring == Primary)
, ("mdl-button--accent", coloring == Accent)
2016-03-08 16:30:09 +00:00
-- Kind.
2016-03-13 21:47:00 +00:00
, (kind, kind /= "")
2016-03-08 16:30:09 +00:00
]
2016-03-13 21:47:00 +00:00
, Aux.blurOn "mouseup"
, Aux.blurOn "mouseleave"
, onClick addr Click
]
(case model of
S (Just ripple) ->
Ripple.view
(Signal.forwardTo addr Ripple)
[ class "mdl-button__ripple-container"
, Aux.blurOn "mouseup" ]
ripple
:: html
_ -> html)
{-| From the
[Material Design Specification](https://www.google.com/design/spec/components/buttons.html#buttons-flat-buttons):
> Flat buttons are printed on material. They do not lift, but fill with color on
> press.
>
> Use flat buttons in the following locations:
>
> - On toolbars
> - In dialogs, to unify the button action with the dialog content
> - Inline, with padding, so the user can easily find them
Example use (uncolored flat button, assuming properly setup model):
import Material.Button as Button
flatButton : Html
flatButton = Button.flat addr model Button.Plain [text "Click me!"]
-}
flat : Signal.Address Action -> Model -> Coloring -> List Html -> Html
flat = view ""
{-| From the
[Material Design Specification](https://www.google.com/design/spec/components/buttons.html#buttons-raised-buttons):
> Raised buttons add dimension to mostly flat layouts. They emphasize functions
> on busy or wide spaces.
>
> Raised buttons behave like a piece of material resting on another sheet
> they lift and fill with color on press.
Example use (colored raised button, assuming properly setup model):
import Material.Button as Button
raisedButton : Html
raisedButton = Button.raised addr model Button.Colored [text "Click me!"]
-}
raised : Signal.Address Action -> Model -> Coloring -> List Html -> Html
raised = view "mdl-button--raised"
{-| Floating Action Button. From the
[Material Design Specification](https://www.google.com/design/spec/components/buttons-floating-action-button.html):
> Floating action buttons are used for a promoted action. They are distinguished
> by a circled icon floating above the UI and have motion behaviors that include
> morphing, launching, and a transferring anchor point.
>
> Floating action buttons come in two sizes:
>
> - Default size: For most use cases
> - Mini size: Only used to create visual continuity with other screen elements
This constructor produces the default size, use `minifab` to get the mini-size.
Example use (colored with a '+' icon):
import Material.Button as Button
import Material.Icon as Icon
fabButton : Html
fabButton = fab addr model Colored [Icon.i "add"]
-}
fab : Signal.Address Action -> Model -> Coloring -> List Html -> Html
fab = view "mdl-button--fab"
{-| Mini-sized variant of a Floating Action Button; refer to `fab`.
-}
minifab : Signal.Address Action -> Model -> Coloring -> List Html -> Html
minifab = view "mdl-button--mini-fab"
{-| The [Material Design Lite implementation](https://www.getmdl.io/components/index.html#buttons-section)
also offers an "icon button", which we
re-implement here. See also
[Material Design Specification](http://www.google.com/design/spec/components/buttons.html#buttons-toggle-buttons).
Example use (no color, displaying a '+' icon):
import Material.Button as Button
import Material.Icon as Icon
iconButton : Html
iconButton = icon addr model Plain [Icon.i "add"]
-}
icon : Signal.Address Action -> Model -> Coloring -> List Html -> Html
icon = view "mdl-button--icon"