Skip to contents

Introduction

To use pages with muiMaterial, you might need to use a router service. This document shows examples using the reactRouter and shiny.router R packages.

Examples using {reactRouter}

reactRouter wraps React Router v7. The entry point is RouterProvider(router = ...), where the router is built with createHashRouter(). Routes are declared with nested Route() calls and the active child route is rendered wherever you place Outlet() in the parent’s element. The hash strategy (createHashRouter()) works in Shiny, Quarto and from a local file:// page.

An example using reactRouter client routing (no server):

# install.packages("reactRouter")
library(reactRouter)
library(muiMaterial)
library(shiny)

reactRouter::RouterProvider(
  router = reactRouter::createHashRouter(
    reactRouter::Route(
      path = "/",
      element = Box(
        sx = list(flexGrow = 1),
        AppBar(
          position = "static",
          Toolbar(
            Typography(
              variant = "h6",
              component = "div",
              "muiMaterial"
            ),
            reactRouter::NavLink(
              to = "/",
              style = JS('({isActive}) => { return isActive ? {color: "white"} : {color: "white"}; }'),
              Button(
                color = "inherit",
                "Home"
              )
            ),
            reactRouter::NavLink(
              to = "/analysis",
              style = JS('({isActive}) => { return isActive ? {color: "white"} : {color: "white"}; }'),
              Button(
                color = "inherit",
                "Analysis"
              )
            )
          )
        ),
        Box(
          sx = list(p = 3),
          reactRouter::Outlet()
        )
      ),
      reactRouter::Route(
        index = TRUE,
        element = div(
          tags$h3("Home page"),
          p("A basic example of reactRouter with muiMaterial."),
          p("Content home")
        )
      ),
      reactRouter::Route(
        path = "analysis",
        element = div(
          tags$h3("Analysis"),
          p("Content analysis")
        )
      ),
      reactRouter::Route(path = "*", element = div(tags$p("Error 404")))
    )
  )
)

An example with reactRouter in an R Shiny app (with server). Each route’s element holds a uiOutput() that the server fills with renderUI(); client-side navigation mounts the matched route and Shiny renders its content automatically:

# install.packages("reactRouter")
library(reactRouter)
library(muiMaterial)
library(shiny)

ui <- muiMaterialPage(
  CssBaseline(),
  reactRouter::RouterProvider(
    router = reactRouter::createHashRouter(
      reactRouter::Route(
        path = "/",
        element = div(
          Typography("reactRouter with muiMaterial", variant = "h5", m = 2),
          Stack(
            direction = "row", spacing = 2, p = 2,
            Paper(
              MenuList(
                reactRouter::NavLink(
                  to = "/",
                  style = JS('({isActive}) => { return isActive ? {color: "red", textDecoration:"none"} : { textDecoration: "none" }; }'),
                  MenuItem(
                    "Home"
                  )
                ),
                reactRouter::NavLink(
                  to = "/analysis",
                  style = JS('({isActive}) => { return isActive ? {color: "red", textDecoration: "none"} : { textDecoration: "none" }; }'),
                  MenuItem(
                    "Analysis"
                  )
                ),
                reactRouter::NavLink(
                  to = "/about",
                  style = JS('({ isActive }) => { return isActive ? { color: "red", textDecoration: "none" } : { textDecoration: "none" }; }'),
                  MenuItem(
                    "About"
                  )
                )
              )
            ),
            Box(
              reactRouter::Outlet()
            )
          )
        ),
        reactRouter::Route(
          index = TRUE,
          element = div(
            tags$h1("Home page"),
            tags$h4("A basic example of reactRouter with muiMaterial."),
            uiOutput(outputId = "contentHome")
          )
        ),
        reactRouter::Route(
          path = "analysis",
          element = div(
            tags$h1("Analysis"),
            uiOutput(outputId = "contentAnalysis")
          )
        ),
        reactRouter::Route(
          path = "about",
          element = uiOutput(outputId = "contentAbout")
        ),
        reactRouter::Route(path = "*", element = div(tags$p("Error 404")))
      )
    )
  )
)

server <- function(input, output, session) {

  # Content for Home page
  output$contentHome <- renderUI({
    p("Content home")
  })

  # Content for Analysis page
  output$contentAnalysis <- renderUI({
    p("Content analysis")
  })

  # Content for About page
  output$contentAbout <- renderUI({
    div(
      tags$h1("About"),
      p("Content about")
    )
  })

}

shinyApp(ui, server)

Example using {shiny.router}

Below an example using the shiny.router R package.

Note that using CssBaseline() at top level doesn’t work with shiny.router. CssBaseline() should be used only at the lower level, as showed below.

library(shiny)
library(muiMaterial)
library(shiny.router)

Header <- CssBaseline(
  Box(
    sx = list(flexGrow = 1),
    AppBar(
      position = "static",
      Toolbar(
        IconButton(
          shiny::icon("home"),
          href = route_link("#!/"),
          size = "large",
          edge = "start",
          color = "inherit",
          'aria-label' = "home",
          sx = list(mr = 2)
        ),
        Link(
          "Other",
          href = route_link("#!/other"),
          underline = "none",
          edge = "start",
          color = "inherit",
          'aria-label' = "other",
          sx = list(mr = 2)
        )
      )
    )
  )
)

Main <- CssBaseline(
  Box(
    sx = list(display = "flex", alignItems = "center", p = 2),
    Typography("Main content.")
  )
)

otherPage <- CssBaseline(
  Box(
    sx = list(display = "flex", alignItems = "center", p = 2),
    Typography("Other content.")
  )
)

ui <- muiMaterialPage( # using CssBaseline() here doesn't work with shiny.router
  Header,
  router_ui(
    route("/", Main),
    route("other", otherPage)
  )
)

server <- function(input, output, session) {
  router_server()
}

shinyApp(ui, server)