Skip to contents

Lists are continuous, vertical indexes of text or images. They are composed of items containing primary and supplemental actions, which are represented by icons and text.

Basic list

A simple list with text items:

muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper"),
    List(
      ListItem(
        ListItemButton(
          ListItemIcon(shiny::icon("inbox")),
          ListItemText(primary = "Inbox")
        )
      ),
      ListItem(
        ListItemButton(
          ListItemIcon(shiny::icon("paper-plane")),
          ListItemText(primary = "Drafts")
        )
      )
    )
  )
)

Nested list

A list with nested items and collapsible sections:

library(shiny)
library(muiMaterial)

muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper"),
    List(
      component = "nav",
      ListItemButton(
        ListItemIcon(shiny::icon("home")),
        ListItemText(primary = "Home")
      ),
      ListItemButton(
        ListItemIcon(shiny::icon("envelope")),
        ListItemText(primary = "Inbox"),
        shiny::icon("chevron-down"),
        onClick = JS("() => {
            const el = document.getElementById('inbox-collapse');
            if (el) {
              el.style.display = el.style.display === 'none' ? 'block' : 'none';
            }
          }")
      ),
      Collapse(
        `in` = TRUE,
        timeout = "auto",
        unmountOnExit = TRUE,
        id = "inbox-collapse",
        List(
          component = "div",
          disablePadding = TRUE,
          ListItemButton(
            sx = list(pl = 4),
            ListItemIcon(shiny::icon("star")),
            ListItemText(primary = "Starred")
          ),
          ListItemButton(
            sx = list(pl = 4),
            ListItemIcon(shiny::icon("clock")),
            ListItemText(primary = "Snoozed")
          )
        )
      ),
      ListItemButton(
        ListItemIcon(shiny::icon("paper-plane")),
        ListItemText(primary = "Drafts")
      )
    )
  )
)

List with dividers

Use Divider() to separate list items:

muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper"),
    List(
      component = "nav",
      ListItem(
        ListItemButton(
          ListItemIcon(shiny::icon("inbox")),
          ListItemText(primary = "Inbox")
        )
      ),
      Divider(),
      ListItem(
        ListItemButton(
          ListItemIcon(shiny::icon("paper-plane")),
          ListItemText(primary = "Drafts")
        )
      ),
      Divider(),
      ListItem(
        ListItemButton(
          ListItemIcon(shiny::icon("trash")),
          ListItemText(primary = "Trash")
        )
      )
    )
  )
)

List with avatars

Combine lists with Avatar() components:

muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper"),
    List(
      ListItem(
        ListItemAvatar(
          Avatar(
            alt = "Remy Sharp",
            src = "https://mui.com/static/images/avatar/1.jpg"
          )
        ),
        ListItemText(
          primary = "Remy Sharp",
          secondary = "Available for chat"
        )
      ),
      ListItem(
        ListItemAvatar(
          Avatar(
            alt = "Travis Howard",
            src = "https://mui.com/static/images/avatar/2.jpg"
          )
        ),
        ListItemText(
          primary = "Travis Howard",
          secondary = "Busy - Do not disturb"
        )
      ),
      ListItem(
        ListItemAvatar(
          Avatar(
            alt = "Cindy Baker",
            src = "https://mui.com/static/images/avatar/3.jpg"
          )
        ),
        ListItemText(
          primary = "Cindy Baker",
          secondary = "Away"
        )
      )
    )
  )
)

List with secondary action

Add secondary actions to list items using ListItemSecondaryAction():

muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper"),
    List(
      ListItem(
        secondaryAction = IconButton(
          edge = "end",
          shiny::icon("comment")
        ),
        ListItemAvatar(
          Avatar(
            alt = "Remy Sharp",
            src = "https://mui.com/static/images/avatar/1.jpg"
          )
        ),
        ListItemText(
          primary = "Remy Sharp",
          secondary = "Jan 9, 2024"
        )
      ),
      ListItem(
        secondaryAction = IconButton(
          edge = "end",
          shiny::icon("comment")
        ),
        ListItemAvatar(
          Avatar(
            alt = "Travis Howard",
            src = "https://mui.com/static/images/avatar/2.jpg"
          )
        ),
        ListItemText(
          primary = "Travis Howard",
          secondary = "Jan 7, 2024"
        )
      )
    )
  )
)

Interactive list with reactRouter

Create an interactive navigation list with reactRouter R package:

library(muiMaterial)
library(reactRouter)
#> 
#> Attaching package: 'reactRouter'
#> The following object is masked from 'package:muiMaterial':
#> 
#>     Link

muiMaterialPage(
  CssBaseline(),
  HashRouter(
      Box(
      sx = list(display = "flex", height = "100vh"),
      Box(
          sx = list(width = 240, bgcolor = "background.paper", borderRight = "1px solid #e0e0e0"),
          List(
              component = "nav",
              NavLink(
                  to = "/",
                  style = "text-decoration: none; color: black",
                  ListItemButton(
                      ListItemIcon(shiny::icon("home")),
                      ListItemText(primary = "Home")
                  )
              ),
              NavLink(
                  to = "/inbox",
                  style = "text-decoration: none; color: black",
                  ListItemButton(
                      onClick = Navigate("/inbox"),
                      ListItemIcon(shiny::icon("inbox")),
                      ListItemText(primary = "Inbox")
                  )
              ),
              NavLink(
                  to = "/starred",
                  style = "text-decoration: none; color: black",
                  ListItemButton(
                      onClick = Navigate("/starred"),
                      ListItemIcon(shiny::icon("star")),
                      ListItemText(primary = "Starred")
                  )
              ),
              NavLink(
                  to = "/drafts",
                  style = "text-decoration: none; color: black",
                  ListItemButton(
                      ListItemIcon(shiny::icon("paper-plane")),
                      ListItemText(primary = "Drafts")
                  )
              )
          )
      ),
      Box(
          sx = list(flex = 1, p = 3),
          Routes(
          Route(
              path = "/",
              element = Typography("Home Page", variant = "h4")
          ),
          Route(
              path = "/inbox",
              element = Typography("Inbox", variant = "h4")
          ),
          Route(
              path = "/starred",
              element = Typography("Starred", variant = "h4")
          ),
          Route(
              path = "/drafts",
              element = Typography("Drafts", variant = "h4")
          )
          )
      )
      )
  )
)

Selectable list

Create a list with selectable items:

library(shiny)
library(muiMaterial)

ui <- muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper", p = 2),
    Typography("Select items:", variant = "h6", sx = list(mb = 2)),
    uiOutput("selectable_list"),
    Typography(
      uiOutput("selected_message"),
      variant = "body2",
      sx = list(mt = 2)
    )
  )
)

server <- function(input, output, session) {
  items <- c("Photos", "Work", "Vacation")
  selected <- reactiveVal(character(0))
  
  output$selectable_list <- renderUI({
    List(
      lapply(items, function(item) {
        is_selected <- item %in% selected()
        ListItem(
          disablePadding = TRUE,
          ListItemButton(
            selected = is_selected,
            onClick = JS(sprintf(
              "() => Shiny.setInputValue('toggle_item', {item: '%s', time: Math.random()})",
              item
            )),
            ListItemIcon(shiny::icon("folder")),
            ListItemText(primary = item)
          )
        )
      })
    )
  })
  
  observeEvent(input$toggle_item, {
    item <- input$toggle_item$item
    if (item %in% selected()) {
      selected(setdiff(selected(), item))
    } else {
      selected(c(selected(), item))
    }
  })
  
  output$selected_message <- renderUI({
    if (length(selected()) == 0) {
      "No items selected"
    } else {
      paste("Selected:", paste(selected(), collapse = ", "))
    }
  })
}

shinyApp(ui, server)

List with checkboxes

Add checkboxes to list items for multiple selection:

library(shiny)
library(muiMaterial)

ui <- muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper", p = 2),
    Typography("To-do list:", variant = "h6", sx = list(mb = 2)),
    uiOutput("checkbox_list")
  )
)

server <- function(input, output, session) {
  todos <- reactiveVal(list(
    list(id = "1", text = "Buy groceries", checked = FALSE),
    list(id = "2", text = "Walk the dog", checked = FALSE),
    list(id = "3", text = "Finish report", checked = FALSE),
    list(id = "4", text = "Call mom", checked = FALSE)
  ))
  
  output$checkbox_list <- renderUI({
    List(
      lapply(todos(), function(todo) {
        ListItem(
          disablePadding = TRUE,
          ListItemButton(
            role = "undefined",
            onClick = JS(sprintf(
              "() => Shiny.setInputValue('toggle_todo', {id: '%s', time: Math.random()})",
              todo$id
            )),
            dense = TRUE,
            ListItemIcon(
              Checkbox(
                edge = "start",
                checked = todo$checked,
                tabIndex = -1,
                disableRipple = TRUE
              )
            ),
            ListItemText(
              primary = todo$text,
              sx = if (todo$checked) list(textDecoration = "line-through") else NULL
            )
          )
        )
      })
    )
  })
  
  observeEvent(input$toggle_todo, {
    todo_id <- input$toggle_todo$id
    current <- todos()
    updated <- lapply(current, function(t) {
      if (t$id == todo_id) {
        t$checked <- !t$checked
      }
      t
    })
    todos(updated)
  })
}

shinyApp(ui, server)

List with switches

Add switches to list items for settings-style lists:

library(shiny)
library(muiMaterial)

ui <- muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper", p = 2),
    Typography("Notifications:", variant = "h6", sx = list(mb = 2)),
    uiOutput("settings_list")
  )
)

server <- function(input, output, session) {
  settings <- reactiveVal(list(
    list(id = "wifi", label = "Wi-Fi", enabled = TRUE),
    list(id = "bluetooth", label = "Bluetooth", enabled = FALSE),
    list(id = "notifications", label = "Notifications", enabled = TRUE)
  ))
  
  output$settings_list <- renderUI({
    List(
      lapply(settings(), function(setting) {
        ListItem(
          ListItemIcon(
            if (setting$id == "wifi") shiny::icon("wifi")
            else if (setting$id == "bluetooth") shiny::icon("bluetooth")
            else shiny::icon("bell")
          ),
          ListItemText(primary = setting$label),
          Switch(
            edge = "end",
            checked = setting$enabled,
            onChange = JS(sprintf(
              "() => Shiny.setInputValue('toggle_setting', {id: '%s', time: Math.random()})",
              setting$id
            ))
          )
        )
      })
    )
  })
  
  observeEvent(input$toggle_setting, {
    setting_id <- input$toggle_setting$id
    current <- settings()
    updated <- lapply(current, function(s) {
      if (s$id == setting_id) {
        s$enabled <- !s$enabled
      }
      s
    })
    settings(updated)
  })
}

shinyApp(ui, server)

Dense list

Use the dense prop for more compact lists:

muiMaterialPage(
  CssBaseline(),
  Box(
    sx = list(width = "100%", maxWidth = 360, bgcolor = "background.paper"),
    List(
      dense = TRUE,
      ListItem(
        ListItemAvatar(
          Avatar(
            alt = "Remy Sharp",
            src = "https://mui.com/static/images/avatar/1.jpg"
          )
        ),
        ListItemText(
          primary = "Remy Sharp",
          secondary = "Software Engineer"
        )
      ),
      ListItem(
        ListItemAvatar(
          Avatar(
            alt = "Travis Howard",
            src = "https://mui.com/static/images/avatar/2.jpg"
          )
        ),
        ListItemText(
          primary = "Travis Howard",
          secondary = "Product Manager"
        )
      ),
      ListItem(
        ListItemAvatar(
          Avatar(
            alt = "Cindy Baker",
            src = "https://mui.com/static/images/avatar/3.jpg"
          )
        ),
        ListItemText(
          primary = "Cindy Baker",
          secondary = "Designer"
        )
      )
    )
  )
)