From ef7d2a99166d82b789708e1155df86016b814c7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Rosseb=C3=B8?= Date: Sat, 19 Mar 2016 18:23:47 +0100 Subject: [PATCH] feat(badge):initial implementation --- examples/Demo/Badges.elm | 11 ++++- src/Material/Badge.elm | 87 ++++++++++++++++++++++++++++++++++++++++ src/Material/Icon.elm | 77 +++++++++++++++++++++++++++-------- 3 files changed, 157 insertions(+), 18 deletions(-) create mode 100644 src/Material/Badge.elm diff --git a/examples/Demo/Badges.elm b/examples/Demo/Badges.elm index 4a21d9e..720cf89 100644 --- a/examples/Demo/Badges.elm +++ b/examples/Demo/Badges.elm @@ -1,11 +1,18 @@ module Demo.Badges where --- import Material.Badge exposing (..) +import Material.Icon as Icon +import Material.Badge as Badge import Html exposing (..) +import Html.Attributes exposing (..) view : List Html view = [ - h1 [][text "Badges"] + h1 [][text "Badges"], + Icon.viewWithOptions "add" Icon.S18 [] { badgeInfo = Just (Badge.viewDefault "16")}, + Icon.viewWithOptions "add" Icon.S18 [] { badgeInfo = Just (Badge.view { overlap = False, noBackground = False} "99")}, + Icon.viewWithOptions "add" Icon.S18 [] { badgeInfo = Just (Badge.view { overlap = False, noBackground = True} "4")}, + Icon.view "add" Icon.S18 [], + Icon.i "add" ] diff --git a/src/Material/Badge.elm b/src/Material/Badge.elm new file mode 100644 index 0000000..b1eeb0e --- /dev/null +++ b/src/Material/Badge.elm @@ -0,0 +1,87 @@ +module Material.Badge + ( Options + , view + , viewDefault + , BadgeInfo + ) where + +{-| From the [Material Design Lite documentation](http://www.getmdl.io/components/#badges-section): + +The Material Design Lite (MDL) badge component is an onscreen notification element. A badge consists of a small circle, typically containing a number or other characters, that appears in proximity to another object. A badge can be both a notifier that there are additional items associated with an object and an indicator of how many items there are. + +You can use a badge to unobtrusively draw the user's attention to items they might not otherwise notice, or to emphasize that items may need their attention. For example: + +A "New messages" notification might be followed by a badge containing the number of unread messages. +A "You have unpurchased items in your shopping cart" reminder might include a badge showing the number of items in the cart. +A "Join the discussion!" button might have an accompanying badge indicating the number of users currently participating in the discussion. +A badge is almost always positioned near a link so that the user has a convenient way to access the additional information indicated by the badge. However, depending on the intent, the badge itself may or may not be part of the link. + +Badges are a new feature in user interfaces, and provide users with a visual clue to help them discover additional relevant content. Their design and use is therefore an important factor in the overall user experience. + +@docs viewDefault, view, BadgeInfo, Options +-} + + +import Html exposing (Attribute) +import Html.Attributes exposing (attribute) + + +{-| Internal Type used by other elements. Not sure if this should be documented. +-} +type alias BadgeInfo = + { classes : String + , dataBadge : Attribute + } + +{-| Options for Badge + ovelap: Bool to set css class - mdl-badge--overlap. Make the badge overlap with its container + noBackground: Bool to set css class - mdl-badge--no-background. Applies open-circle effect to badge +-} +type alias Options = + { overlap : Bool + , noBackground : Bool + } + +defaultOptions : Options +defaultOptions = + { + overlap = True + , noBackground = False + } + +{-| View function for Badge + + First parameter will set Badge options. See Options for more info. + Last parameter will set a value to data-badge="value". Assigns string value to badge + + import Material.Badge as Badge + + badgeInfo : Badge.BadgeInfo + badgeInfo = Badge.view { overlap = False, noBackground = False} "3" +-} +view : Options -> String -> BadgeInfo +view options databadge = + let classes = + [ + {css = " mdl-badge", show = True} + , {css = " mdl-badge--no-background", show = options.noBackground} + , {css = " mdl-badge--overlap", show = options.overlap} + ] + |> List.filter .show + |> List.map .css + |> List.foldl (++) "" + in + { classes = " mdl-badge" ++ classes, dataBadge = attribute "data-badge" databadge} + + +{-| Create BadgeInfo with default values + + Parameter will set a value to data-badge="value". Assigns string value to badge + + import Material.Badge as Badge + + badgeInfo : Badge.BadgeInfo + badgeInfo = Badge.viewDefault "3" +-} +viewDefault : String -> BadgeInfo +viewDefault databadge = view defaultOptions databadge diff --git a/src/Material/Icon.elm b/src/Material/Icon.elm index 7b52263..43202be 100644 --- a/src/Material/Icon.elm +++ b/src/Material/Icon.elm @@ -1,5 +1,6 @@ module Material.Icon ( Size(..) + , viewWithOptions , view , i ) where @@ -15,13 +16,12 @@ This implementation assumes that you have or an equivalent means of loading the icons in your HTML header. -@docs i, Size, view +@docs i, Size, viewWithOptions, view -} - import Html exposing (i, text, Html, Attribute) -import Html.Attributes exposing (class) - +import Html.Attributes exposing (class, attribute) +import Material.Badge as Badge {-| Size of an icon. Constructors indicate their pixel size, i.e., `S18` is 18px. The constructor `S` gives you the default size, 24px. @@ -29,6 +29,60 @@ import Html.Attributes exposing (class) type Size = S18 | S24 | S36 | S48 | S +{-| Options +See Badge on how to create a badge. +-} +type alias Options = + { + badgeInfo : Maybe Badge.BadgeInfo + } + +defaultOptions : Options +defaultOptions = + { + badgeInfo = Nothing + } + + +{-| View function for icons. Supply the +[Material Icons Library](https://design.google.com/icons/) name as +the first argument (replace spaces with underscores); and the size of the icon +as the second. Do not use this function to produce clickable icons; use +icon buttons in Material.Button for that. + +I.e., to produce a 48px +["trending flat"](https://design.google.com/icons/#ic_trending_flat) icon with +no attributes: + +See Badge for info on how to create a badge for options. + + import Material.Icon as Icon + + icon : Html + icon = Icon.viewWithOptions "trending_flat" Icon.S48 [] { badgeInfo = Just (Badge.viewDefault "16") + +This function will override any `class` set in `List Attribute`. +-} +viewWithOptions : String -> Size -> List Attribute -> Options-> Html +viewWithOptions name size attrs options = + let + sz = + case size of + S18 -> " md-18" + S24 -> " md-24" + S36 -> " md-36" + S48 -> " md-48" + S -> "" + appAttrs = + case options.badgeInfo of + Just badgeInfo -> List.append attrs [badgeInfo.dataBadge] + Nothing -> attrs + optionClasses = + case options.badgeInfo of + Just badgeInfo -> badgeInfo.classes + Nothing -> "" + in + Html.i (class ("material-icons" ++ sz ++ optionClasses ) :: appAttrs) [text name] {-| View function for icons. Supply the [Material Icons Library](https://design.google.com/icons/) name as @@ -47,18 +101,9 @@ no attributes: This function will override any `class` set in `List Attribute`. -} + view : String -> Size -> List Attribute -> Html -view name size attrs = - let - sz = - case size of - S18 -> " md-18" - S24 -> " md-24" - S36 -> " md-36" - S48 -> " md-48" - S -> "" - in - Html.i (class ("material-icons" ++ sz) :: attrs) [text name] +view name size attrs = viewWithOptions name size attrs defaultOptions {-| Render a default-sized icon with no behaviour. The @@ -73,4 +118,4 @@ I.e., to produce a default size (24xp) "trending flat" icon: icon = Icon.i "trending_flat" -} i : String -> Html -i name = view name S [] +i name = view name S []