diff options
author | Benjamin Barenblat <benjamin@barenblat.name> | 2017-01-16 16:06:09 -0500 |
---|---|---|
committer | Benjamin Barenblat <benjamin@barenblat.name> | 2017-01-16 16:06:09 -0500 |
commit | 59e04bbb5acde9e2ce209ee43bad9c134debe4d4 (patch) | |
tree | 34d0870c9e228a76aef72f9276658882f6f66b78 | |
parent | d457eb2a8778d23bf98a8593b5083a2750b0e05a (diff) |
Add floating action button
Abstract ripple effect, as it’s shared between the button and the
checkboxes.
-rw-r--r-- | main.ur | 4 | ||||
-rw-r--r-- | material/lib.urp | 1 | ||||
-rw-r--r-- | material/material.css | 42 | ||||
-rw-r--r-- | material/material.ur | 129 | ||||
-rw-r--r-- | material/material.urs | 6 |
5 files changed, 126 insertions, 56 deletions
@@ -1,4 +1,4 @@ -(* Copyright 2016 Benjamin Barenblat +(* Copyright 2016, 2017 Benjamin Barenblat Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -47,6 +47,7 @@ datatype mode = NextActions | NewNextAction val main = actionItems <- bind renderNextActions source; mode <- source NextActions; + floatingActionButton <- Material.FloatingActionButton.make "add"; return (Material.page { Head = <xml> (* TODO(bbaren): Write a meta-description tag. *) @@ -76,6 +77,7 @@ val main = {Material.List.SingleLine.make <xml> <dyn signal={signal actionItems} /> </xml>} + {floatingActionButton} </div> </xml> }) diff --git a/material/lib.urp b/material/lib.urp index 0f75854..f6f779e 100644 --- a/material/lib.urp +++ b/material/lib.urp @@ -1,3 +1,4 @@ file /material.css material.css +rewrite style Material/materialIcon material-icons material
\ No newline at end of file diff --git a/material/material.css b/material/material.css index 0a762f2..bdc63a6 100644 --- a/material/material.css +++ b/material/material.css @@ -24,6 +24,15 @@ html, body { z-index: 0; } +.Material_Ripple_ink { + display: block; + position: fixed; + transform: scale(0); + background: #fafafa; + border-radius: 100%; + animation: ripple 300ms linear; +} + .Material_AppBar_bar { background: #9c27b0; height: 56px; @@ -69,22 +78,35 @@ html, body { background: #9c27b0 url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgdmVyc2lvbj0iMS4xIgogICB2aWV3Qm94PSIwIDAgMSAxIgogICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPSJ4TWluWU1pbiBtZWV0Ij4KICA8cGF0aAogICAgIGQ9Ik0gMC4wNDAzODA1OSwwLjYyNjc3NjcgMC4xNDY0NDY2MSwwLjUyMDcxMDY4IDAuNDI5Mjg5MzIsMC44MDM1NTMzOSAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IE0gMC4yMTcxNTcyOSwwLjgwMzU1MzM5IDAuODUzNTUzMzksMC4xNjcxNTcyOSAwLjk1OTYxOTQxLDAuMjczMjIzMyAwLjMyMzIyMzMsMC45MDk2MTk0MSB6IgogICAgIGlkPSJyZWN0Mzc4MCIKICAgICBzdHlsZT0iZmlsbDojZmZmZmZmO2ZpbGwtb3BhY2l0eToxO3N0cm9rZTpub25lIiAvPgo8L3N2Zz4K); } -.Material_Checkbox_ink { - display: block; - position: fixed; - transform: scale(0); +.Material_Checkbox_container .Material_Ripple_ink { background: #9c27b0; /* TODO(bbaren): Is this the correct color? */ - border-radius: 100%; - animation: ripple 300ms linear; - - /* These must match the width and height defined in Material.Checkbox. */ - width: 24px; - height: 24px; /* Place the ripple effect underneath the checkmark. */ z-index: -1; } +.Material_FloatingActionButton_container { + width: 56px; + height: 56px; + position: fixed; + right: 16px; + bottom: 16px; + border-radius: 100%; + overflow: hidden; + box-shadow: 0px 6px 12px 0px rgba(0,0,0,0.34); /* 6dp */ +} + +.Material_FloatingActionButton_element { + width: 100%; + height: 100%; + background: #ff9800; + border: none; + + /* Black text on orange looks a bit weird, but the MDL color picker says that’s + correct, so.... */ + color: #000; +} + .Material_List_SingleLine_element { list-style-type: none; height: 48px; diff --git a/material/material.ur b/material/material.ur index 72a3e98..f63bec0 100644 --- a/material/material.ur +++ b/material/material.ur @@ -12,13 +12,52 @@ under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. *) +style materialIcon style stackingContext +fun icon s = <xml><i class={materialIcon}>{[s]}</i></xml> + fun inNewStackingContext x = <xml><div class={stackingContext}>{x}</div></xml> +structure Ripple : sig + val inkAnimation : int -> int -> source (option {X : int, Y : int}) -> xbody +end = struct + style ink + + fun inkStyle width height xy = + let + fun p a b = value (property a) (atom (show b ^ "px")) + in + oneProperty + (oneProperty + (oneProperty + (oneProperty noStyle + (p "width" width)) + (p "height" height)) + (p "left" (xy.X - width / 2))) + (p "top" (xy.Y - height / 2)) + end + + fun inkAnimation width height s = + <xml> + <dyn + signal={ + v <- signal s; + return (case v of + None => <xml></xml> + | Some xy => <xml> + <span class={ink} style={inkStyle width height xy}> + </span> + </xml>) + } + /> + </xml> +end + (* TODO(bbaren): Support attributes in the arguments. *) fun page p = <xml> <head> + <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" /> <link rel="stylesheet" href="/material.css" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> @@ -49,63 +88,65 @@ structure Checkbox = struct style checkbox style checked style container - style ink (* Pixel dimensions of the checkbox. If you update these, you must also update the CSS file. *) val width = 24 val height = 24 - fun centeredAtXY x y : css_style = - let - val x' = x - width / 2 - val y' = y - width / 2 - in - oneProperty (oneProperty - noStyle - (value (property "left") (atom (show x' ^ "px")))) - (value (property "top") (atom (show y' ^ "px"))) - end - - fun inkAnimation (s : source (option {X : int, Y : int})) = - <xml> - <dyn - signal={ - v <- signal s; - return (case v of - None => <xml></xml> - | Some xy => <xml> - <span class={ink} style={centeredAtXY xy.X xy.Y}></span> - </xml>) - } - /> - </xml> - val make c onChange = s <- source c; inkCenter <- source None; return (inNewStackingContext <xml> - {inkAnimation inkCenter} - <span - dynClass={ - c <- signal s; - return (classes checkbox (if c then checked else null)) - } - onclick={fn click => - set inkCenter (Some {X = click.ClientX, Y = click.ClientY}); - c <- get s; - let - val c' = not c - in - set s c'; - onChange c' - end - } - > - </span> + <div class={container}> + {Ripple.inkAnimation width height inkCenter} + <span + dynClass={ + c <- signal s; + return (classes checkbox (if c then checked else null)) + } + onclick={fn click => + set inkCenter (Some {X = click.ClientX, Y = click.ClientY}); + c <- get s; + let + val c' = not c + in + set s c'; + onChange c' + end + } + > + </span> + </div> </xml>) end +structure FloatingActionButton = struct + style container + style element + + (* Pixel dimensions of the button. If you update these, you must also + update the CSS file. *) + val width = 56 + val height = 56 + + fun make s = + inkCenter <- source None; + return <xml> + <div class={container}> + <button + class={element} + onclick={fn click => + set inkCenter (Some {X = click.ClientX, Y = click.ClientY}) + } + > + {icon s} + </button> + {Ripple.inkAnimation width height inkCenter} + </div> + </xml> +end + structure List = struct structure SingleLine = struct style element diff --git a/material/material.urs b/material/material.urs index cee2b85..7cb7c89 100644 --- a/material/material.urs +++ b/material/material.urs @@ -1,4 +1,4 @@ -(* Copyright 2016 Benjamin Barenblat +(* Copyright 2016, 2017 Benjamin Barenblat Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -21,6 +21,10 @@ structure Checkbox : sig val make : bool -> (bool -> transaction unit) -> transaction xbody end +structure FloatingActionButton : sig + val make : string -> transaction xbody +end + structure List : sig structure SingleLine : sig val make : xbody -> xbody |