packages feed

threepenny-gui-flexbox-0.4: README.org

* 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.

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

** Properties

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.
  
If you want ~ChildProps~ with ~flex-grow: 1;~ you can just do:

#+BEGIN_SRC Haskell
flexGrow 1
#+END_SRC

You can define multiple properties using record syntax:

#+BEGIN_SRC Haskell
order 1 { cflexGrow = 1, cFlexShrink = 2 }
#+END_SRC

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.

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
  
** Setting Properties

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 ~#~:

#+BEGIN_SRC Haskell
UI.div # set UI.text "foo" # setProps (order 1)
#+END_SRC

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~:

#+BEGIN_SRC Haskell
UI.div # set UI.style (toStyle $ order 1)
#+END_SRC

*** 'flex'

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