-----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE MultilineStrings  #-}
{-# LANGUAGE RecordWildCards   #-}
-----------------------------------------------------------------------------
module Miso.UI.Button
  ( -- ** Props
    ButtonProps (..)
  , defaultButtonProps
    -- ** Views
  , button_
  , buttonClass
    -- ** Samples
  , buttonUsage
  , buttonSample
  , buttonCodeSample
  , buttonPropsApi
  ) where
-----------------------------------------------------------------------------
import           Miso
import qualified Miso.Html.Element as H
import qualified Miso.Html.Property as P
import qualified Miso.String as MS
-----------------------------------------------------------------------------
import           Miso.UI.Types
import           Miso.UI.Icons
-----------------------------------------------------------------------------
-- | Props for 'button'
data ButtonProps action
  = ButtonProps
  { forall action. ButtonProps action -> Variant
buttonVariant :: Variant
    -- ^ 'Primary', 'Secondary', 'Destructive', 'Outline', 'Ghost' or 'Link'
  , forall action. ButtonProps action -> Size
buttonSize :: Size
    -- ^ 'DefaultSize', 'Small' or 'Large'
  , forall action. ButtonProps action -> Bool
buttonIcon :: Bool
    -- ^ Square icon-only button (e.g. @btn-icon-outline@)
  , forall action. ButtonProps action -> Bool
buttonDisabled :: Bool
  , forall action. ButtonProps action -> [MisoString]
buttonClasses :: [MisoString]
    -- ^ Extra classes appended to the computed basecoat class
  , forall action. ButtonProps action -> [Attribute action]
buttonAttrs :: [Attribute action]
    -- ^ Extra attributes (e.g. @onClick@)
  }
-----------------------------------------------------------------------------
-- | Smart constructor: primary variant, default size
defaultButtonProps :: ButtonProps action
defaultButtonProps :: forall action. ButtonProps action
defaultButtonProps
  = ButtonProps
  { buttonVariant :: Variant
buttonVariant = Variant
Primary
  , buttonSize :: Size
buttonSize = Size
DefaultSize
  , buttonIcon :: Bool
buttonIcon = Bool
False
  , buttonDisabled :: Bool
buttonDisabled = Bool
False
  , buttonClasses :: [MisoString]
buttonClasses = []
  , buttonAttrs :: [Attribute action]
buttonAttrs = []
  }
-----------------------------------------------------------------------------
-- | Computes the basecoat button class (e.g. @btn-sm-icon-outline@)
buttonClass :: ButtonProps action -> MisoString
buttonClass :: forall action. ButtonProps action -> MisoString
buttonClass ButtonProps {Bool
[MisoString]
[Attribute action]
Size
Variant
buttonVariant :: forall action. ButtonProps action -> Variant
buttonSize :: forall action. ButtonProps action -> Size
buttonIcon :: forall action. ButtonProps action -> Bool
buttonDisabled :: forall action. ButtonProps action -> Bool
buttonClasses :: forall action. ButtonProps action -> [MisoString]
buttonAttrs :: forall action. ButtonProps action -> [Attribute action]
buttonVariant :: Variant
buttonSize :: Size
buttonIcon :: Bool
buttonDisabled :: Bool
buttonClasses :: [MisoString]
buttonAttrs :: [Attribute action]
..} = MisoString -> [MisoString] -> MisoString
MS.intercalate MisoString
"-" ([MisoString] -> MisoString) -> [MisoString] -> MisoString
forall a b. (a -> b) -> a -> b
$ [[MisoString]] -> [MisoString]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
  [ [ MisoString
"btn" ]
  , [ Size -> MisoString
sizeSuffix Size
buttonSize | Size
buttonSize Size -> Size -> Bool
forall a. Eq a => a -> a -> Bool
/= Size
DefaultSize ]
  , [ MisoString
"icon" | Bool
buttonIcon ]
  , [ Variant -> MisoString
variantSuffix Variant
buttonVariant | Variant
buttonVariant Variant -> Variant -> Bool
forall a. Eq a => a -> a -> Bool
/= Variant
Primary ]
  ]
-----------------------------------------------------------------------------
-- | <https://basecoatui.com/components/button/ Button>, driven by 'ButtonProps'
button_
  :: ButtonProps action
  -> [View model action]
  -> View model action
button_ :: forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
cfg [View model action]
kids =
  ([Attribute action] -> [View model action] -> View model action)
-> [Attribute action]
-> Bool
-> [Attribute action]
-> [View model action]
-> View model action
forall action model.
([Attribute action] -> [View model action] -> View model action)
-> [Attribute action]
-> Bool
-> [Attribute action]
-> [View model action]
-> View model action
optionalAttrs
    [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.button_
    ( [MisoString] -> Attribute action
forall action. [MisoString] -> Attribute action
P.classes_ (ButtonProps action -> MisoString
forall action. ButtonProps action -> MisoString
buttonClass ButtonProps action
cfg MisoString -> [MisoString] -> [MisoString]
forall a. a -> [a] -> [a]
: ButtonProps action -> [MisoString]
forall action. ButtonProps action -> [MisoString]
buttonClasses ButtonProps action
cfg)
    Attribute action -> [Attribute action] -> [Attribute action]
forall a. a -> [a] -> [a]
: ButtonProps action -> [Attribute action]
forall action. ButtonProps action -> [Attribute action]
buttonAttrs ButtonProps action
cfg
    )
    (ButtonProps action -> Bool
forall action. ButtonProps action -> Bool
buttonDisabled ButtonProps action
cfg)
    [ Attribute action
forall action. Attribute action
P.disabled_ ]
    [View model action]
kids
-----------------------------------------------------------------------------
-- | Compact usage example (source of the kitchen sink "Code" tab)
buttonUsage :: View model action
buttonUsage :: forall model action. View model action
buttonUsage =
  [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
  [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-wrap items-center gap-2" ]
  [ ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps [ View model action
"Primary" ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonVariant = Outline } [ View model action
"Outline" ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonVariant = Ghost } [ View model action
"Ghost" ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonVariant = Destructive }
    [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
sendIcon [], View model action
"Danger" ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = Small, buttonVariant = Secondary }
    [ View model action
"Small" ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = Large } [ View model action
"Large" ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonIcon = True, buttonVariant = Outline }
    [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
arrowRightIcon [] ]
  , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonVariant = Outline, buttonDisabled = True }
    [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
loaderIcon [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"animate-spin" ], View model action
"Loading" ]
  ]
-----------------------------------------------------------------------------
buttonSample :: View model action
buttonSample :: forall model action. View model action
buttonSample =
  [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
  [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-col gap-6" ]
  [ Size -> View model action
forall {model} {action}. Size -> View model action
row Size
DefaultSize, Size -> View model action
forall {model} {action}. Size -> View model action
row Size
Small, Size -> View model action
forall {model} {action}. Size -> View model action
row Size
Large, View model action
forall model action. View model action
icons ]
  where
    row :: Size -> View model action
row Size
size =
      [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
      [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-wrap items-center gap-2 md:flex-row" ]
      [ ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size } [ View model action
"Primary" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Outline } [ View model action
"Outline" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Ghost } [ View model action
"Ghost" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Destructive }
        [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
sendIcon [], View model action
"Danger" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Secondary } [ View model action
"Secondary" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Link } [ View model action
"Link" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Outline }
        [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
sendIcon [], View model action
"Send" ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Outline }
        [ View model action
"Learn more", [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
arrowRightIcon [] ]
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonSize = size, buttonVariant = Outline, buttonDisabled = True }
        [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
loaderIcon [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"animate-spin" ], View model action
"Loading" ]
      ]
    icons :: View model action
icons =
      [Attribute action] -> [View model action] -> View model action
forall action model.
[Attribute action] -> [View model action] -> View model action
H.div_
      [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"flex flex-wrap items-center gap-2 md:flex-row" ]
      [ Variant -> View model action -> View model action
forall {model} {action}.
Variant -> View model action -> View model action
iconButton Variant
Primary ([Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
downloadIcon [])
      , Variant -> View model action -> View model action
forall {model} {action}.
Variant -> View model action -> View model action
iconButton Variant
Secondary ([Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
uploadIcon [])
      , Variant -> View model action -> View model action
forall {model} {action}.
Variant -> View model action -> View model action
iconButton Variant
Outline ([Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
arrowRightIcon [])
      , Variant -> View model action -> View model action
forall {model} {action}.
Variant -> View model action -> View model action
iconButton Variant
Ghost ([Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
dotsIcon [])
      , Variant -> View model action -> View model action
forall {model} {action}.
Variant -> View model action -> View model action
iconButton Variant
Destructive ([Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
trashIcon [])
      , ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps
          { buttonIcon = True
          , buttonVariant = Outline
          , buttonDisabled = True
          }
          [ [Attribute action] -> View model action
forall action model. [Attribute action] -> View model action
loaderIcon [ MisoString -> Attribute action
forall action. MisoString -> Attribute action
P.class_ MisoString
"animate-spin" ] ]
      ]
    iconButton :: Variant -> View model action -> View model action
iconButton Variant
v View model action
icon =
      ButtonProps action -> [View model action] -> View model action
forall action model.
ButtonProps action -> [View model action] -> View model action
button_ ButtonProps action
forall action. ButtonProps action
defaultButtonProps { buttonIcon = True, buttonVariant = v } [ View model action
icon ]
-----------------------------------------------------------------------------
buttonCodeSample :: View model action
buttonCodeSample :: forall model action. View model action
buttonCodeSample =
  View model action
"""
  -----------------------------------------------------------------------------
  module MyButton (buttonUsage) where
  -----------------------------------------------------------------------------
  import           Miso
  import qualified Miso.Html.Element as H
  import qualified Miso.Html.Property as P
  import qualified Miso.String as MS
  import           Miso.UI.Types
  import           Miso.UI.Icons
  import           Miso.UI.Button
  -----------------------------------------------------------------------------
  buttonUsage :: View model action
  buttonUsage =
    H.div_
    [ P.class_ "flex flex-wrap items-center gap-2" ]
    [ button_ defaultButtonProps [ "Primary" ]
    , button_ defaultButtonProps { buttonVariant = Outline } [ "Outline" ]
    , button_ defaultButtonProps { buttonVariant = Ghost } [ "Ghost" ]
    , button_ defaultButtonProps { buttonVariant = Destructive }
      [ sendIcon [], "Danger" ]
    , button_ defaultButtonProps { buttonSize = Small, buttonVariant = Secondary }
      [ "Small" ]
    , button_ defaultButtonProps { buttonSize = Large } [ "Large" ]
    , button_ defaultButtonProps { buttonIcon = True, buttonVariant = Outline }
      [ arrowRightIcon [] ]
    , button_ defaultButtonProps { buttonVariant = Outline, buttonDisabled = True }
      [ loaderIcon [ P.class_ "animate-spin" ], "Loading" ]
    ]
  """
-----------------------------------------------------------------------------
buttonPropsApi :: View model action
buttonPropsApi :: forall model action. View model action
buttonPropsApi =
  View model action
"""
  -- | Props for 'button'
  data ButtonProps action
    = ButtonProps
    { buttonVariant :: Variant
      -- ^ 'Primary', 'Secondary', 'Destructive', 'Outline', 'Ghost' or 'Link'
    , buttonSize :: Size
      -- ^ 'DefaultSize', 'Small' or 'Large'
    , buttonIcon :: Bool
      -- ^ Square icon-only button (e.g. @btn-icon-outline@)
    , buttonDisabled :: Bool
    , buttonClasses :: [MisoString]
      -- ^ Extra classes appended to the computed basecoat class
    , buttonAttrs :: [Attribute action]
      -- ^ Extra attributes (e.g. @onClick@)
    }
  -----------------------------------------------------------------------------
  -- | Smart constructor: primary variant, default size
  defaultButtonProps :: ButtonProps action
  defaultButtonProps
    = ButtonProps
    { buttonVariant = Primary
    , buttonSize = DefaultSize
    , buttonIcon = False
    , buttonDisabled = False
    , buttonClasses = []
    , buttonAttrs = []
    }
  """
-----------------------------------------------------------------------------