From 59e04bbb5acde9e2ce209ee43bad9c134debe4d4 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Mon, 16 Jan 2017 16:06:09 -0500 Subject: Add floating action button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Abstract ripple effect, as it’s shared between the button and the checkboxes. --- main.ur | 4 +- material/lib.urp | 1 + material/material.css | 42 ++++++++++++---- material/material.ur | 129 +++++++++++++++++++++++++++++++++----------------- material/material.urs | 6 ++- 5 files changed, 126 insertions(+), 56 deletions(-) diff --git a/main.ur b/main.ur index 5e2eab2..1f540f8 100644 --- a/main.ur +++ b/main.ur @@ -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 = (* TODO(bbaren): Write a meta-description tag. *) @@ -76,6 +77,7 @@ val main = {Material.List.SingleLine.make } + {floatingActionButton} }) 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 = {[s]} + fun inNewStackingContext x =
{x}
+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 = + + + | Some xy => + + + ) + } + /> + +end + (* TODO(bbaren): Support attributes in the arguments. *) fun page p = + @@ -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})) = - - - | Some xy => - - ) - } - /> - - val make c onChange = s <- source c; inkCenter <- source None; return (inNewStackingContext - {inkAnimation inkCenter} - - set inkCenter (Some {X = click.ClientX, Y = click.ClientY}); - c <- get s; - let - val c' = not c - in - set s c'; - onChange c' - end - } - > - +
+ {Ripple.inkAnimation width height inkCenter} + + set inkCenter (Some {X = click.ClientX, Y = click.ClientY}); + c <- get s; + let + val c' = not c + in + set s c'; + onChange c' + end + } + > + +
) 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 +
+ + {Ripple.inkAnimation width height inkCenter} +
+
+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 -- cgit v1.2.3