Button.purs 2.66 KB
Newer Older
arturo's avatar
arturo committed
1 2 3 4
module Gargantext.Components.Bootstrap.Button (button) where

import Gargantext.Prelude

arturo's avatar
arturo committed
5
import DOM.Simple.Event as DE
arturo's avatar
arturo committed
6 7 8 9
import Data.Array (elem)
import Data.Foldable (intercalate)
import Effect (Effect)
import Gargantext.Components.Bootstrap.Spinner (spinner)
10
import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), ComponentStatus(..), Sizing(..), Variant(..))
arturo's avatar
arturo committed
11 12 13 14
import Gargantext.Utils ((?))
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
arturo's avatar
arturo committed
15
import Reactix.SyntheticEvent as RE
arturo's avatar
arturo committed
16 17 18 19 20 21 22

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

type Options =
23
  ( block     :: Boolean
arturo's avatar
arturo committed
24
  , className :: String
25 26
  , size      :: Sizing
  , status    :: ComponentStatus
27
  , title     :: String
28 29
  , type      :: String
  , variant   :: ButtonVariant
arturo's avatar
arturo committed
30 31 32 33
  )

options :: Record Options
options =
34
  { block     : false
arturo's avatar
arturo committed
35
  , className : ""
36 37
  , status    : Enabled
  , size      : MediumSize
38
  , title     : ""
39 40
  , type      : "button"
  , variant   : ButtonVariant Primary
arturo's avatar
arturo committed
41 42 43 44
  }

-- | Structural Component for the Bootstrap button
-- |
45
-- | https://getbootstrap.com/docs/4.6/components/buttons/
arturo's avatar
arturo committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
button :: forall r. R2.OptComponent Options Props r
button = R2.optComponent component options

componentName :: String
componentName = "b-button"

bootstrapName :: String
bootstrapName = "btn"

component :: R.Component Props
component = R.hooksComponent componentName cpt where
  cpt props@{ callback
            , status
            } children = do
    -- Computed
arturo's avatar
arturo committed
61
    let
arturo's avatar
arturo committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
      className = intercalate " "
        -- provided custom className
        [ props.className
        -- BEM classNames
        , componentName
        , componentName <> "--" <> show status
        -- Bootstrap specific classNames
        , bootstrapName
        , bootstrapName <> "-" <> show props.variant
        , bootstrapName <> "-" <> show props.size
        , props.block == true ?
            bootstrapName <> "-block" $
            mempty
        ]

arturo's avatar
arturo committed
77
      click = onClick status callback
arturo's avatar
arturo committed
78

arturo's avatar
arturo committed
79 80 81 82 83 84 85 86
    -- Render
    pure $

      H.button
      { className
      , on: { click }
      , disabled: elem status [ Disabled, Deferred ]
      , type: props.type
87
      , title: props.title
arturo's avatar
arturo committed
88
      }
arturo's avatar
arturo committed
89 90
      [
        R2.when (status == Deferred) $
arturo's avatar
arturo committed
91
          spinner
arturo's avatar
arturo committed
92 93 94 95
          { className: componentName <> "__spinner" }
      ,
        H.span
        { className: componentName <> "__inner" }
arturo's avatar
arturo committed
96 97 98 99 100
        children
      ]

-- | Clicked event will effectively be triggered according to the
-- | component status props
arturo's avatar
arturo committed
101
onClick ::
arturo's avatar
arturo committed
102 103
     ComponentStatus
  -> (Unit -> Effect Unit)
arturo's avatar
arturo committed
104
  -> RE.SyntheticEvent DE.Event
arturo's avatar
arturo committed
105 106
  -> Effect Unit
onClick status callback event = do
arturo's avatar
arturo committed
107 108
  RE.preventDefault event
  when (status == Enabled) $ callback unit