diff --git a/bulmex.cabal b/bulmex.cabal
--- a/bulmex.cabal
+++ b/bulmex.cabal
@@ -4,12 +4,12 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: d67294831c6d62f3268fe8a5d7abc24d2271686c6842d096537e2fdda8d7a170
+-- hash: 437fddec128f807a107380e8703fad0e32c13b707a2252431b9ac45157b6de50
 
 name:           bulmex
-version:        2.1.0
+version:        3.0.0
 synopsis:       Reflex infused with bulma (css)
-description:    Reflex infused with bulma, With a bunch of helper functions for making server side rendering easier. See related [blogpost](https://jappieklooster.nl/reflex-server-side-html-rendering.html).
+description:    Reflex infused with bulma, [Implements](https://hackage.haskell.org/package/bulmex/docs/Reflex-Bulmex-Modal.html) the [modal](https://bulma.io/documentation/components/modal/) for example. Also has helper functions for common tasks. such as making server side rendering easier. See related [blogpost](https://jappieklooster.nl/reflex-server-side-html-rendering.html).
 category:       Web
 homepage:       https://github.com/jappeace/bulmex#readme
 bug-reports:    https://github.com/jappeace/bulmex/issues
@@ -35,6 +35,7 @@
       Reflex.Bulmex.Form.FormTypes
       Reflex.Bulmex.Html
       Reflex.Bulmex.Input.Basic
+      Reflex.Bulmex.Input.Debounce
       Reflex.Bulmex.Input.Polymorphic
       Reflex.Bulmex.Load
       Reflex.Bulmex.Modal
@@ -81,6 +82,7 @@
       Reflex.Bulmex.Form.FormTypes
       Reflex.Bulmex.Html
       Reflex.Bulmex.Input.Basic
+      Reflex.Bulmex.Input.Debounce
       Reflex.Bulmex.Input.Polymorphic
       Reflex.Bulmex.Load
       Reflex.Bulmex.Modal
diff --git a/src/Reflex/Bulmex/Event.hs b/src/Reflex/Bulmex/Event.hs
--- a/src/Reflex/Bulmex/Event.hs
+++ b/src/Reflex/Bulmex/Event.hs
@@ -3,7 +3,24 @@
 {-# LANGUAGE RankNTypes        #-}
 
 -- | Helper functions for dealing with events
-module Reflex.Bulmex.Event where
+module Reflex.Bulmex.Event
+  ( eventJoin
+  , switchTup
+  -- * Hold
+  , holdEvent
+  , holdEvent_
+  , holdAfter
+  -- * Flash
+  , flash
+  , flash'
+  -- * Display
+  , evtText
+  -- * Gate
+  , noNothing
+  , gatePrism
+  , blockFalse
+  )
+  where
 
 import           Control.Applicative      (empty)
 import           Control.Lens
diff --git a/src/Reflex/Bulmex/Form.hs b/src/Reflex/Bulmex/Form.hs
--- a/src/Reflex/Bulmex/Form.hs
+++ b/src/Reflex/Bulmex/Form.hs
@@ -10,8 +10,8 @@
   ( actionForm
   , form
   -- * Spin
-  , withSpinDyn
   , spinWidget
+  , withSpinDyn
   , aSpinButtonClass
   , loadAttr
   -- * Types
@@ -33,13 +33,27 @@
 import qualified Reflex.Tags                  as T
 import qualified Web.KeyCode                  as Dom
 
--- | This will make send on enter work for a form.
---   Gives a spinstate to a form and hooks up onenter press to it
---   use actReqButton for sane defaults
+-- | This function mimics an arbitrary html form in control flow.
+--   The first argument is the action function with arbitrary input a
+--   and a trigger event.
+--   This returns another event in a monadic context.
+--
+--   > action="(a -> Event t () -> m (Event t b))"
+--
+--   This perfectly aligns with servant-reflex.
+--   The produced event is given to the form, the second argument.
+--   which is the form body:
+--
+--   > <form>(Event t b -> Dynamic t FormState -> m (a, Event t FormAction, c))</form>
+--
+--   and also includes the 'FormState',
+--   indicating if we're executing the action or not.
+--   The form has to return 3 values, the information for the action function,
+--   The 'FormAction' event that controls the form, and the third is a return value for the form.
 actionForm ::
      (Dom.DomBuilder t m, MonadHold t m, MonadFix m)
-  => (a -> Event t () -> m (Event t b))
-  -> (Event t b -> Dynamic t SpinState -> m (a, Event t FormAction, c))
+  => (a -> Event t () -> m (Event t b)) -- ^ Action function
+  -> (Event t b -> Dynamic t FormState -> m (a, Event t FormAction, c)) -- ^ form body
   -> m c
 actionForm actF monM =
   form $ \onEnter -> do
@@ -59,11 +73,14 @@
      (Reflex t, MonadHold t m, MonadFix m)
   => Event t ()
   -> Event t ()
-  -> m (Dynamic t SpinState)
+  -> m (Dynamic t FormState)
 spinState start stop =
-  accumDyn (const id) SpinRest $ leftmost [Spinning <$ start, SpinRest <$ stop]
+  accumDyn (const id) FormStateRest $ leftmost [FormStateSpinning <$ start, FormStateRest <$ stop]
 
--- | This looks a lot like `withDebounceEvtReq`, maybe a better abstraction is possible?
+-- This looks a lot like `withDebounceEvtReq`, maybe a better abstraction is possible?
+-- | A more general use of the spinstate.
+--   The first argument is the widget that can indicate when to execute
+--   the second function. It will be made aware of the 'FormState'.
 spinWidget ::
      ( Dom.DomBuilder t m
      , PerformEvent t m
@@ -72,8 +89,8 @@
      , MonadHold t m
      , MonadFix m
      )
-  => (Dynamic t SpinState -> m (Event t ()))
-  -> (Event t () -> m (Event t b))
+  => (Dynamic t FormState -> m (Event t ())) -- ^ Widget body
+  -> (Event t () -> m (Event t b)) -- ^ Trigger function
   -> m (Event t b)
 spinWidget widgetF eventHandlr = do
   rec onClick <- widgetF dynamicClass
@@ -83,9 +100,9 @@
       dynamicClass <- spinState onClick $ setClassOnReq <> setClassafterReq
   pure onRequest
 
-loadAttr :: SpinState -> AttrMap
-loadAttr SpinRest = mempty
-loadAttr Spinning = Map.fromList [("class", "is-loading"), ("disabled", "1")]
+loadAttr :: FormState -> AttrMap
+loadAttr FormStateRest = mempty
+loadAttr FormStateSpinning = Map.fromList [("class", "is-loading"), ("disabled", "1")]
 
 withSpinDyn -- XXX only used once? maybe remove
  ::
@@ -106,7 +123,7 @@
 aSpinButtonClass ::
      (Dom.DomBuilder t m, PostBuild t m)
   => Text.Text
-  -> Dynamic t SpinState
+  -> Dynamic t FormState
   -> m ()
   -> m (Event t ())
 aSpinButtonClass clazz spinstate =
@@ -115,7 +132,7 @@
 
 -- attrmap
 -- | A form captures enter presses of child componetns and
---   sends it to them
+--   sends it to them in an event.
 form :: (Dom.DomBuilder t m, MonadFix m) => (Event t () -> m a) -> m a
 form monF = do
   rec val <-
diff --git a/src/Reflex/Bulmex/Form/FormTypes.hs b/src/Reflex/Bulmex/Form/FormTypes.hs
--- a/src/Reflex/Bulmex/Form/FormTypes.hs
+++ b/src/Reflex/Bulmex/Form/FormTypes.hs
@@ -5,7 +5,7 @@
 -- | Types for Form.
 module Reflex.Bulmex.Form.FormTypes
   ( FormAction(..)
-  , SpinState(..)
+  , FormState(..)
   -- * Prisms
   , _PostDefault
   , _Loading
@@ -31,14 +31,14 @@
 _FormRest :: Prism' FormAction ()
 _FormRest = _Ctor @"FormRest"
 
-data SpinState -- TODO rename to load state?
-  = SpinRest
-  | Spinning
+data FormState
+  = FormStateRest
+  | FormStateSpinning
   deriving (Show)
 
-instance Semigroup SpinState where
-  (<>) SpinRest SpinRest = SpinRest
-  (<>) _ _               = Spinning
+instance Semigroup FormState where
+  (<>) FormStateRest FormStateRest = FormStateRest
+  (<>) _ _                         = FormStateSpinning
 
-instance Monoid SpinState where
-  mempty = SpinRest
+instance Monoid FormState where
+  mempty = FormStateRest
diff --git a/src/Reflex/Bulmex/Html.hs b/src/Reflex/Bulmex/Html.hs
--- a/src/Reflex/Bulmex/Html.hs
+++ b/src/Reflex/Bulmex/Html.hs
@@ -137,6 +137,7 @@
     traversed .
     to (Text.pack . show)
 
+-- TODO Move to Load
 -- | Insert an encodable in the document body,
 --   in case of the server side rendering we encode it as script tag with jsonval,
 --   in case of ghcjsdom we read the value from that script tag
diff --git a/src/Reflex/Bulmex/Input/Basic.hs b/src/Reflex/Bulmex/Input/Basic.hs
--- a/src/Reflex/Bulmex/Input/Basic.hs
+++ b/src/Reflex/Bulmex/Input/Basic.hs
@@ -5,13 +5,14 @@
 
 -- | Basic inputs with bulma styling
 module Reflex.Bulmex.Input.Basic
-  ( abuttonClass
+  ( abutton
+  , abuttonClass
   , abuttonLarge
-  , txtInput
-  , abutton
-  , buttonClassAttr
   , abuttonDynAttr
+  , buttonClassAttr
+  -- * Text inputs
   , txtArea
+  , txtInput
   ) where
 
 import           Control.Lens
@@ -56,6 +57,11 @@
   -> m (Event t (), a)
 abuttonClass = abutton . classAttr
 
+-- | A button around an arbitrary dom element:
+--
+--   > <button> m a </button>
+--
+--   It's also styled nicely.
 abutton ::
      (PostBuild t m, Dom.DomBuilder t m) => AttrMap -> m a -> m (Event t (), a)
 abutton = abuttonDynAttr . constDyn
diff --git a/src/Reflex/Bulmex/Input/Debounce.hs b/src/Reflex/Bulmex/Input/Debounce.hs
new file mode 100644
--- /dev/null
+++ b/src/Reflex/Bulmex/Input/Debounce.hs
@@ -0,0 +1,88 @@
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecursiveDo       #-}
+{-# LANGUAGE TypeFamilies      #-}
+
+-- | This makes it easy to create auto-save operations
+--   not limited to saves.
+module Reflex.Bulmex.Input.Debounce
+  ( InputStates(..)
+  , defStateAttr
+  , withInputDebounceEvt
+  , withInput
+  )
+where
+
+import           Control.Monad.Fix
+import           Control.Monad.IO.Class (MonadIO)
+import qualified Data.Text              as Text
+import           Data.Time
+import           Reflex
+import           Reflex.Bulmex.Event
+
+-- | Allows widgets to react according with what's happening
+data InputStates
+  = InputStarted
+  | InputBuffered
+  | InputProcessed
+  | InputAborted
+  | InputInitial
+
+-- | do a debounced action, create a widget with the dynamic inputstates
+--  that indicates the state of doing the action
+--  This allows you to automatically request the server once user is
+--  finished with typing for example,
+--   while not flooding the server with requests trough debouncing
+withInputDebounceEvt
+  :: ( PostBuild t m
+     , MonadFix m
+     , MonadHold t m
+     , TriggerEvent t m
+     , MonadIO (Performable m)
+     , PerformEvent t m
+     )
+  => NominalDiffTime -- ^ Delay before posting the request
+  -> (result -> Bool) -- ^ Was the final requess successfull?
+  -> (Dynamic t InputStates -> m (b, Event t inputEvt)) -- ^ Widget body reacting to states
+  -> (b -> Event t inputEvt -> m (Event t result)) -- ^ Action function
+  -> m (Event t result, b)
+withInputDebounceEvt debtime succF stateF =
+  withInput (debounce debtime) succF
+    $ const
+    $ fmap (\(one', two) -> (one', two, one'))
+    . stateF
+
+-- | Maps input state to bulmex classes: InputStarted = is-warning for example
+defStateAttr :: InputStates -> Text.Text
+defStateAttr InputStarted   = "is-warning"
+defStateAttr InputBuffered  = "is-warning" -- is-loading
+defStateAttr InputProcessed = "is-success"
+defStateAttr InputAborted   = "is-danger"
+defStateAttr InputInitial   = ""
+
+-- | A general debounce widget
+--  This looks a lot like 'actionForm', but it's not the same because
+--  form allows user code to decide what
+withInput
+  :: (PostBuild t m, MonadFix m, MonadHold t m)
+  => (Event t inputEvt -> m (Event t inputEvt)) -- ^ change input timeline, eg pure for no change
+  -> (result -> Bool) -- ^ Was the final requess successfull?
+  -> (  Event t result
+     -> Dynamic t InputStates
+     -> m (actArgs, Event t inputEvt, finalRes)
+     ) -- ^ Widget body reacting to states
+  -> (actArgs -> Event t inputEvt -> m (Event t result)) -- ^ Action function
+  -> m (Event t result, finalRes)
+withInput timeF isSuccessF createTypeEvt reqFunc = mdo
+  (someData, typeEvtImmediate, result) <- createTypeEvt postFinished areaState
+  typeEvtDeb                           <- timeF typeEvtImmediate
+  postFinished                         <- reqFunc someData typeEvtDeb
+  areaState                            <-
+    holdDyn InputInitial
+    $ leftmost
+    $ [ InputStarted <$ typeEvtImmediate
+      , InputBuffered <$ typeEvtDeb
+      , InputProcessed <$ (blockFalse $ isSuccessF <$> postFinished)
+      , InputAborted <$ (blockFalse $ not . isSuccessF <$> postFinished)
+      ]
+  pure (postFinished, result)
diff --git a/src/Reflex/Bulmex/Load.hs b/src/Reflex/Bulmex/Load.hs
--- a/src/Reflex/Bulmex/Load.hs
+++ b/src/Reflex/Bulmex/Load.hs
@@ -2,8 +2,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecursiveDo       #-}
 
--- | Bulma loading screen w/ help of extension:
---   https://wikiki.github.io/elements/pageloader/
+-- | Load time manipulation
 module Reflex.Bulmex.Load
   ( pageLoader
   , prerenderLoad
@@ -24,10 +23,12 @@
 import qualified Reflex.Dom.Widget.Basic    as Dom
 import qualified Reflex.Tags                as T
 
+-- | Bulma loading screen with help of extension:
+--   https://wikiki.github.io/elements/pageloader/
 pageLoader :: DomBuilder t m => Text.Text -> m a -> m a
 pageLoader = partialDiv "pageloader"
 
--- | show a spinning image while loading JS
+-- | show input monad while JS is loading, for example a spinning image
 prerenderLoad :: (Prerender js t m, DomBuilder t m) => m () -> m ()
 prerenderLoad spinner =
   void $ prerender (T.divClass "prerender-load" $ spinner) Dom.blank
diff --git a/src/Reflex/Bulmex/Modal.hs b/src/Reflex/Bulmex/Modal.hs
--- a/src/Reflex/Bulmex/Modal.hs
+++ b/src/Reflex/Bulmex/Modal.hs
@@ -5,9 +5,9 @@
 --   Puts code behinds bulma's modal styling: https://bulma.io/documentation/components/modal/
 module Reflex.Bulmex.Modal
   ( modal
-  , OnClose
   , modal'
   , modalClose
+  , OnClose
   ) where
 
 import           Control.Lens
@@ -18,34 +18,36 @@
 import qualified Reflex.Dom.Widget.Basic  as Dom
 import qualified Reflex.Tags              as T
 
-data OnClose =
-  OnClose
 
 -- | A modal that opens on event and has a cross to close it.
+--   m a dictates what's inside the modal.
+--   You probably want to use a 'Reflex.Bulmex.Tag.Bulma.box'.
 modal ::
      (PostBuild t m, MonadHold t m, MonadFix m, Dom.DomBuilder t m)
-  => Event t ()
-  -> m a
+  => Event t () -- ^ open trigger
+  -> m a -- ^ modal body
   -> m (a, Event t OnClose)
 modal = modal' never
 
 -- | A modal that can be opened and closed with events.
---   Also has a cross to close it.
+--   It also has a cross to close with.
 modal' ::
      (PostBuild t m, MonadHold t m, MonadFix m, Dom.DomBuilder t m)
-  => Event t ()
-  -> Event t ()
-  -> m a
+  => Event t () -- ^ close trigger
+  -> Event t () -- ^ open trigger
+  -> m a -- ^ modal body
   -> m (a, Event t OnClose)
 modal' closeEvt openEvt monad =
   modalClose openEvt $ do
     res <- monad
     pure (res, closeEvt)
 
+-- | The most generic modal, It receives an open event.
+--   And the inner monad can indicate when to close with a closeEvent.
 modalClose ::
      (PostBuild t m, MonadHold t m, MonadFix m, Dom.DomBuilder t m)
-  => Event t ()
-  -> m (a, Event t ())
+  => Event t () -- ^ open trigger
+  -> m (a, Event t ()) -- ^ body + close trigger result
   -> m (a, Event t OnClose)
 modalClose openEvt monad = do
   rec stateDyn <-
@@ -68,3 +70,7 @@
   where
     closed = classAttr "modal"
     opened = classAttr "modal is-active"
+
+-- | An incation that an event came from closing a modal
+data OnClose =
+  OnClose
diff --git a/src/Reflex/Bulmex/Tag/Hide.hs b/src/Reflex/Bulmex/Tag/Hide.hs
--- a/src/Reflex/Bulmex/Tag/Hide.hs
+++ b/src/Reflex/Bulmex/Tag/Hide.hs
@@ -13,6 +13,7 @@
 import qualified Reflex.Dom.Builder.Class as Dom
 import qualified Reflex.Tags              as T
 
+-- | When the dynamic is true the first monad is shown, otherwise the second.
 switchDiv ::
      (PostBuild t m, Dom.DomBuilder t m) => Dynamic t Bool -> m () -> m a -> m a
 switchDiv attrDyn true false = do
