We've seen button in quite a few examples. Hyperbole provides a few other high-level inputs to easily tie interactivity to an Action, such as search, dropdown, and option
data Planet
  = Mercury
  | Venus
  | Earth
  | Mars
  deriving (Generic, FromParam, ToParam, Eq, Show, Enum, Bounded)

selectPlanet :: Maybe Planet -> View Dropper ()
selectPlanet mp = do
  dropdown Select mp ~ border 1 . pad 10 $ do
    option Nothing "Choose a Planet"
    option (Just Mercury) "Mercury"
    option (Just Venus) "Venus"
    option (Just Earth) "Earth"
    option (Just Mars) "Mars"
  case mp of
    Nothing -> none
    Just p -> el $ text $ "You chose: " <> pack (show p)
For a more in-depth example see Filter
Hyperbole provides various events that can be tied to specific Actions. Up to this point, we've only used them via the higher-level Views like button and dropdown . There are also events like onClick, onKeyDown, and onInput which can be used directly
viewEvents :: Text -> View TryEvents ()
viewEvents t = do
  el ~ bold $ text t
  input @ onInput SetMessage 250 ~ border 1 . pad 5 $ none
  button @ onDblClick (SetMessage "") ~ btn $ "Double Click to Clear"
 where
  input = tag "input"
  button = tag "button"
The following example demonstrates using onMouseEnter and onMouseLeave
Remember it is better to use Atomic CSS to provide immediate feedback whenever possible. If used improperly, too many mouse events could make the app unresponsive
viewBoxes :: Maybe Int -> View Boxes ()
viewBoxes mn = do
  boxes mn $ \n -> do
    el ~ box @ onMouseEnter (SelectBox n) . onMouseLeave ClearBox $ text $ pack $ show n
For a more in-depth example see Autocomplete
Include custom js on a page with the script tag on only the page where it is needed, or globally via your docuemnt function
page :: (Hyperbole :> es) => Page es '[JBoxes, Message]
page = do
  pure $ do
    script "custom.js"
    hyper JBoxes $ viewJBoxes Nothing
    hyper Message viewMessage
let boxes = Hyperbole.hyperView("JBoxes")
console.log("Found HyperView 'Boxes'")

boxes.addEventListener("mouseover", function(e) {
  if (e.target.classList.contains("box")) {
    let action = Hyperbole.action("Selected", parseInt(e.target.innerHTML))
    boxes.runAction(action)
  }
})
boxes.addEventListener("mouseout", function(e) {
  if (e.target.classList.contains("box")) {
    boxes.runAction("Clear")
  }
})
RunAction
JS can call the server with an API attached to window.Hyperbole. Here we re-implement mouseover boxes from the events example using Javascript
PushEvent
The server can push an event to be dispatched on a HyperView
  update AlertMe = do
    pushEvent "server-message" ("hello" :: Text)
    pure "Sent 'server-message' event"
function listenServerEvents() {
  // you can listen on document instead, the event will bubble
  Hyperbole.hyperView("Message").addEventListener("server-message", function(e) {
    alert("Server Message: " + e.detail)
  })
}