packages feed

templates-0.1.0.0: src/Templates/Partials/Containers.hs

{-# LANGUAGE OverloadedStrings #-}
module Templates.Partials.Containers where

import Classh
import Classh.Reflex
import Templates.Partials.Image
import Templates.Partials.Buttons
import Templates.Types

import Data.Text as T (Text)
import Data.Bool
import Control.Monad.Fix
import Control.Monad
import Reflex.Dom.Core

screenContainer :: (DomBuilder t m) => m a -> m a
screenContainer = elClass "div" $(classh' [w .~~ TWSize_Screen, h .~~ TWSize_Screen, custom .~ "flex flex-col overflow-hidden"])

toggleButton :: (MonadFix m, DomBuilder t m, PostBuild t m, MonadHold t m) => Text -> m (Dynamic t Bool)
toggleButton label = do
  let
    classes :: Bool -> Text
    classes shown =
      "text-icon font-icon transform select-none "           -- Icon display classes
        <> "transition-transform duration-300 ease-in-out "  -- Animation settings classes
        <> bool "rotate-180" mempty shown                    -- Do a little twirl!

  -- The icon for a rendered container is a triangle pointing up, and
  -- the icon for an unrendered container is that same triangle, rotated
  -- 180deg. Using a single icon + a rotation means the transition can
  -- be animated; Having the "neutral" position be "no transform" means
  -- the icon won't do a twirl on page load.
  rec
    (labelEl, _) <- elClass' "div" $(classh' [ mt .~~ TWSize 8
                                             , custom .~ "cursor-pointer  flex flex-row justify-between"
                                             ]) $ do
      textS $(classh' [ text_color .~~ White ]) label
      elDynClass' "span" (classes <$> toggled) $ text "expand_less"
    let toggleEv = domEvent Click labelEl
    toggled <- holdUniqDyn =<< toggle True toggleEv

  pure toggled




-- | Wrap the body contents in a container that can be collapsed by
-- clicking on its header. As an optimisation, when the container is
-- collapsed, the inner tree is not rendered.
collapsibleContainer_ :: (MonadFix m, DomBuilder t m, PostBuild t m, MonadHold t m) => Text -> m a -> m ()
collapsibleContainer_ label body = do
  toggled <- toggleButton label

  dyn_ (bool blank (void body) <$> toggled)

-- | Wrap the body contents in a container that can be collapsed by
-- clicking on its header.
collapsibleContainer :: (MonadFix m, DomBuilder t m, PostBuild t m, MonadHold t m) => Text -> m a -> m a
collapsibleContainer label body = do
  let
    bodyClasses :: Bool -> Text
    bodyClasses shown = bool "hidden" mempty shown

  toggled <- toggleButton label

  elDynClass "div" (bodyClasses <$> toggled) body


-- | Wrap the body contents in a container that can be collapsed by
-- clicking on its header.
collapsibleContainerWithImage
  :: (MonadFix m, DomBuilder t m, PostBuild t m, MonadHold t m)
  => Text
  -> Text
  -> m a
  -> m a
collapsibleContainerWithImage imgSrc label body = do
  let
    bodyClasses :: Bool -> Text
    bodyClasses shown = bool "hidden" mempty shown

  toggled <- toggleButton' imgSrc label
  elDynClass "div" (bodyClasses <$> toggled) body


toggleButton' :: (MonadFix m, DomBuilder t m, PostBuild t m, MonadHold t m) => Text -> Text -> m (Dynamic t Bool)
toggleButton' imgSrc label = do
  let
    classes :: Bool -> Text
    classes shown =
      "text-icon font-icon transform select-none "           -- Icon display classes
        <> "transition-transform duration-300 ease-in-out "  -- Animation settings classes
        <> bool "rotate-180" mempty shown                    -- Do a little twirl!

  -- The icon for a rendered container is a triangle pointing up, and
  -- the icon for an unrendered container is that same triangle, rotated
  -- 180deg. Using a single icon + a rotation means the transition can
  -- be animated; Having the "neutral" position be "no transform" means
  -- the icon won't do a twirl on page load.
  rec
    (labelEl, _) <- elClass' "div" "grid grid-cols-12 p-4" $ do
      elClass "div" $(classh' [colSpan .~~ 2]) $ imgClass imgSrc ""
      elClass "div" $(classh' [colSpan .~~ 9]) $ textS $(classh' [text_size .|~ [Base,LG,XL,XL2, XL3]]) label
      elDynClass' "span" (classes <$> toggled) $
        dynText "expand_less"

    let toggleEv = domEvent Click labelEl
    toggled <- holdUniqDyn =<< toggle True toggleEv

  pure toggled



openCloseButton :: Template t m => ImgSrc -> Color -> T.Text -> m (Event t ())
openCloseButton imgSrc tColor name = do
  buttonToggleBody (constDyn "pl-10") True $ \case
    True -> do
      --gridCol Col12 $ do
        col [6] $ imgClass imgSrc $(classh' [custom .~ "rotate-180 inline-block", position .~~ centered ])
        divClass $(classh' [colSpan .|~ [6], position .~~ centered, custom .~ "inline-block"]) $ do
          textS (classhUnsafe [text_color .~~ tColor]) $ "close" <&> name
    False -> do
      col [6] $ imgClass imgSrc $(classh' [custom .~ "rotate-180 inline-block", position .~~ centered ])
      divClass $(classh' [colSpan .|~ [6], position .~~ centered, custom .~ "inline-block"]) $ do
        textS (classhUnsafe [text_color .~~ tColor]) $ "open" <&> name