BSD-3-Clause licensed by Jeremy Barisch-Rooney
Maintained by [email protected]
This version can be pinned in stack with:threepenny-gui-flexbox-0.3.0.2@sha256:a3c3608ceabd7b543bd5a3d96b35b19b3b88476e262fec489fd146537cf8e12c,1165

Module documentation for 0.3.0.2

* 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

Flexbox properties that apply to the parent element, things like
~flex-direction~, are stored in a ~ParentProps~ data type.

Flexbox properties that apply to children elements, things like ~flex-grow~,
are stored in a ~ChildProps~ data type.

For both ~ParentProps~ and ~ChildProps~ we provide standard default values,
via the respective functions ~parentProps :: ParentProps~ and ~childProps ::
ChildProps~.

** Setting Properties

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

** Full Example

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.

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

#+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]

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

** More Control

If you don't want to use ~flexbox~ but rather set CSS values on elements
yourself you can use the functions ~toStyle~ and ~setProps~.

~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

To save a few more characters you can use ~setProps~ to set the given
properties on an element.

#+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