helloWorld :: View context ()
helloWorld =
el "Hello World"
>>> renderText helloWorld
"<div>Hello World</div>"
We can factor
Views into reusable functions:
messageView :: Text -> View context ()
messageView msg =
el $ text msg
page :: Page es '[]
page = do
pure $ messageView "Hello World"
Hello World
Using
atomic-css we can use functions to factor styles as well
Let's get interactive! Using
Hyperbole, we divide our
Page into independent live subsections called
HyperViews
To start, define a data type that uniquely identifies an interactive section of the page. Make it an instance of
ViewId. We will call this datatype a
ViewId
data Message = Message1 | Message2
deriving (Generic, ViewId)
-
Create an
Action type with a constructor for every possible way that the user can interact with it
-
instance HyperView Message es where
data Action Message
= Louder Text
deriving (Generic, ViewAction)
update (Louder msg) = do
let new = msg <> "!"
pure $ messageView new
Choose where the new
HyperView will appear on the page using the
hyper function, and add the
ViewId type to the type-level list of
Page
page :: Page es '[Message]
page = do
pure $ do
el "Unchanging Header"
hyper Message1 $ messageView "Hello"
hyper Message2 $ messageView "World"
Finally, let's create a
View with a button that triggers our
Action. Instead of using a generic
context in the
View type signature, we must set it to our
ViewId. The compiler will tell us if we try to trigger actions that don't belong to our
HyperView instance
messageView :: Text -> View Message ()
messageView msg = do
button (Louder msg) ~ border 1 $ text msg
When the user clicks the button, the contents of
hyper will be replaced with the result of
update, leaving the rest of the page untouched.