Typed documentation navigation
Choose a search preset and inspect the encoded destination before navigating.
Both controls receive the same LiveLocationclass LiveLocationAn encoded destination produced by a typed Live route. from the
documentation site's named search route. Push navigation adds a browser-history
entry; replace navigation replaces the current entry.
final class NavigationExample extends LiveView[NavigationExample.Msg, NavigationExample.Model]:
import NavigationExample.*
private val ariaPressed = htmlAttr("aria-pressed", BooleanAsTrueFalseStringEncoder)
def mount(ctx: MountContext): Task[Model] =
ZIO.succeed(Model.initial)
def handleMessage(model: Model, ctx: MessageContext) =
case Msg.Select(query) => ZIO.succeed(Model(query))
case Msg.Reset => ZIO.succeed(Model.initial)
def view(model: Signal[Model]): HtmlElement[Msg] =
val destination = model.map(model => searchLocation(model.query))
div(
cls := "docs-navigation-example",
sectionTag(
cls := "docs-navigation-step docs-navigation-parameters",
dataAttr("example-controls") := "",
headerTag(
span(cls := "docs-navigation-step-number", aria.hidden := true, "01"),
div(
h3("Choose search parameters"),
p("Select a typed value for the route's optional q parameter.")
)
),
div(
cls := "docs-navigation-presets",
aria.label := "Search query presets",
Presets.map(query =>
button(
typ := "button",
cls := "docs-navigation-preset",
dataAttr("navigation-preset") := query.value,
ariaPressed := model.map(_.query == query),
on.click(Msg.Select(query)),
query.label
)
)
)
),
sectionTag(
cls := "docs-navigation-step docs-navigation-result",
headerTag(
span(cls := "docs-navigation-step-number", aria.hidden := true, "02"),
div(
h3("Navigate with a LiveLocation"),
p("One checked destination, two browser-history choices.")
)
),
div(
cls := "docs-navigation-route",
div(
span(cls := "docs-navigation-route-label", "Typed query"),
code(dataAttr("navigation-query") := "", model.map(_.query.value))
),
div(
span(cls := "docs-navigation-route-label", "Encoded destination"),
code(dataAttr("navigation-destination") := "", destination.map(_.href))
)
),
div(
cls := "docs-navigation-actions",
link.pushNavigate(
destination,
cls := "docs-navigation-primary",
dataAttr("push-navigation") := "",
span("Open search"),
small("Push history")
),
link.replaceNavigate(
destination,
cls := "docs-navigation-secondary",
dataAttr("replace-navigation") := "",
span("Open and replace"),
small("Replace history")
),
button(
cls := "docs-navigation-reset",
typ := "button",
on.click(Msg.Reset),
"Reset"
)
)
)
)
end view
end NavigationExample
object NavigationExample:
enum SearchPreset(val label: String, val value: String):
case LiveView extends SearchPreset("LiveView", "LiveView")
case Streams extends SearchPreset("Streams", "streams")
case TypedForms extends SearchPreset("Typed forms", "typed forms")
val Presets = SearchPreset.values.toVector
final case class Model(query: SearchPreset)
object Model:
val initial = Model(SearchPreset.LiveView)
enum Msg:
case Select(query: SearchPreset)
case Reset
private def searchLocation(query: SearchPreset): LiveLocation =
DocumentationApplication.SearchRouteBuilder.location(Some(query.value))View source (documentation/site/src/scalive/docs/examples/NavigationExample.scala:10-117)
Live result
ConnectedReconnectingRead-onlyChoose search parameters
Select a typed value for the route's optional q parameter.
Navigate with a LiveLocation
One checked destination, two browser-history choices.
LiveView/search?q=LiveViewDisconnected. Controls resume after reconnection.
Interaction inspector
See how actions in the live result above travel through typed messages, server state, protocol frames, and DOM updates.
The live result and its inspector resume when the connection returns.
Related guidance: declare typed routes and choose navigation semantics.