IconButton.purs 2.63 KB
Newer Older
arturo's avatar
arturo committed
1 2 3 4 5 6
module Gargantext.Components.Bootstrap.IconButton (iconButton) where

import Gargantext.Prelude

import Data.Foldable (elem, intercalate)
import Effect (Effect)
arturo's avatar
arturo committed
7
import Gargantext.Components.Bootstrap.Types (ComponentStatus(..), Elevation(..), Variant(..))
arturo's avatar
arturo committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
import Gargantext.Utils ((?))
import Gargantext.Utils.Reactix as R2
import React.SyntheticEvent as SE
import Reactix as R
import Reactix.DOM.HTML as H

type Props =
  ( name      :: String
  , callback  :: Unit -> Effect Unit
  | Options
  )

type Options =
  ( className :: String
  , status    :: ComponentStatus
  , title     :: String
  , overlay   :: Boolean
arturo's avatar
arturo committed
25
  , elevation :: Elevation
arturo's avatar
arturo committed
26 27 28 29 30 31 32 33
  , variant   :: Variant
  )

options :: Record Options
options =
  { className : ""
  , status    : Enabled
  , title     : ""
arturo's avatar
arturo committed
34 35
  , overlay   : true
  , elevation : Level0
arturo's avatar
arturo committed
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
  , variant   : Dark
  }

-- | Structural Component for a simple Glyphicon element with call-to-action
-- |
-- | https://forkaweso.me/Fork-Awesome/icons/
iconButton :: forall r. R2.OptLeaf Options Props r
iconButton = R2.optLeaf component options

componentName :: String
componentName = "b-icon-button"

bootstrapName :: String
bootstrapName = "fa"

component :: R.Component Props
component = R.hooksComponent componentName cpt where
  cpt props@{ callback
            , status
arturo's avatar
arturo committed
55 56
            , name
            } _ = do
arturo's avatar
arturo committed
57 58 59 60 61 62 63 64 65 66 67 68
    -- Computed
    let
      wrapperClassName = intercalate " "
        -- provided custom className
        [ props.className
        -- BEM classNames
        , componentName
        , componentName <> "--" <> show status
        , componentName <> "--" <> show props.variant
        , props.overlay ?
            componentName <> "--overlay" $
            ""
arturo's avatar
arturo committed
69
        , componentName <> "--" <> show props.elevation
arturo's avatar
arturo committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
        ]

      contentClassName = intercalate " "
        -- Bootstrap specific classNames
        [ bootstrapName
        , bootstrapName <> "-" <> name
        ]
    -- Behaviors
    let
      click = onClick status callback
    -- Render
    pure $

      H.span
      { className: wrapperClassName
      , on: { click }
      , disabled: elem status [ Disabled, Deferred ]
      }
      [
arturo's avatar
arturo committed
89 90 91 92 93 94 95 96 97
        H.span
        { className: componentName <> "__inner" }
        [
          H.i
          { title: props.title
          , className: contentClassName
          }
          []
        ]
arturo's avatar
arturo committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111
      ]

-- | Clicked event will effectively be triggered according to the
-- | component status props
onClick :: forall event.
     ComponentStatus
  -> (Unit -> Effect Unit)
  -> SE.SyntheticEvent_ event
  -> Effect Unit
onClick status callback event = do
  SE.preventDefault event
  if   status == Enabled
  then callback unit
  else pure unit