threepenny-gui-flexbox 0.3.0.2 → 0.4
raw patch · 4 files changed
+121/−93 lines, 4 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Graphics.UI.Threepenny.Ext.Flexbox: column :: UI Element -> [UI Element] -> UI Element
- Graphics.UI.Threepenny.Ext.Flexbox: flexbox :: UI Element -> ParentProps -> [(UI Element, ChildProps)] -> UI Element
- Graphics.UI.Threepenny.Ext.Flexbox: row :: UI Element -> [UI Element] -> UI Element
+ Graphics.UI.Threepenny.Ext.Flexbox: aligContent :: AlignContentValue -> ParentProps
+ Graphics.UI.Threepenny.Ext.Flexbox: alignItems :: AlignItemsValue -> ParentProps
+ Graphics.UI.Threepenny.Ext.Flexbox: alignSelf :: AlignSelfValue -> ChildProps
+ Graphics.UI.Threepenny.Ext.Flexbox: display :: Display -> ParentProps
+ Graphics.UI.Threepenny.Ext.Flexbox: flex :: UI Element -> ParentProps -> [(UI Element, ChildProps)] -> UI Element
+ Graphics.UI.Threepenny.Ext.Flexbox: flexBasis :: Size LengthUnit -> ChildProps
+ Graphics.UI.Threepenny.Ext.Flexbox: flexDirection :: FlexDirection -> ParentProps
+ Graphics.UI.Threepenny.Ext.Flexbox: flexGrow :: Int -> ChildProps
+ Graphics.UI.Threepenny.Ext.Flexbox: flexShrink :: Int -> ChildProps
+ Graphics.UI.Threepenny.Ext.Flexbox: flexWrap :: FlexWrap -> ParentProps
+ Graphics.UI.Threepenny.Ext.Flexbox: flex_c :: UI Element -> ParentProps -> [UI Element] -> UI Element
+ Graphics.UI.Threepenny.Ext.Flexbox: flex_p :: UI Element -> [(UI Element, ChildProps)] -> UI Element
+ Graphics.UI.Threepenny.Ext.Flexbox: flex_pc :: UI Element -> [UI Element] -> UI Element
+ Graphics.UI.Threepenny.Ext.Flexbox: justifyContent :: JustifyContentValue -> ParentProps
+ Graphics.UI.Threepenny.Ext.Flexbox: order :: Int -> ChildProps
- Graphics.UI.Threepenny.Ext.Flexbox: setProps :: ToStyle a => UI Element -> a -> UI Element
+ Graphics.UI.Threepenny.Ext.Flexbox: setProps :: ToStyle a => a -> UI Element -> UI Element
Files
- README.org +69/−67
- app/Main.hs +4/−7
- src/Graphics/UI/Threepenny/Ext/Flexbox.hs +47/−18
- threepenny-gui-flexbox.cabal +1/−1
README.org view
@@ -1,89 +1,91 @@ * Threepenny-gui Flexbox [[https://travis-ci.org/barischj/threepenny-gui-flexbox.svg?branch=master]] [[https://img.shields.io/hackage/v/threepenny-gui-flexbox.svg]] [[https://www.stackage.org/package/threepenny-gui-flexbox/badge/nightly?.jpg]] - Flexbox layouts for Threepenny-gui.+Flexbox layouts for Threepenny-gui. - This library was written following the wonderful- [[https://css-tricks.com/snippets/css/a-guide-to-flexbox][A Complete Guide to- Flexbox]] and using the equally wonderful- [[https://hackage.haskell.org/package/clay][Clay]] library as a CSS domain- specific language.+This library was written following the wonderful [[https://css-tricks.com/snippets/css/a-guide-to-flexbox][A Complete Guide to Flexbox]] and+using the equally wonderful [[https://hackage.haskell.org/package/clay][Clay]] library as a CSS domain specific language. [[./example.png]] * Usage - Flexbox properties that apply to the parent element, things like- ~flex-direction~, are stored in a ~ParentProps~ data type.+** Properties - Flexbox properties that apply to children elements, things like ~flex-grow~,- are stored in a ~ChildProps~ data type.+Ultimately we just want to set Flexbox properties on elements, both parent and+child elements. In CSS these properties would look like ~flex-grow: 1;~.++We collect Flexbox properties that apply to the parent element, things like+~flex-direction~, in a ~ParentProps~ data type. Flexbox properties that apply to+child elements, things like ~flex-grow~, are collected in a ~ChildProps~ data+type. - For both ~ParentProps~ and ~ChildProps~ we provide standard default values,- via the respective functions ~parentProps :: ParentProps~ and ~childProps ::- ChildProps~.+If you want ~ChildProps~ with ~flex-grow: 1;~ you can just do: -** Setting Properties+#+BEGIN_SRC Haskell+flexGrow 1+#+END_SRC - You can set a property by using the defaults and over-riding a specific entry- using record syntax.- - Setting ~flex-grow: 2;~ which is a property for a child element:- #+BEGIN_SRC Haskell- childProps { cFlexGrow = 2 }- #+END_SRC- - You can use Clay to set values for some of the more exotic types.- - Setting ~display: inline-flex;~ which is property for a parent element:- #+BEGIN_SRC Haskell- parentProps { pDisplay = Clay.Flexbox.inlineFlex }- #+END_SRC+You can define multiple properties using record syntax: -** Full Example+#+BEGIN_SRC Haskell+order 1 { cflexGrow = 1, cFlexShrink = 2 }+#+END_SRC - Once you have your properties defined you need to apply them to elements and- attach the children to the parent. ~flexbox~ provides this functionality, you- need to pass a parent element and respective properties, and a list of- children elements and their respective properties.+Note that in the examples above we used ~flexGrow~ and ~order~ to return+~ChildProps~ with given values set but also with default values set for all+other Flexbox properties, unless record syntax is used to override a property. - The example image above was produced with the below code. It attaches three- ~div~ s with text "foo" to the ~body~ in the ratio 1:2:1. The example can be- run with ~stack exec threepenny-flexbox-exe~.+Some properties like ~flexGrow~ simply take an ~Int~ but others take a value+from the ~Clay~ library. Here's an example for ~ParentProps~:++#+BEGIN_SRC Haskell+display Clay.Display.inlineFlex { pFlexWrap = Clay.Flexbox.nowrap }+#+END_SRC++If you just want ~ParentProps~ or ~ChildProps~ with default values:++#+BEGIN_SRC Haskell+parentProps :: ParentProps+childProps :: ChildProps+#+END_SRC - #+BEGIN_SRC Haskell- -- |Example of three divs using a flex-grow ratio of 1:2:1.- example :: Window -> UI ()- example w = void $- flexbox (getBody w) parentProps $ [grow 1, grow 2, grow 1]+** Setting Properties - -- |Example "foo" div and given flex-grow value.- grow :: Int -> (UI Element, ChildProps)- grow n = (foo, childProps { cFlexGrow = n })- where foo = UI.div # set UI.text "foo"- # set UI.style [("background-color", "#F89406"),- ("margin", "8px")]- #+END_SRC+Once you have your properties defined you'll want to apply them to elements.+For this you can use ~setProps~ which can be used with Threepenny's reverse+function application operator ~#~: -** More Control+#+BEGIN_SRC Haskell+UI.div # set UI.text "foo" # setProps (order 1)+#+END_SRC - If you don't want to use ~flexbox~ but rather set CSS values on elements- yourself you can use the functions ~toStyle~ and ~setProps~.+You can also convert ~ParentProps~ or ~ChildProps~ to a ~[(String, String)]~+which is [[http://hackage.haskell.org/package/threepenny-gui/docs/src/Graphics-UI-Threepenny-Core.html#style][how Threepenny expects CSS]]. This can be done using ~toStyle~ which is+defined in the typeclass ~ToStyle~: - ~ParentProps~ and ~ChildProps~ are both an instance of ~ToStyle~, defined- below. That means you can convert either parent properties or child properties- to a ~[(String, String)]~ which is [[http://hackage.haskell.org/package/threepenny-gui/docs/src/Graphics-UI-Threepenny-Core.html#style][how Threepenny expects CSS]].- - #+BEGIN_SRC Haskell- -- |Convert to Threepenny style.- class ToStyle a where- toStyle :: a -> [(String, String)]- #+END_SRC+#+BEGIN_SRC Haskell+UI.div # set UI.style (toStyle $ order 1)+#+END_SRC - To save a few more characters you can use ~setProps~ to set the given- properties on an element.+*** 'flex' - #+BEGIN_SRC Haskell- -- |Set Flexbox properties on an element.- setProps :: ToStyle a => UI Element -> a -> UI Element- setProps el props = el # set UI.style (toStyle props)- #+END_SRC+We provide a utility function ~flex~ which takes both parent and child elements+and their respective ~ParentProps~ and ~ChildProps~, applies the respective+properties and then returns the parent element with children attached. We also+provide variants of this function which use default properties for parent or+children. Below is a full example demonstrating this, which produced the image+above.+ +#+BEGIN_SRC Haskell+-- |Example of three divs using a flex-grow ratio of 1:2:1.+example :: Window -> UI ()+example w = void $+ flex_p (getBody w) $ [grow 1, grow 2, grow 1]++-- |Example "foo" div and given flex-grow value.+grow :: Int -> (UI Element, ChildProps)+grow n = (foo, flexGrow n)+ where foo = UI.div # set UI.text "foo"+ # set UI.style [("background-color", "#F89406"),+ ("margin", "8px")]+#+END_SRC
app/Main.hs view
@@ -3,10 +3,8 @@ import Control.Monad (void) import qualified Graphics.UI.Threepenny as UI import Graphics.UI.Threepenny.Core hiding (row)-import Graphics.UI.Threepenny.Ext.Flexbox (ChildProps, cFlexGrow,- childProps,- parentProps,- flexbox)+import Graphics.UI.Threepenny.Ext.Flexbox (ChildProps, flexGrow,+ flex_p) main :: IO () main = startGUI defaultConfig example@@ -14,12 +12,11 @@ -- |Example of three divs using a flex-grow ratio of 1:2:1. example :: Window -> UI () example w = void $- flexbox (getBody w) parentProps $ [grow 1, grow 2, grow 1]+ flex_p (getBody w) $ [grow 1, grow 2, grow 1] -- |Example "foo" div and given flex-grow value. grow :: Int -> (UI Element, ChildProps)-grow n = (foo, childProps { cFlexGrow = n })+grow n = (foo, flexGrow n) where foo = UI.div # set UI.text "foo" # set UI.style [("background-color", "#F89406"), ("margin", "8px")]-
src/Graphics/UI/Threepenny/Ext/Flexbox.hs view
@@ -2,14 +2,17 @@ -- * Parent Properties ParentProps (..), parentProps, + -- ** Parent Property Helpers+ display, flexDirection, flexWrap, justifyContent, alignItems, aligContent,+ -- * Child Properties ChildProps (..), childProps, - -- * Core Functions- ToStyle, flexbox, setProps, toStyle,+ -- ** Child Property Helpers+ order, flexGrow, flexShrink, flexBasis, alignSelf, - -- * Helper Functions- column, row+ -- * Core Functions+ ToStyle (..), setProps, flex, flex_p, flex_c, flex_pc ) where import qualified Clay.Common as CC@@ -68,6 +71,13 @@ , pAlignContent = CF.stretch } +display x = parentProps { pDisplay = x }+flexDirection x = parentProps { pFlexDirection = x }+flexWrap x = parentProps { pFlexWrap = x }+justifyContent x = parentProps { pJustifyContent = x }+alignItems x = parentProps { pAlignItems = x }+aligContent x = parentProps { pAlignContent = x }+ -- |Properties for a child. data ChildProps = ChildProps { cOrder :: Int@@ -97,27 +107,46 @@ , cAlignSelf = CC.auto } +order x = childProps { cOrder = x }+flexGrow x = childProps { cFlexGrow = x }+flexShrink x = childProps { cFlexShrink = x }+flexBasis x = childProps { cFlexBasis = x }+alignSelf x = childProps { cAlignSelf = x }+ -- |Set Flexbox properties on an element.-setProps :: ToStyle a => UI Element -> a -> UI Element-setProps el props = el # set UI.style (toStyle props)+setProps :: ToStyle a => a -> UI Element -> UI Element+setProps props el = el # set UI.style (toStyle props) --- |Attach elements to a parent element, with given Flexbox properties applied.-flexbox ::+-- |Attach elements to a parent element, applying given Flexbox properties.+flex :: UI Element -- ^ Parent -> ParentProps -- ^ Parent Flexbox properties -> [(UI Element, ChildProps)] -- ^ Children and respective Flexbox properties -> UI Element -- ^ Parent with attached children-flexbox p pProps cs = do- p' <- setProps p pProps- cs' <- mapM (uncurry setProps) cs+flex p pProps cs = do+ p' <- p # setProps pProps+ cs' <- mapM (\(c, cProps) -> c # setProps cProps) cs element p' #+ map element cs' --- |Attach elements to a parent element with flex-direction column.-column :: UI Element -> [UI Element] -> UI Element-column p cs = flexbox p parentProps { pFlexDirection = CF.column } $- zip cs $ repeat childProps+-- |Like 'flex' but apply default properties to the parent.+flex_p ::+ UI Element -- ^ Parent+ -> [(UI Element, ChildProps)] -- ^ Children and respective Flexbox properties+ -> UI Element -- ^ Parent with attached children+flex_p p = flex p parentProps --- |Attach elements to a parent element with default Flexbox properties.-row :: UI Element -> [UI Element] -> UI Element-row p cs = flexbox p parentProps $ zip cs $ repeat childProps+-- |Like 'flex' but apply default properties to the children.+flex_c ::+ UI Element -- ^ Parent+ -> ParentProps -- ^ Parent Flexbox properties+ -> [UI Element] -- ^ Children+ -> UI Element -- ^ Parent with attached children+flex_c p pProps cs = flex p pProps $ zip cs $ repeat childProps++-- |Like 'flex' but apply default properties to the parent and children.+flex_pc ::+ UI Element -- ^ Parent+ -> [UI Element] -- ^ Children+ -> UI Element -- ^ Parent with attached children+flex_pc p = flex_c p parentProps
threepenny-gui-flexbox.cabal view
@@ -1,5 +1,5 @@ name: threepenny-gui-flexbox-version: 0.3.0.2+version: 0.4 synopsis: Flexbox layouts for Threepenny-gui. homepage: https://github.com/barischj/threepenny-gui-flexbox license: BSD3