Title: Microsoft Fluent UI for Shiny Apps
Version: 0.4.0
Description: A rich set of UI components for building Shiny applications, including inputs, containers, overlays, menus, and various utilities. All components from Fluent UI (the underlying JavaScript library) are available and have usage examples in R.
URL: https://appsilon.github.io/shiny.fluent/, https://github.com/appsilon/shiny.fluent
License: LGPL-3
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.3.1
Depends: R (≥ 2.10)
Imports: htmltools, jsonlite, purrr, shiny, shiny.react (≥ 0.4.0)
Suggests: chromote, covr, dplyr, DT, ggplot2, glue, imola, knitr, leaflet, mockery, plotly, rcmdcheck, RColorBrewer, rmarkdown, sass, shiny.i18n (≥ 0.3.0), shiny.router (≥ 0.3.1), shinyjs, shinytest2, sortable, stringi, testthat (≥ 3.0.0), tibble, withr
Config/testthat/edition: 3
NeedsCompilation: no
Packaged: 2024-05-21 07:47:32 UTC; jakub
Author: Jakub Sobolewski [aut, cre], Kamil Żyła [aut], Marek Rogala [aut], Appsilon Sp. z o.o. [cph]
Maintainer: Jakub Sobolewski <opensource+jakub.sobolewski@appsilon.com>
Repository: CRAN
Date/Publication: 2024-05-21 10:40:02 UTC

Button

Description

Buttons give people a way to trigger an action. They’re typically found in forms, dialog panels, and dialogs. Some buttons are specialized for particular tasks, such as navigation, repeated actions, or presenting menus.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ActionButton(...)

CommandBarButton(...)

CommandButton(...)

CompoundButton(...)

DefaultButton(...)

IconButton(...)

PrimaryButton(...)

ActionButton.shinyInput(inputId, ...)

updateActionButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

CommandBarButton.shinyInput(inputId, ...)

updateCommandBarButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

CommandButton.shinyInput(inputId, ...)

updateCommandButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

CompoundButton.shinyInput(inputId, ...)

updateCompoundButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

DefaultButton.shinyInput(inputId, ...)

updateDefaultButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

IconButton.shinyInput(inputId, ...)

updateIconButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

PrimaryButton.shinyInput(inputId, ...)

updatePrimaryButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

session

Object passed as the session argument to Shiny server.

Details

Besides the compound button, other button types will need more information provided to screen reader.

Note: This increases the time the button will take to mount, but can improve perceived menu open perf. when the user opens the menu.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

# Example 1
library(shiny)
library(shiny.fluent)

tokens <- list(childrenGap = 20)

ui <- function(id) {
  ns <- NS(id)
  tags$div(
    Stack(
      DefaultButton.shinyInput(
        ns("button1"),
        text = "Default Button",
        styles = list("background: green")
      ),
      PrimaryButton.shinyInput(
        ns("button2"),
        text = "Primary Button"
      ),
      CompoundButton.shinyInput(
        ns("button3"),
        secondaryText = "Compound Button has additional text",
        text = "Compound Button"
      ),
      ActionButton.shinyInput(
        ns("button4"),
        iconProps = list("iconName" = "AddFriend"),
        text = "Action Button"
      ),
      horizontal = TRUE,
      tokens = tokens
    ),
    textOutput(ns("text"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    clicks <- reactiveVal(0)
    addClick <- function() { clicks(isolate(clicks() + 1)) }
    observeEvent(input$button0, addClick())
    observeEvent(input$button1, addClick())
    observeEvent(input$button2, addClick())
    observeEvent(input$button3, addClick())
    observeEvent(input$button4, addClick())
    output$text <- renderText({
      paste0("Clicks:", clicks())
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Split button with menu
menuProps <- list(
  items = list(
    list(
      key = "emailMessage",
      text = "Email message",
      onClick = JS("() => alert('Email message clicked')"),
      iconProps = list(
        iconName = "Mail"
      )
    ),
    list(
      key = "calendarEvent",
      text = "Calendar event",
      onClick = JS("() => alert('Calendar event clicked')"),
      iconProps = list(
        iconName = "Calendar"
      )
    )
  )
)

ui <- function(id) {
  ns <- NS(id)
  fluentPage(
    Stack(
      horizontal = TRUE,
      wrap = TRUE,
      tokens = list(
        childrenGap = 40
      ),
      DefaultButton.shinyInput(
        inputId = ns("button_1"),
        text = "Standard",
        primary = FALSE,
        split = TRUE,
        splitButtonAriaLabel = "See 2 options",
        `aria-roledescription` = "split button",
        menuProps = menuProps,
        disabled = FALSE,
        checked = FALSE
      ),
      DefaultButton.shinyInput(
        inputId = ns("button_2"),
        text = "Primary",
        primary = TRUE,
        split = TRUE,
        splitButtonAriaLabel = "See 2 options",
        `aria-roledescription` = "split button",
        menuProps = menuProps,
        disabled = FALSE,
        checked = FALSE
      ),
      DefaultButton.shinyInput(
        inputId = ns("button_3"),
        text = "Main action disabled",
        primaryDisabled = NA,
        split = TRUE,
        splitButtonAriaLabel = "See 2 options",
        `aria-roledescription` = "split button",
        menuProps = menuProps,
        checked = FALSE
      ),
      DefaultButton.shinyInput(
        inputId = ns("button_4"),
        text = "Disabled",
        disabled = TRUE,
        split = TRUE,
        splitButtonAriaLabel = "See 2 options",
        `aria-roledescription` = "split button",
        menuProps = menuProps,
        checked = FALSE
      )
    ),
    uiOutput(ns("text"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$text <- renderUI({
      lapply(seq_len(4), function(i) {
        paste0("button_", i, ": ", input[[paste0("button_", i)]])
      })
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 3
library(shiny)
library(shiny.fluent)
library(shinyjs)

# This example app shows how to use a Fluent UI Button to trigger a file upload.
# File upload is not natively supported by shiny.fluent so shinyjs is used
# to trigger the file upload input.
ui <- function(id) {
  ns <- NS(id)
  fluentPage(
    useShinyjs(),
    Stack(
      tokens = list(
        childrenGap = 10L
      ),
      horizontal = TRUE,
      DefaultButton.shinyInput(
        inputId = ns("uploadFileButton"),
        text = "Upload File",
        iconProps = list(iconName = "Upload")
      ),
      div(
        style = "
          visibility: hidden;
          height: 0;
          width: 0;
        ",
        fileInput(
          inputId = ns("uploadFile"),
          label = NULL
        )
      )
    ),
    textOutput(ns("file_path"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$uploadFileButton, {
      click("uploadFile")
    })

    output$file_path <- renderText({
      input$uploadFile$name
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 4
library(shiny)
library(shiny.fluent)
library(shinyjs)

# This example app shows how to use a Fluent UI Button to trigger a file download.
# File download is not natively supported by shiny.fluent so shinyjs is used
# to trigger the file download.
ui <- function(id) {
  ns <- NS(id)
  fluentPage(
    useShinyjs(),
    DefaultButton.shinyInput(
      inputId = ns("downloadButton"),
      text = "Download",
      iconProps = list(iconName = "Download")
    ),
    div(
      style = "visibility: hidden;",
      downloadButton(ns("download"), label = "")
    )
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    observeEvent(input$downloadButton, {
      click("download")
    })

    output$download <- downloadHandler(
      filename = function() {
        paste("data-", Sys.Date(), ".csv", sep="")
      },
      content = function(file) {
        write.csv(iris, file)
      }
    )
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ActivityItem

Description

An activity item (ActivityItem) represents a person's actions, such as making a comment, mentioning someone with an @mention, editing a document, or moving a file.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ActivityItem(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ActivityItem(
    activityDescription = tagList(
      Link(key = 1, "Philippe Lampros"),
      tags$span(key = 2, " commented")
    ),
    activityIcon = Icon(iconName = "Message"),
    comments = tagList(
      tags$span(key = 1, "Hello! I am making a comment.")
    ),
    timeStamp = "Just now"
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Announced

Description

The Announced component aims to fill several of the accessibility gaps that exist in various web application experiences. It provides text for the screen reader in certain scenarios that are lacking comprehensive updates, particularly those showing the completion status or progress of operation(s).

Some real-world applications of the component include copying, uploading, or moving many files; deleting or renaming a single file; "lazy loading" of page sections that do not appear all at once; and appearance of search results.

The Announced component currently has the following documented use cases:

  1. Quick Actions: Operations such as editing text or deletion that are short enough that they do not require a status during progress.

  2. Search Results: Appearance of search results such as in contact fields or search boxes.

  3. Lazy Loading: "Lazy loading" of page sections that do not appear all at once.

  4. Bulk Operations: Operations that require multiple sub operations, such as the moving of several files.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Announced(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  Announced(message = "Screen reader message")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Pickers

Description

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Pickers are used to select one or more items, such as tags or files, from a large list.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

BasePickerListBelow(...)

TagPicker(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

TODO (adjective-object) remove IPersonaprops before the next major version bump

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

makeScript <- function(js) {
  htmltools::htmlDependency(
    name = "TagPickerExample",
    version = "0", # Not used.
    src = c(href = ""), # Not used.
    head = paste0("<script>", js, "</script>")
  )
}

ui <- function(id) {
  ns <- NS(id)
  tagList(
    makeScript("
      testTags = [
        'black',
        'blue',
        'brown',
        'cyan',
        'green',
        'magenta',
        'mauve',
        'orange',
        'pink',
        'purple',
        'red',
        'rose',
        'violet',
        'white',
        'yellow',
      ].map(item => ({ key: item, name: item }));

      function listContainsTagList(tag, tagList) {
        if (!tagList || !tagList.length || tagList.length === 0) {
          return false;
        }
        return tagList.some(compareTag => compareTag.key === tag.key);
      };

      function filterSuggestedTags(filterText, tagList) {
        return filterText
          ? testTags.filter(
              tag => tag.name.toLowerCase().indexOf(filterText.toLowerCase()) === 0 &&
               !listContainsTagList(tag, tagList),
            )
          : [];
      };
    "),
    textOutput(ns("selectedTags")),
    TagPicker(
      onResolveSuggestions = JS("filterSuggestedTags"),
      onEmptyInputFocus = JS(
        "function(tagList) { return testTags.filter(tag => !listContainsTagList(tag, tagList)); }"
      ),
      getTextFromItem = JS("function(item) { return item.text }"),
      pickerSuggestionsProps = list(
        suggestionsHeaderText = 'Suggested tags',
        noResultsFoundText = 'No color tags found'
      ),
      itemLimit = 2,
      onChange = JS(paste0(
        "function(selection) {",
        "  Shiny.setInputValue('", ns("selectedTags") ,"', JSON.stringify(selection));",
        "}"
      ))
    )
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$selectedTags <- renderText({
      if (is.null(input$selectedTags)) {
        "Select up to 2 colors below:"
      } else {
        paste(
          "You have selected:",
          paste(jsonlite::fromJSON(input$selectedTags)$name, collapse = ", ")
        )
      }
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Description

Breadcrumbs should be used as a navigational aid in your app or site. They indicate the current page’s location within a hierarchy and help the user understand where they are in relation to the rest of that hierarchy. They also afford one-click access to higher levels of that hierarchy.

Breadcrumbs are typically placed, in horizontal form, under the masthead or navigation of an experience, above the primary content area.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Breadcrumb(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

items <- list(
  list(text = "Files", key = "Files", href = "#/page"),
  list(text = "Folder 1", key = "f1", href = "#/page"),
  list(text = "Folder 2", key = "f2", href = "#/page"),
  list(text = "Folder 3", key = "f3", href = "#/page"),
  list(text = "Folder 4 (non-clickable)", key = "f4"),
  list(text = "Folder 5", key = "f5", href = "#/page", isCurrentItem = TRUE)
)

ui <- function(id) {
  Breadcrumb(
    items = items,
    maxDisplayedItems = 3,
    ariaLabel = "Breadcrumb with items rendered as links",
    overflowAriaLabel = "More links"
  )
}
server <- function(id) {
  moduleServer(id, function(input, output, session) { })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Calendar

Description

The calendar control lets people select and view a single date or a range of dates in their calendar. It’s made up of 3 separate views: the month view, year view, and decade view.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Calendar(...)

Calendar.shinyInput(inputId, ..., value = shiny.react::JS("new Date()"))

updateCalendar.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    Calendar.shinyInput(ns("calendar"), value = "2020-06-25T22:00:00.000Z"),
    textOutput(ns("calendarValue")),
    h3("If `value` is missing, default to system date"),
    Calendar.shinyInput(ns("calendar2")),
    textOutput(ns("calendarDefault")),
    h3("If `value` is NULL, also default to system date"),
    Calendar.shinyInput(ns("calendar3"), value = NULL),
    textOutput(ns("calendarNull"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$calendarValue <- renderText({
      sprintf("Value: %s", input$calendar)
    })
    output$calendarDefault <- renderText({
      sprintf("Value: %s", input$calendar2)
    })
    output$calendarNull <- renderText({
      sprintf("Value: %s", input$calendar3)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Callout

Description

A callout is an anchored tip that can be used to teach people or guide them through the app without blocking them.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Callout(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

If you set overflowY in this object, it provides a performance optimization by preventing Popup (underlying component of Callout) from calculating whether it needs a scroll bar.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DefaultButton.shinyInput(ns("toggleCallout"), text = "Toggle Callout"),
    reactOutput(ns("callout"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    show <- reactiveVal(FALSE)
    observeEvent(input$toggleCallout, show(!show()))
    output$callout <- renderReact({
      if (show()) {
        Callout(
          tags$div(
            style = "margin: 10px",
            "Callout contents"
          )
        )
      }
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Checkbox

Description

Check boxes (Checkbox) give people a way to select one or more items from a group, or switch between two mutually exclusive options (checked or unchecked, on or off).

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Checkbox(...)

Checkbox.shinyInput(inputId, ..., value = defaultValue)

updateCheckbox.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    Checkbox.shinyInput(ns("checkbox"), value = FALSE),
    textOutput(ns("checkboxValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$checkboxValue <- renderText({
      sprintf("Value: %s", input$checkbox)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ChoiceGroup

Description

Radio buttons (ChoiceGroup) let people select a single option from two or more choices.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ChoiceGroup(...)

ChoiceGroup.shinyInput(inputId, ..., value = defaultValue)

updateChoiceGroup.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

options <- list(
  list(key = "A", text = "Option A"),
  list(key = "B", text = "Option B"),
  list(key = "C", text = "Option C")
)

ui <- function(id) {
  ns <- NS(id)
  div(
    ChoiceGroup.shinyInput(ns("choice"), value = "B", options = options),
    textOutput(ns("groupValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$groupValue <- renderText({
      sprintf("Value: %s", input$choice)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Coachmark

Description

Coach marks (Coachmark) are used to draw a person’s attention to parts of the UI and increase engagement with those elements. A teaching bubble appears on hover or selection of the coach mark.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Coachmark(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  tagList(
    uiOutput(ns("coachmark")),
    DefaultButton.shinyInput(ns("toggleCoachmark"),
      id = "target", text = "Toggle coachmark"
    )
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    coachmarkVisible <- reactiveVal(FALSE)
    observeEvent(input$toggleCoachmark, coachmarkVisible(!coachmarkVisible()))
    observeEvent(input$hideCoachmark, coachmarkVisible(FALSE))
    output$coachmark <- renderUI({
      if (coachmarkVisible()) Coachmark(
        target = "#target",
        TeachingBubbleContent(
          hasCloseButton = TRUE,
          onDismiss = triggerEvent(ns("hideCoachmark")),
          headline = "Example title",
          primaryButtonProps = list(text = "Try it"),
          secondaryButtonProps = list(text = "Try it again"),
          "Welcome to the land of coachmarks!"
        )
      )
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ColorPicker

Description

The color picker (ColorPicker) is used to browse through and select colors. By default, it lets people navigate through colors on a color spectrum; or specify a color in either Red-Green-Blue (RGB); or alpha color code; or Hexadecimal textboxes.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ColorPicker(...)

ColorPicker.shinyInput(inputId, ..., value = defaultValue)

updateColorPicker.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Alpha represents the opacity of the color, whereas transparency represents the transparentness of the color: i.e. a 30% transparent color has 70% opaqueness.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    ColorPicker.shinyInput(ns("color"), value = "#00FF01"),
    textOutput(ns("colorValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$colorValue <- renderText({
      sprintf("Value: %s", input$color)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ComboBox

Description

A combo box (ComboBox) combines a text field and a drop-down menu, giving people a way to select an option from a list or enter their own choice.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ComboBox(...)

VirtualizedComboBox(...)

ComboBox.shinyInput(inputId, ..., value = defaultValue)

updateComboBox.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

options <- list(
  list(key = "A", text = "Option A"),
  list(key = "B", text = "Option B"),
  list(key = "C", text = "Option C")
)

ui <- function(id) {
  ns <- NS(id)
  div(
    ComboBox.shinyInput(ns("combo"), value = list(text = "some text"),
      options = options, allowFreeform = TRUE
    ),
    textOutput(ns("comboValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$comboValue <- renderText({
      sprintf("Value: %s", input$combo$text)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

CommandBar

Description

CommandBar is a surface that houses commands that operate on the content of the window, panel, or parent region it resides above. CommandBars are one of the most visible and recognizable ways to surface commands, and can be an intuitive method for interacting with content on the page; however, if overloaded or poorly organized, they can be difficult to use and hide valuable commands from your user. CommandBars can also display a search box for finding content, hold simple commands as well as menus, or display the status of ongoing actions.

Commands should be sorted in order of importance, from left-to-right or right-to-left depending on the culture. Secondarily, organize commands in logical groupings for easier recall. CommandBars work best when they display no more than 5-7 commands. This helps users quickly find your most valuable features. If you need to show more commands, consider using the overflow menu. If you need to render status or viewing controls, these go on the right side of the CommandBar (or left side if in a left-to-right experience). Do not display more than 2-3 items on the right side as it will make the overall CommandBar difficult to parse.

All command items should have an icon and a label. Commands can render as labels only as well. In smaller widths, commands can just use icon only, but only for the most recognizable and frequently used commands. All other commands should go into an overflow where text labels can be shown.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

CommandBar(...)

CommandBar.shinyInput(inputId, ..., itemValueGetter = function(el) el$key)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component. Value of the clicked CommandBarItem will be sent to this ID.

itemValueGetter

A function that takes a CommandBarItem and returns a value to be sent to Shiny. By default it returns key of the item.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

items <- function(ns) {
  list(
    CommandBarItem(
      key = ns("newItem"),
      text = "New",
      cacheKey = "myCacheKey",
      split = TRUE,
      iconProps = list(iconName = "Add"),
      subMenuProps = list(
        items = list(
          CommandBarItem(
            key = ns("emailMessage"),
            text = "Email message",
            iconProps = list(iconName = "Mail")
          ),
          CommandBarItem(
            key = ns("calendarEvent"),
            text = "Calendar event",
            iconProps = list(iconName = "Calendar")
          )
        )
      )
    ),
    CommandBarItem(
      key = ns("upload"),
      text = "Upload",
      iconProps = list(iconName = "Upload")
    ),
    CommandBarItem(
      key = ns("share"),
      text = "Share",
      iconProps = list(iconName = "Share")
    ),
    CommandBarItem(
      key = ns("download"),
      text = "Download",
      iconProps = list(iconName = "Download")
    )
  )
}

farItems <- function(ns) {
  list(
    CommandBarItem(
      key = ns("tile"),
      text = "Grid view",
      ariaLabel = "Grid view",
      iconOnly = TRUE,
      iconProps = list(iconName = "Tiles")
    ),
    CommandBarItem(
      key = ns("info"),
      text = "Info",
      ariaLabel = "Info",
      iconOnly = TRUE,
      iconProps = list(iconName = "Info")
    )
  )
}

ui <- function(id) {
  ns <- NS(id)
  tagList(
    CommandBar(
      items = items(ns),
      farItems = farItems(ns)
    ),
    textOutput(ns("commandBarItems")),
    CommandBar.shinyInput(
      inputId = ns("commandBar"),
      items = items(identity),
      farItems = farItems(identity)
    ),
    textOutput(ns("commandBar"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    commandBarItemClicked <- reactiveVal()
    observeEvent(input$newItem, commandBarItemClicked("newItem clicked (explicitly observed)"))
    observeEvent(input$upload, commandBarItemClicked("upload clicked (explicitly observed)"))
    output$commandBarItems <- renderText(commandBarItemClicked())
    output$commandBar <- renderText(input$commandBar)
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Command bar item

Description

Helper function for constructing items for CommandBar and CommandBar.shinyInput.

Usage

CommandBarItem(
  key,
  text,
  onClick = setInputValue(inputId = key, value = 0, event = TRUE),
  ...
)

Arguments

key

Key of the item.

text

Text to be displayed on the menu.

onClick

A JS function that runs on item click. By default it sends input value to input[[key]]. If used within CommandBar.shinyInput, it will send the value to the input ID specified in inputId argument of CommandBar.shinyInput.

...

Additional props to pass to CommandBarItem.

Value

Item suitable for use in the CommandBar and CommandBar.shinyInput.

See Also

CommandBar


PeoplePicker

Description

The people picker (PeoplePicker) is used to select one or more entities, such as people or groups, from a list. It makes composing an email to someone, or adding them to a group, easy if you don’t know their full name or email address.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

CompactPeoplePicker(...)

NormalPeoplePicker(...)

NormalPeoplePicker.shinyInput(inputId, ..., value = defaultValue)

updateNormalPeoplePicker.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

assetsUrl <- "https://static2.sharepointonline.com/files/fabric/office-ui-fabric-react-assets/"
malePersonaUrl <- paste0(assetsUrl, "persona-male.png")
femalePersonaUrl <- paste0(assetsUrl, "persona-female.png")

people <- tibble::tibble(
  key = c(1, 2, 3, 4, 5, 6, 7),
  imageUrl = c(
    femalePersonaUrl,
    malePersonaUrl,
    malePersonaUrl,
    malePersonaUrl,
    malePersonaUrl,
    femalePersonaUrl,
    malePersonaUrl
  ),
  imageInitials = c("PV", "AR", "AL", "RK", "CB", "VL", "MS"),
  text = c(
    "Annie Lindqvist",
    "Aaron Reid",
    "Alex Lundberg",
    "Roko Kolar",
    "Christian Bergqvist",
    "Valentina Lovric",
    "Maor Sharett"
  ),
  secondaryText = c(
    "Designer",
    "Designer",
    "Software Developer",
    "Financial Analyst",
    "Sr. Designer",
    "Design Developer",
    "UX Designer"
  ),
  tertiaryText = c(
    "In a meeting",
    "In a meeting",
    "In a meeting",
    "In a meeting",
    "In a meeting",
    "In a meeting",
    "In a meeting"
  ),
  optionalText = c(
    "Available at 4:00pm",
    "Available at 4:00pm",
    "Available at 4:00pm",
    "Available at 4:00pm",
    "Available at 4:00pm",
    "Available at 4:00pm",
    "Available at 4:00pm"
  ),
  isValid = c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
  presence = c(2, 6, 4, 1, 2, 2, 3),
  canExpand = c(NA, NA, NA, NA, NA, NA, NA)
)

ui <- function(id) {
  ns <- NS(id)
  tagList(
    textOutput(ns("selectedPeople")),
    NormalPeoplePicker.shinyInput(
      ns("selectedPeople"),
      options = people,
      pickerSuggestionsProps = list(
        suggestionsHeaderText = 'Matching people',
        mostRecentlyUsedHeaderText = 'Sales reps',
        noResultsFoundText = 'No results found',
        showRemoveButtons = TRUE
      )
    )
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$selectedPeople <- renderText({
      if (length(input$selectedPeople) == 0) {
        "Select recipients below:"
      } else {
        selectedPeople <- dplyr::filter(people, key %in% input$selectedPeople)
        paste("You have selected:", paste(selectedPeople$text, collapse=", "))
      }
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ContextualMenu

Description

ContextualMenus are lists of commands that are based on the context of selection, mouse hover or keyboard focus. They are one of the most effective and highly used command surfaces, and can be used in a variety of places.

There are variants that originate from a command bar, or from cursor or focus. Those that come from CommandBars use a beak that is horizontally centered on the button. Ones that come from right click and menu button do not have a beak, but appear to the right and below the cursor. ContextualMenus can have submenus from commands, show selection checks, and icons.

Organize commands in groups divided by rules. This helps users remember command locations, or find less used commands based on proximity to others. One should also group sets of mutually exclusive or multiple selectable options. Use icons sparingly, for high value commands, and don’t mix icons with selection checks, as it makes parsing commands difficult. Avoid submenus of submenus as they can be difficult to invoke or remember.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ContextualMenu(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DefaultButton.shinyInput(
      ns("toggleContextualMenu"),
      id = "target",
      text = "Toggle menu"
    ),
    reactOutput(ns("contextualMenu"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    showContextualMenu <- reactiveVal(FALSE)
    observeEvent(input$toggleContextualMenu, {
      showContextualMenu(!showContextualMenu())
    })

    output$contextualMenu <- renderReact({
      menuItems <- JS("[
        {
          key: 'newItem',
          text: 'New',
          onClick: () => console.log('New clicked'),
        },
        {
          key: 'divider_1',
          itemType: 1,
        },
        {
          key: 'rename',
          text: 'Rename',
          onClick: () => console.log('Rename clicked'),
        },
        {
          key: 'edit',
          text: 'Edit',
          onClick: () => console.log('Edit clicked'),
        },
        {
          key: 'properties',
          text: 'Properties',
          onClick: () => console.log('Properties clicked'),
        },
        {
          key: 'linkNoTarget',
          text: 'Link same window',
          href: 'http://bing.com',
        },
        {
          key: 'linkWithTarget',
          text: 'Link new window',
          href: 'http://bing.com',
          target: '_blank',
        },
        {
          key: 'linkWithOnClick',
          name: 'Link click',
          href: 'http://bing.com',
          onClick: function(){
            alert('Link clicked');
            ev.preventDefault();
          },
          target: '_blank',
        },
        {
          key: 'disabled',
          text: 'Disabled item',
          disabled: true,
          onClick: () => console.error('Disabled item should not be clickable.'),
        },
      ]")

      ContextualMenu(
        items = menuItems,
        hidden = !showContextualMenu(),
        target = "#target",
        onItemClick = JS(paste0(
          "function() {",
          "  Shiny.setInputValue('", ns("toggleContextualMenu"), "', Math.random());",
          "}"
        )),
        onDismiss = JS(paste0(
          "function() {",
          "  Shiny.setInputValue('", ns("toggleContextualMenu"), "', Math.random());",
          "}"
        ))
      )
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

DatePicker

Description

Picking a date can be tough without context. A date picker (DatePicker) offers a drop-down control that’s optimized for picking a single date from a calendar view where contextual information like the day of the week or fullness of the calendar is important. You can modify the calendar to provide additional context or to limit available dates.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

DatePicker(...)

DatePicker.shinyInput(inputId, ..., value = defaultValue)

updateDatePicker.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

# Example 1
library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DatePicker.shinyInput(ns("date"), value = "2020-06-25T22:00:00.000Z"),
    textOutput(ns("dateValue")),
    h3("If `value` is missing, default to system date"),
    DatePicker.shinyInput(ns("date2")),
    textOutput(ns("dateDefault")),
    h3("If `value` is NULL, return NULL"),
    DatePicker.shinyInput(ns("date3"), value = NULL, placeholder = "I am placeholder!"),
    textOutput(ns("dateNull"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$dateValue <- renderText({
      sprintf("Value: %s", input$date)
    })
    output$dateDefault <- renderText({
      sprintf("Value: %s", input$date2)
    })
    output$dateNull <- renderText({
      sprintf("Value: %s", deparse(input$date3))
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Supplying custom strings for DatePicker
ui <- function(id) {
  fluentPage(
    DatePicker.shinyInput(
      "date",
      value = Sys.Date(),
      strings = list(
        months = list(
          "January", "February", "March", "April",
          "May", "June", "July", "August",
          "September", "October", "November", "December"
        ),
        shortMonths = list(
          "Jan", "Feb", "Mar", "Apr", "May", "Jun",
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
        ),
        days = list(
          "Sunday", "Monday", "Tuesday", "Wednesday",
          "Thursday", "Friday", "Saturday"
        ),
        shortDays = list("S", "M", "T", "W", "T", "F", "S"),
        goToToday = "Go to today",
        prevMonthAriaLabel = "Go to previous month",
        nextMonthAriaLabel = "Go to next month",
        prevYearAriaLabel = "Go to previous year",
        nextYearAriaLabel = "Go to next year"
      )
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

DetailsList

Description

A details list (DetailsList) is a robust way to display an information-rich collection of items, and allow people to sort, group, and filter the content. Use a details list when information density is critical.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

DetailsList(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Virtualization will add and remove pages of items as the user scrolls them into the visible range. This benefits larger list scenarios by reducing the DOM on the screen, but can negatively affect performance for smaller lists.

The default implementation will virtualize when this callback is not provided.

Falls back to window 'resize' event.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

⁠[capitalization]⁠: https://docs.microsoft.com/style-guide/capitalization

FAQ

My scrollable content isn't updating on scroll. What should I do?

Add the data-is-scrollable="true" attribute to your scrollable element containing the DetailsList.

By default, the List used within DetailsList will use the body element as the scrollable element. If you contain the List within a scrollable div using overflow: auto or scroll, the List needs to listen for scroll events on that element instead. On initialization, the List will traverse up the DOM looking for the first element with the data-is-scrollable attribute to know which element to listen to for knowing when to re-evaulate the visible window.

My List is not re-rendering when I mutate its items. What should I do?

To determine if the List within DetailsList should re-render its contents, the component performs a referential equality check within its shouldComponentUpdate method. This is done to minimize the performance overhead associated with re-rendering the virtualized List pages, as recommended by the React documentation.

As a result of this implementation, the inner List will not determine it should re-render if the array values are mutated. To avoid this problem, we recommend re-creating the items array backing the DetailsList by using a method such as Array.prototype.concat or ES6 spread syntax shown below:

public appendItems(): void {
  const { items } = this.state;

  this.setState({
    items: [...items, ...['Foo', 'Bar']]
  })
}

public render(): JSX.Element {
  const { items } = this.state;

  return <DetailsList items={items} />;
}

By re-creating the items array without mutating the values, the inner List will correctly determine its contents have changed and it should then re-render with the new values.

Examples

# Example 1
library(shiny)
library(shiny.fluent)

items <- list(
  list(key = "1", name = "Mark", surname = "Swanson"),
  list(key = "2", name = "Josh", surname = "Johnson")
)

columns <- list(
  list(key = "name", fieldName = "name", name = "Name"),
  list(key = "surname", fieldName = "surname", name = "Surname")
)


ui <- function(id) {
  ns <- NS(id)
  DetailsList(items = items, columns = columns)
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Custom columns text alignment and formatting
items <- list(
  list(
    key = "1",
    name = "Mark",
    number = "2"
  ),
  list(
    key = "2",
    name = "Josh",
    number = "1"
  )
)

columns <- list(
  list(
    key = "name",
    fieldName = "name",
    name = "Name"
  ),
  list(
    key = "number",
    fieldName = "number",
    name = "Number"
  )
)

ui <- function(id) {
  DetailsList(
    items = items,
    columns = columns,
    onRenderItemColumn = JS("(item, index, column) => {
      const fieldContent = item[column.fieldName]
      switch (column.key) {
        case 'name':
          return React.createElement(
            'span',
            {
              style: { textAlign: 'right', width: '100%', display: 'block' }
            },
            fieldContent
          );
        case 'number':
          return React.createElement(
            'span',
            {
              style: { textAlign: 'left', width: '100%', display: 'block' }
            },
            `%${fieldContent}`
          );
        default:
          return React.createElement('span', null, fieldContent);
      }
    }")
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 3
library(shiny)
library(shiny.fluent)

# Selecting rows in DetailsList
CustomComponents <- tags$script(HTML("(function() {
  const React = jsmodule['react'];
  const Fluent = jsmodule['@fluentui/react'];
  const Shiny = jsmodule['@/shiny'];
  const CustomComponents = jsmodule['CustomComponents'] ??= {};

  function useSelection(inputId) {
    const selection = React.useRef(new Fluent.Selection({
      onSelectionChanged() {
        const value = this.getSelectedIndices().map(i => i + 1); // R uses 1-based indexing.
        Shiny.setInputValue(inputId, value);
      }
    }));
    return selection.current;
  }

  CustomComponents.DetailsList = function DetailsList({ inputId, ...rest }) {
    const selection = useSelection(inputId);
    return React.createElement(Fluent.DetailsList, { selection, ...rest });
  }
})()"))

DetailsList.shinyInput <- function(inputId, ...) {
  shiny.react::reactElement(
    module = "CustomComponents",
    name = "DetailsList",
    props = shiny.react::asProps(inputId = inputId, ...),
    deps = shinyFluentDependency()
  )
}

items <- list(
  list(name = "Apple"),
  list(name = "Banana"),
  list(name = "Cherry")
)

ui <- function(id) {
  ns <- NS(id)
  tagList(
    CustomComponents,
    DetailsList.shinyInput(ns("selection"), items = items),
    textOutput(ns("text"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$text <- renderText(paste(input$selection, collapse = ", "))
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Dialog

Description

A dialog box (Dialog) is a temporary pop-up that takes focus from the page or app and requires people to interact with it. It’s primarily used for confirming actions, such as deleting a file, or asking people to make a choice.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Dialog(...)

DialogFooter(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Header
Footer
Width
Height

Content

Title
Body copy (Optional)
Button labels

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DefaultButton.shinyInput(ns("showDialog"), text = "Open dialog"),
    reactOutput(ns("reactDialog"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    isDialogOpen <- reactiveVal(FALSE)
    output$reactDialog <- renderReact({
      dialogContentProps <- list(
        type = 0,
        title = "Missing Subject",
        closeButtonAriaLabel = "Close",
        subText = "Do you want to send this message without a subject?"
      )
      Dialog(
        hidden = !isDialogOpen(),
        onDismiss = JS(paste0(
          "function() {",
          "  Shiny.setInputValue('", ns("hideDialog"),"', Math.random());",
          "}"
        )),
        dialogContentProps = dialogContentProps,
        modalProps = list(),
        DialogFooter(
          PrimaryButton.shinyInput(ns("dialogSend"), text = "Send"),
          DefaultButton.shinyInput(ns("dialogDontSend"), text = "Don't send")
        )
      )
    })

    observeEvent(input$showDialog, isDialogOpen(TRUE))
    observeEvent(input$hideDialog, isDialogOpen(FALSE))
    observeEvent(input$dialogSend, isDialogOpen(FALSE))
    observeEvent(input$dialogDontSend, isDialogOpen(FALSE))
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

DocumentCard

Description

A document card (DocumentCard) represents a file, and contains additional metadata or actions. This offers people a richer view into a file than the typical grid view.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

DocumentCard(...)

DocumentCardActions(...)

DocumentCardActivity(...)

DocumentCardDetails(...)

DocumentCardImage(...)

DocumentCardLocation(...)

DocumentCardLogo(...)

DocumentCardPreview(...)

DocumentCardStatus(...)

DocumentCardTitle(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Deprecated at v4.17.1, to be removed at \>= v5.0.0.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

# Example 1
library(shiny)
library(shiny.fluent)

title <- "Long_file_name_with_underscores_used_to_separate_all_of_the_words"

previewImages <- list(
  list(
    previewImageSrc = "https://picsum.photos/318/196",
    width = 318,
    height = 196
  )
)

ui <- function(id) {
  ns <- NS(id)
  DocumentCard(
    DocumentCardPreview(previewImages = previewImages),
    DocumentCardTitle(
      title = title,
      shouldTruncate = TRUE
    ),
    DocumentCardActivity(
      activity = "Created a few minutes ago",
      people = list(list(name = "Annie Lindqvist"))
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Using icons in DocumentCardActions
ui <- function(id) {
  previewImages <- list(
    list(
      previewImageSrc = "https://picsum.photos/318/196",
      width = 318,
      height = 200
    )
  )
  fluidPage(
    DocumentCard(
      DocumentCardPreview(previewImages = previewImages),
      DocumentCardTitle(
        title = "Card",
        shouldTruncate = TRUE
      ),
      DocumentCardActivity(
        activity = "2022-03-23",
        people = list(list(name = "Annie Lindqvist"))
      ),
      DocumentCardActions(
        actions = list(
          list(
            iconProps = list(iconName = "Share"),
            onClick = JS("function() { alert('share icon clicked') }")
          ),
          list(
            iconProps = list(iconName = "Pin"),
            onClick = JS("function() { alert('pin icon clicked') }")
          ),
          list(
            iconProps = list(iconName = "Ringer"),
            onClick = JS("function() { alert('ringer icon clicked') }")
          )
        )
      )
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Description

A dropdown menu is a list in which the selected item is always visible while other items are visible on demand by clicking a dropdown button.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Dropdown(...)

Dropdown.shinyInput(inputId, ..., value = defaultValue)

updateDropdown.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

# Example 1
library(shiny)
library(shiny.fluent)

options <- list(
  list(key = "A", text = "Option A"),
  list(key = "B", text = "Option B"),
  list(key = "C", text = "Option C")
)

ui <- function(id) {
  ns <- NS(id)
  div(
    Dropdown.shinyInput(ns("dropdown"), value = "A", options = options),
    textOutput(ns("dropdownValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$dropdownValue <- renderText({
      sprintf("Value: %s", input$dropdown)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Rendering headers and dividers inside dropdown
DropdownMenuItemType <- function(type) {
  JS(paste0("jsmodule['@fluentui/react'].DropdownMenuItemType."), type)
}

ui <- function(id) {
  fluentPage(
    Dropdown(
      "fruit",
      label = "Fruit",
      multiSelect = TRUE,
      options = list(
        list(
          key = "fruitsHeader",
          text = "Fruit",
          itemType = DropdownMenuItemType("Header")
        ),
        list(key = "apple", text = "Apple"),
        list(key = "banana", text = "Banana"),
        list(key = "orange", text = "Orange", disabled = TRUE),
        list(key = "grape", text = "Grape"),
        list(
          key = "divider_1",
          text = "-",
          itemType = DropdownMenuItemType("Divider")
        ),
        list(
          key = "vegetablesHeader",
          text = "Vegetables",
          itemType = DropdownMenuItemType("Header"
          )
        ),
        list(key = "broccoli", text = "Broccoli"),
        list(key = "carrot", text = "Carrot"),
        list(key = "lettuce", text = "Lettuce")
      )
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Facepile

Description

A face pile (Facepile) displays a list of personas. Each circle represents a person and contains their image or initials. Often this control is used when sharing who has access to a specific view or file, or when assigning someone a task within a workflow.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Facepile(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

personas <- list(
  list(personaName = "Adams Baker"),
  list(personaName = "Clark Davis"),
  list(personaName = "Evans Frank")
)

ui <- function(id) {
  ns <- NS(id)
  Facepile(personas = personas)
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

FocusTrapZone

Description

FocusTrapZone is used to trap the focus in any html element. Pressing tab will circle focus within the inner focusable elements of the FocusTrapZone.

Note: Trapping focus will restrict interaction with other elements in the website such as the side nav. Turn off the "Use trap zone" toggle control to allow this interaction to happen again.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

FocusTrapCallout(...)

FocusTrapZone(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  reactOutput(ns("focusTrapZone"))
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    output$focusTrapZone <- renderReact({
      useTrapZone <- isTRUE(input$useTrapZone)
      stackStyles <- list(root = list(
        border = if (useTrapZone) '2px solid #ababab' else 'transparent',
        padding = 10
      ))
      textFieldStyles <- list(root = list(width = 300));
      stackTokens = list(childrenGap = 8);

      div(
        FocusTrapZone(
          disabled = !useTrapZone,
          Stack(
            horizontalAlign = "start",
            tokens = stackTokens,
            styles = stackStyles,
            Toggle.shinyInput(ns("useTrapZone"),
              value = FALSE,
              label = "Use trap zone",
              onText = "On (toggle to exit)",
              offText = "Off (toggle to trap focus)"
            ),
            TextField.shinyInput(
              ns("textInput"),
              label = "Input inside trap zone",
              styles = textFieldStyles
            ),
            Link(
              href = "https://bing.com",
              target = "_blank",
              "Hyperlink inside trap zone"
            )
          )
        ),
        Link(
          href = "https://bing.com",
          target = "_blank",
          "Hyperlink outside trap zone"
        )
      )
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

FocusZone

Description

FocusZones abstract arrow key navigation behaviors. Tabbable elements (buttons, anchors, and elements with data-is-focusable='true' attributes) are considered when pressing directional arrow keys and focus is moved appropriately. Tabbing to a zone sets focus only to the current "active" element, making it simple to use the tab key to transition from one zone to the next, rather than through every focusable element.

Using a FocusZone is simple. Just wrap a bunch of content inside of a FocusZone, and arrows and tabbling will be handled for you! See examples below.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

FocusZone(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

tokens <- list(childrenGap = 20)

ui <- function(id) {
  ns <- NS(id)
  Stack(
    tokens = tokens,
    horizontalAlign = "start",
    FocusZone(
      Stack(
        tokens = tokens,
        horizontal = TRUE,
        verticalAlign = "center",
        tags$span("Enabled FocusZone:"),
        DefaultButton(text = "Button 1"),
        DefaultButton(text = "Button 2"),
        TextField(placeholder = "FocusZone TextField"),
        DefaultButton(text = "Button 3")
      )
    ),
    DefaultButton(text = "Tabbable Element 1"),
    FocusZone(
      disabled = TRUE,
      Stack(
        tokens = tokens,
        horizontal = TRUE,
        verticalAlign = "center",
        tags$span("Disabled FocusZone:"),
        DefaultButton(text = "Button 1"),
        DefaultButton(text = "Button 2")
      )
    ),
    TextField(placeholder = "Tabbable Element 2")
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Icon

Description

In a user interface, an icon is an image that represents an application, a capability, or some other concept or specific entity with meaning for the user. An icon is usually selectable but can also be a nonselectable image, such as a company's logo.

For a list of icons, visit our icon documentation.

Note that icons are not bundled by default and typically must be loaded by calling initializeIcons from the ⁠@uifabric/icons⁠ package at the root of your application. See the icon documentation for more details.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

FontIcon(...)

Icon(...)

ImageIcon(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

style <- list(fontSize = 50, margin = 10)

ui <- function(id) {
  ns <- NS(id)
  tags$div(
    FontIcon(iconName = "CompassNW", style = style),
    FontIcon(iconName = "Dictionary", style = style),
    FontIcon(iconName = "TrainSolid", style = style)
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

GroupedList

Description

A grouped list (GroupedList) allows you to render a set of items as multiple lists with various grouping properties.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

GroupedList(...)

GroupHeader(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

FAQ

My List is not re-rendering when I mutate its items. What should I do?

To determine if the list within the grouped list should re-render its contents, the component performs a referential equality check within its shouldComponentUpdate method. This is done to minimize the performance overhead associating with re-rendering the virtualized List pages, as recommended by the React documentation.

As a result of this implementation, the inner list will not determine it should re-render if the array values are mutated. To avoid this problem, we recommend re-creating the items array backing the grouped list by using a method such as Array.prototype.concat or ES6 spread syntax shown below:

public appendItems(): void {
  const { items } = this.state;

  this.setState({
    items: [...items, ...['Foo', 'Bar']]
  })
}

public render(): JSX.Element {
  const { items } = this.state;

  return <GroupedList items={items} />;
}

By re-creating the items array without mutating the values, the inner List will correctly determine its contents have changed and then it should re-render with the new values.

Examples

# Example 1
library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  GroupedList(
    items = list("Item A", "Item B", "Item C", "Item D", "Item E"),
    groups = list(
      list(key = "g1", name = "Some items", startIndex = 0, count = 2),
      list(key = "g2", name = "More items", startIndex = 2, count = 3)
    ),
    selectionMode = 0,
    onRenderCell = JS("(depth, item) => (
      jsmodule['react'].createElement('span', { style: { paddingLeft: 49 } }, item)
    )")
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

ui <- function(id) {
  fluentPage(
    GroupedList(
      items = list("Item A", "Item B", "Item C", "Item D", "Item E"),
      groups = list(
        list(key = "g1", name = "Some items", startIndex = 0, count = 2),
        list(key = "g2", name = "More items", startIndex = 2, count = 3)
      ),
      selectionMode = 0,
      onRenderCell = JS(
        "(depth, item) => (
          jsmodule['react'].createElement('span', { style: { paddingLeft: 50 } }, item)
        )"
      ),
      groupProps = list(
        onRenderHeader = JS(
          "(props) => (
            jsmodule['react'].createElement(
              jsmodule['@fluentui/react'].GroupHeader,
              { ...props, styles: { headerCount: { display: 'none' } } },
              props
            )
          )"
        )
      )
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

HoverCard

Description

Hover cards (HoverCard) show commands and information, such as metadata and activity, when someone hovers over an item.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

HoverCard(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  HoverCard(
    type = "PlainCard",
    plainCardProps = JS("{
      onRenderPlainCard: (a, b, c) => 'HoverCard contents',
      style: { margin: 10 }
    }"),
    "Hover over me"
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Image

Description

An image is a graphic representation of something (e.g photo or illustration). The borders have been added to these examples in order to help visualize empty space in the image frame.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Image(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Image(src = "https://via.placeholder.com/350x150")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Keytip

Description

A Keytip is a small popup near a component that indicates a key sequence that will trigger that component. These are not to be confused with keyboard shortcuts; they are instead key sequences to traverse through levels of UI components. Technically, a Keytip is a wrapper around a Callout where the target element is discovered through a 'data-ktp-target' attribute on that element.

To enable Keytips on your page, a developer will add the KeytipLayer component somewhere in their document. It can be added anywhere in your document, but must only be added once. Use the registerKeytip utility helper to add a Keytip. A user will enter and exit keytip mode with a IKeytipTransitionSequence, which is a key with any amount of modifiers (Alt, Shift, etc).

By default, the entry and exit sequence is 'Alt-Windows' (Meta) on Windows and 'Option-Control' on macOS. There is also a sequence to 'return' up a level of keytips while traversing. This is by default 'Esc'.

Fluent UI React components that have keytips enabled have an optional 'keytipProps' prop which handles registering, unregistering, and rendering of the keytip. The keySequences of the Keytip should be the full sequence to get to that keytip. There is a 'buildKeytipConfigMap' helper which will build a map of ID -> IKeytipProps to assist in defining your keytips.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.


Keytips

Description

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

KeytipLayer(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

makeScript <- function(js) {
  tagList(
    shiny.react::reactDependency(),
    htmltools::htmlDependency(
      name = "KeytipsExample",
      version = "0", # Not used.
      src = c(href = ""), # Not used.
      head = paste0("<script>", js, "</script>")
    )
  )
}

ui <- function(id) {
  ns <- NS(id)
  tagList(
    makeScript(paste0("setTimeout(() => {
      const btnExecute = (el) => {
        el.click();
      };

      const keytipConfig = {
        keytips: [
          // Button example
          {
            id: 'Button',
            content: '1A',
            optionalProps: {
              onExecute: btnExecute,
            },
          },
          {
            id: 'CompoundButton',
            content: '1B',
            optionalProps: {
              onExecute: btnExecute,
            },
          },
          {
            id: 'ButtonWithMenu',
            content: '2A',
            optionalProps: {
              onExecute: btnExecute,
            },
            children: [
              {
                id: 'ButtonMenuItem1',
                content: 'E',
                optionalProps: {
                  onExecute: btnExecute,
                },
              },
              {
                id: 'ButtonMenuItem2',
                content: '8',
                optionalProps: {
                  onExecute: btnExecute,
                },
              },
            ],
          }
        ],
      };

      keytipMap = jsmodule['@fluentui/react'].buildKeytipConfigMap(keytipConfig);

      window.buttonProps = {
        items: [
          {
            key: 'buttonMenuItem1',
            text: 'Menu Item 1',
            keytipProps: keytipMap.ButtonMenuItem1,
            onClick: () => Shiny.setInputValue('", ns("button3"), "', Math.random())
          },
          {
            key: 'buttonMenuItem2',
            text: 'Menu Item 2',
            keytipProps: keytipMap.ButtonMenuItem2,
            onClick: () => Shiny.setInputValue('", ns("button3"), "', Math.random())
          },
        ],
      };
    })")),
    textOutput(ns("keytipsResult")),
    div(
      Label(
        paste0(
          "To open keytips, hit 'Alt-Windows' on Windows/Linux and 'Option-Control' on macOS.",
          "Keytips will appear. Type what you see, e.g. 1 and then A to 'click' the first button."
        )
      ),
      Label(
        paste0(
          "When multiple Keytips start with the same character,",
          "typing that character will filter the visible keytips."
        )
      ),
      KeytipLayer(),
      Stack(horizontal = TRUE, tokens = list(childrenGap = 20),
        DefaultButton.shinyInput(
          ns("button1"),
          keytipProps = JS("keytipMap.Button"),
          text = "Button"
        ),
        CompoundButton.shinyInput(
          ns("button2"),
          style = list(marginBottom = 28),
          keytipProps = JS("keytipMap.CompoundButton"),
          text = "Compound Button",
          secondaryText = 'With a Keytip'
        ),
        DefaultButton.shinyInput(
          ns("button3"),
          keytipProps = JS("keytipMap.ButtonWithMenu"),
          text = "Button with Menu",
          menuProps = JS("buttonProps")
        )
      )
    )
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    clicks <- reactiveVal(0)
    addClick <- function() clicks(clicks() + 1)
    output$keytipsResult <- renderText(paste("Buttons clicked: ", clicks()))
    observeEvent(input$button1, addClick())
    observeEvent(input$button2, addClick())
    observeEvent(input$button3, addClick())
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Label

Description

Labels give a name or title to a control or group of controls, including text fields, check boxes, combo boxes, radio buttons, and drop-down menus.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Label(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Label("Required label", required = TRUE)
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Layer

Description

A Layer is a technical component that does not have specific Design guidance.

Layers are used to render content outside of a DOM tree, at the end of the document. This allows content to escape traditional boundaries caused by "overflow: hidden" css rules and keeps it on the top without using z-index rules. This is useful for example in ContextualMenu and Tooltip scenarios, where the content should always overlay everything else.

There are some special considerations. Due to the nature of rendering content elsewhere asynchronously, React refs within content will not be resolvable synchronously at the time the Layer is mounted. Therefore, to use refs correctly, use functional refs ⁠ref={ (el) => { this._root = el; }⁠ rather than string refs ref='root'. Additionally measuring the physical Layer element will not include any of the children, since it won't render it. Events that propgate from within the content will not go through the Layer element as well.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Layer(...)

LayerHost(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    style = "margin-top: 60px; border: 1px solid navy; padding: 10px; background: #eee;",
    Checkbox.shinyInput(ns("useLayer"), value = FALSE, label = "Display a message in a layer"),
    reactOutput(ns("layer"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$layer <- renderReact({
      box <- div(
        style = "background-color: #60C7FF; margin: 10px; padding: 10px",
        "Hello!"
      )
      if (isTRUE(input$useLayer)) Layer(box)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}
library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    LayerHost(id = "host", style = list(border = "1px dashed", padding = 10)),
    "Layer children are rendered in the LayerHost",
    Layer(hostId = "host", "Content")
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Description

Links lead to another part of an app, other pages, or help articles. They can also be used to initiate commands.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Link(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Link(href = "https://appsilon.com", "Appsilon")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

List

Description

A list provides a base component for rendering large sets of items. It’s agnostic of layout, the tile component used, and selection management.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

List(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

FAQ

My scrollable content isn't updating on scroll, what should I do?

Add the data-is-scrollable="true" attribute to your scrollable element containing the List.

By default, the List will use the ⁠<body>⁠ element as the scrollable element. If you contain List within a scrollable ⁠<div>⁠ using overflow: auto or scroll, List needs to listen for scroll events on that element instead. On initialization, List will traverse up the DOM looking for the first element with the data-is-scrollable attribute to know which element to listen to for knowing when to re-evaulate the visible window.

My list isn't re-rendering when I mutate its items, what should I do?

To determine if List should re-render its contents, the component performs a referential equality check on the items array in its shouldComponentUpdate method. This is done to minimize the performance overhead associating with re-rendering the virtualized list pages, as recommended by the React documentation. As a result of this implementation, List will not determine it should re-render if values within the array are mutated. To avoid this problem, we recommend re-creating the items array using a method such as Array.prototype.concat or ES6 spread syntax shown below:

public appendItems(): void {
  const { items } = this.state;

  this.setState({
    items: [...items, ...[{ name: 'Foo' }, { name: 'Bar' }]]
  })
}

public render(): JSX.Element {
  const { items } = this.state;

  return <List items={items} />;
}

Since the items array has been re-created, the list will conclude that its contents have changed and it should re-render the new values.

How do I limit rendering to improve performance?

Performance is important, and DOM content is expensive. Therefore, limit what you render. The list component applies this principle by using UI virtualization. Unlike a simple for loop that renders all items in a set, a list only renders a subset of items, and as you scroll around, the subset of rendered content is shifted. This gives a much better experience for large sets, especially when the per-item components are complex/render-intensive/network-intensive.

A list breaks down the set of items passed in into pages. Only pages within a "materialized window" are actually rendered. As that window changes due to scroll events, pages that fall outside that window are removed, and their layout space is remembered and pushed into spacer elements. This gives the user the experience of browsing massive amounts of content but only using a small number of actual elements. This gives the browser much less layout to resolve, and gives React DOM diffing much less content to worry about.

Note: If onRenderCell is not provided in IListProps, the list will attempt to render the name property for each object in the items array.

Examples

library(shiny)
library(shiny.fluent)

items <- do.call(paste0, replicate(20, sample(LETTERS, 200, TRUE), FALSE))

ui <- function(id) {
  ns <- NS(id)
  div(
    style = "overflow: auto; max-height: 400px",
    List(
      items = items,
      onRenderCell = JS("(item, index) => `${index} ${item}`")
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

MarqueeSelection

Description

The MarqueeSelection component provides a service which allows the user to drag a rectangle to be drawn around items to select them. This works in conjunction with a selection object, which can be used to generically store selection state, separate from a component that consumes the state.

MarqueeSelection also works in conjunction with the AutoScroll utility to automatically scroll the container when we drag a rectangle within the vicinity of the edges.

When a selection rectangle is dragged, we look for elements with the data-selection-index attribute populated. We get these elements' boundingClientRects and compare them with the root's rect to determine selection state. We update the selection state appropriately.

In virtualization cases where items that were once selected are dematerialized, we will keep the item in its previous state until we know definitively if it's on/off. (In other words, this works with List.)

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

MarqueeSelection(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

# This is an advanced demo showing how you can use virtually all features of Fluent UI
# by creating custom components in JS and rendering them with shiny.react.
# This example is a translation of the example in
# https://developer.microsoft.com/en-us/fluentui#/controls/web/marqueeselection.

# Script showing how to:
# 1. Use mergeStyles and themes from Fluent
# 2. Define custom components
# 3. Send results back to Shiny.

customComponent <- function(name, js) {
  dependency <- htmltools::htmlDependency(
    name = name,
    version = "0", # Not used.
    src = c(href = ""), # Not used.
    head = paste0("
      <script>
        (jsmodule.CustomComponents ??= {}).", name, " = (() => {", js, "})();
      </script>
    ")
  )
  function(...) shiny.react::reactElement(
    module = "CustomComponents",
    name = name,
    props = shiny.react::asProps(...),
    deps = dependency
  )
}

MarqueeSelectionExample <- customComponent("MarqueeSelectionExample", "
  const React = jsmodule['react'];
  const Fluent = jsmodule['@fluentui/react'];

  const theme = Fluent.getTheme();
  const styles = Fluent.mergeStyleSets({
    photoList: {
      display: 'inline-block',
      border: '1px solid ' + theme.palette.neutralTertiary,
      margin: 0,
      padding: 10,
      overflow: 'hidden',
      userSelect: 'none',
    },

    photoCell: {
      position: 'relative',
      display: 'inline-block',
      margin: 2,
      boxSizing: 'border-box',
      background: theme.palette.neutralLighter,
      lineHeight: 100,
      verticalAlign: 'middle',
      textAlign: 'center',
      selectors: {
        '&.is-selected': {
          background: theme.palette.themeLighter,
          border: '1px solid ' + theme.palette.themePrimary,
        },
      },
    },
    checkbox: {
      margin: '10px 0',
    },
  });

  const useForceUpdate = () => {
    const [, setIt] = React.useState(false);
    return () => setIt(it => !it);
  };

  return function(params) {
    const forceUpdate = useForceUpdate();
    const inputId = params['inputId'];
    const photos = params['photos'];

    if (window.selection === undefined) {
      window.selection = new Fluent.Selection({
        items: photos,
        onSelectionChanged: function() {
          Shiny.setInputValue(inputId, window.selection.getSelectedIndices());
          forceUpdate();
        }
      });
    }

    const items = photos.map((photo, index) => {
      return React.createElement(
        'div',
        {
          key: index,
          'data-is-focusable': true,
          className: Fluent.css(
            styles.photoCell,
            window.selection.isIndexSelected(index) && 'is-selected'
          ),
          'data-selection-index': index,
          style: { width: photo.width, height: photo.height }
        },
        index
      );
    });

    return React.createElement(
      Fluent.MarqueeSelection,
      { selection: window.selection, isEnabled: true },
      React.createElement('ul', { className: styles.photoList }, items)
    );
  };
")

ui <- function(id) {
  ns <- NS(id)
  tagList(
    textOutput(ns("marqueeResult")),
    Label("Drag a rectangle around the items below to select them"),
    reactOutput(ns("marqueeSelection"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns

    photos <- lapply(1:50, function(index) {
      randomWidth <- 50 + sample.int(150, 1)
      list(
        key = index,
        url = paste0('http://placehold.it/', randomWidth, 'x100'),
        width = randomWidth,
        height = 100
      )
    })

    output$marqueeResult <- renderText({
      paste("You have selected: ", paste(input$selectedIndices, collapse = ", "))
    })

    output$marqueeSelection <- renderReact({
      MarqueeSelectionExample(
        inputId = ns("selectedIndices"),
        photos = photos
      )
    })
  }
)
}
if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

TextField

Description

Text fields (TextField) give people a way to enter and edit text. They’re used in forms, modal dialogs, tables, and other surfaces where text input is required.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

MaskedTextField(...)

TextField(...)

TextField.shinyInput(inputId, ..., value = defaultValue)

updateTextField.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

When it returns string | JSX.Element: - If valid, it returns empty string. - If invalid, it returns the error message and the text field will show a red border and show an error message below the text field.

When it returns ⁠Promise<string | JSX.Element>⁠: - The resolved value is displayed as the error message. - If rejected, the value is thrown away.

(Unless this prop and/or validateOnFocusOut is set to true, validation will run on every change.)

(Unless this prop and/or validateOnFocusIn is set to true, validation will run on every change.)

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

# Example 1
library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    TextField.shinyInput(ns("text")),
    textOutput(ns("textValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$textValue <- renderText({
      sprintf("Value: %s", input$text)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Using custom handler to convert input to uppercase
CustomComponents <- tags$script(HTML("(function() {
  const { InputAdapter } = jsmodule['@/shiny.react'];
  const { TextField } = jsmodule['@fluentui/react'];
  const CustomComponents = jsmodule['CustomComponents'] ??= {};

  CustomComponents.UpperCaseTextField = InputAdapter(TextField, (value, setValue) => ({
    value: value.toUpperCase(),
    onChange: (e, v) => setValue(v.toUpperCase()),
  }));
})();"))

UpperCaseTextField <- function(inputId, ..., value = "") {
  shiny.react::reactElement(
    module = "CustomComponents",
    name = "UpperCaseTextField",
    props = shiny.react::asProps(inputId = inputId, ..., value = value),
    deps = shinyFluentDependency()
  )
}

ui <- function(id) {
  ns <- NS(id)
  tagList(
    CustomComponents,
    UpperCaseTextField(ns("uppercase_text")),
    textOutput(ns("text"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$text <- renderText(input$uppercase_text)
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

MessageBar

Description

A banner (MessageBar) displays errors, warnings, or important information about an open app or file. For example, if a file failed to upload an error message bar should appear.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

MessageBar(...)

MessageBarButton(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

Message bars should include:

Title

Limit titles to 50 characters (including spaces) to leave room for text expansion when translated. People should be able to scan the title to determine the purpose of the message. Capitalize only the first word of the title and any proper nouns.

Body text

Describe the information or error state concisely, ideally in a single sentence. Limit the message to fewer than 512 characters (including spaces) to leave room for text expansion when translated. Include end punctuation for complete sentences.

Action buttons (Optional)

Offer one to two action buttons to help people solve any errors they're receiving. Limit button text to fewer than 50 charactesr (including spaces) to leave room for translation. Action buttons can have any callback attached to them and should provide people with options to address the notification and dismiss the message bar.

Link (Optional)

Don’t use buttons when a subtler link will suffice. Reserve the use of a button for when the MessageBar has a single ”hero” action that is useful at that particular moment. Avoid using more than one button.

Close button

Always offer a quick way for people to close a message bar, unless there is an issue that must be resolved immediately, such as an expired subscription.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  MessageBar("Message")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Description

Modals are temporary pop-ups that take focus from the page or app and require people to interact with them. Unlike a dialog box (Dialog), a modal should be used for hosting lengthy content, such as privacy statements or license agreements, or for asking people to perform complex or multiple actions, such as changing settings.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Modal(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  tagList(
    reactOutput(ns("modal")),
    PrimaryButton.shinyInput(ns("showModal"), text = "Show modal"),
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    modalVisible <- reactiveVal(FALSE)
    observeEvent(input$showModal, modalVisible(TRUE))
    observeEvent(input$hideModal, modalVisible(FALSE))
    output$modal <- renderReact({
      Modal(isOpen = modalVisible(),
        Stack(tokens = list(padding = "15px", childrenGap = "10px"),
          div(style = list(display = "flex"),
            Text("Title", variant = "large"),
            div(style = list(flexGrow = 1)),
            IconButton.shinyInput(
              ns("hideModal"),
              iconProps = list(iconName = "Cancel")
            ),
          ),
          div(
            p("A paragraph of text."),
            p("Another paragraph.")
          )
        )
      )
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Description

Navs (also called "left nav" or "navigation pane") provide links to the main areas of an app or a site. In larger configurations, the Nav is always on-screen, usually on the left of the view. In smaller configurations, the Nav may collapse into a skinnier version or be completely hidden until the user taps an icon.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Nav(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

# Example 1
library(shiny)
library(shiny.fluent)

navigation_styles <- list(
  root = list(
    height = "100%",
    boxSizing = "border-box",
    border = "1px solid #eee",
    overflowY = "auto"
  )
)

link_groups <- list(
  list(
    links = list(
      list(
        name = "Home",
        expandAriaLabel = "Expand Home section",
        collapseAriaLabel = "Collapse Home section",
        links = list(
          list(
            name = "Activity",
            url = "http://msn.com",
            key = "key1",
            target = "_blank"
          ),
          list(
            name = "MSN",
            url = "http://msn.com",
            disabled = TRUE,
            key = "key2",
            target = "_blank"
          )
        ),
        isExpanded = TRUE
      ),
      list(
        name = "Documents",
        url = "http://example.com",
        key = "key3",
        isExpanded = TRUE
      ),
      list(
        name = "Pages",
        url = "http://msn.com",
        key = "key4"
      ),
      list(
        name = "Notebook",
        url = "http://msn.com",
        key = "key5",
        disabled = TRUE
      ),
      list(
        name = "Communication and Media",
        url = "http://msn.com",
        key = "key6"
      ),
      list(
        name = "News",
        url = "http://cnn.com",
        icon = "News",
        key = "key7",
        target = "_blank",
        iconProps = list(
          iconName = "News",
          styles = list(
            root = list(
              fontSize = 20,
              color = "#106ebe"
            )
          )
        )
      )
    )
  )
)

ui <- function(id) {
  ns <- NS(id)
  Nav(
    groups = link_groups,
    selectedKey = "key1",
    styles = navigation_styles
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

# Custom rendering of group headers
navigation_styles <- list(
  root = list(
    height = "100%",
    width = "30%",
    boxSizing = "border-box",
    border = "1px solid #eee",
    overflowY = "auto"
  )
)

link_groups <- list(
  list(
    name = "Pages",
    links = list(
      list(name = "Activity"),
      list(name = "News")
    )
  ),
  list(
    name = "More Pages",
    links = list(
      list(name = "Settings"),
      list(name = "Notes")
    )
  )
)

ui <- function(id) {
  fluidPage(
    Nav(
      groups = link_groups,
      selectedKey = "key1",
      styles = navigation_styles,
      onRenderGroupHeader = JS("group => React.createElement('h3', null, group.name)")
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

OverflowSet

Description

The OverflowSet is a flexible container component that is useful for displaying a primary set of content with additional content in an overflow callout. Note that the example below is only an example of how to render the component, not a specific use case.

Accessibility

By default, the OverflowSet is simply role=group. If you used as a menu, you will need to add role="menubar" and add proper aria roles to each rendered item (menuitem, menuitemcheckbox, menuitemradio)

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

OverflowSet(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

items <- list(
  list(key = "item1", icon = "Add", name = "Link 1"),
  list(key = "item2", icon = "Upload", name = "Link 2"),
  list(key = "item3", icon = "Share", name = "Link 3")
)
overflowItems <- list(
  list(key = "item4", icon = "Mail", name = "Overflow Link 1"),
  list(key = "item5", icon = "Calendar", name = "Overflow Link 2")
)
onRenderItem <- JS("item =>
  jsmodule['react'].createElement(jsmodule['@fluentui/react'].CommandBarButton, {
    role: 'menuitem',
    iconProps: { iconName: item.icon },
    styles: {
      root: { padding: '10px' }
    }
  })
")
onRenderOverflowButton <- JS("overflowItems =>
  jsmodule['react'].createElement(jsmodule['@fluentui/react'].CommandBarButton, {
    role: 'menuitem',
    title: 'More items',
    styles: {
      root: { padding: '10px' }
    },
    menuIconProps: { iconName: 'More' },
    menuProps: { items: overflowItems }
  })
")


ui <- function(id) {
  ns <- NS(id)
  OverflowSet(
    vertical = TRUE,
    items = items,
    overflowItems = overflowItems,
    onRenderItem = onRenderItem,
    onRenderOverflowButton = onRenderOverflowButton
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Overlay

Description

Overlays are used to render a semi-transparent layer on top of existing UI. Overlays help focus the user on the content that sits above the added layer and are often used to help designate a modal or blocking experience. Overlays can be seen used in conjunction with Panels and Dialogs.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Overlay(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DefaultButton.shinyInput(ns("toggleOverlay"), text = "Open Overlay"),
    reactOutput(ns("overlay"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    show <- reactiveVal(FALSE)
    observeEvent(input$toggleOverlay, show(!show()))
    output$overlay <- renderReact({
      if (show()) {
        Overlay(
          onClick = JS(paste0(
            "function() {",
            "  Shiny.setInputValue('", ns("toggleOverlay"), "', Math.random());",
            "}"
          )),
          isDarkThemed = TRUE,
          div(
            style = "background: white; width: 50vw; height: 20rem; margin: auto;",
            div(
              style = "padding: 2rem;",
              h1("Inside Overlay"),
              p("Click anywhere to hide.")
            )
          )
        )
      }
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Panel

Description

Panels are overlays that contain supplementary content and are used for complex creation, edit, or management experiences.  For example, viewing details about an item in a list or editing settings.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Panel(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Header
Body
Footer

Content

Title

⁠[capitalization]⁠: https://docs.microsoft.com/style-guide/capitalization

Button labels

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DefaultButton.shinyInput(ns("showPanel"), text = "Open panel"),
    reactOutput(ns("reactPanel"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    ns <- session$ns
    isPanelOpen <- reactiveVal(FALSE)
    output$reactPanel <- renderReact({
      Panel(
        headerText = "Sample panel",
        isOpen = isPanelOpen(),
        "Content goes here.",
        onDismiss = JS(paste0(
          "function() {",
          "  Shiny.setInputValue('", ns("hidePanel"), "', Math.random());",
          "}"
        ))
      )
    })
    observeEvent(input$showPanel, isPanelOpen(TRUE))
    observeEvent(input$hidePanel, isPanelOpen(FALSE))
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Persona

Description

A persona is a visual representation of a person across products, typically showcasing the image that person has chosen to upload themselves. The control can also be used to show that person's online status.

The complete control inclues an individual's avatar (an uploaded image or a composition of the person’s initials on a background color), their name or identification, and online status.

The persona control is used in the PeoplePicker and Facepile controls.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Persona(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Persona(
    imageInitials = "AL",
    text = "Annie Lindqvist",
    secondaryText = "Software Engineer",
    presence = 4
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Pivot

Description

The Pivot control and related tabs pattern are used for navigating frequently accessed, distinct content categories. Pivots allow for navigation between two or more content views and relies on text headers to articulate the different sections of content.

Tabs are a visual variant of Pivot that use a combination of icons and text or just icons to articulate section content.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Pivot(...)

PivotItem(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Note that unless you have compelling requirements you should not override aria-label.

Examples: completed (4), Unread (99+)

Note: The 'key' from react props cannot be used inside component.

This property is also mutually exclusive with defaultSelectedKey.

This property is also mutually exclusive with defaultSelectedIndex.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Pivot(
    PivotItem(headerText = "Tab 1", Label("Hello 1")),
    PivotItem(headerText = "Tab 2", Label("Hello 2"))
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ProgressIndicator

Description

ProgressIndicators are used to show the completion status of an operation lasting more than 2 seconds. If the state of progress cannot be determined, use a Spinner instead. ProgressIndicators can appear in a new panel, a flyout, under the UI initiating the operation, or even replacing the initiating UI, as long as the UI can return if the operation is canceled or is stopped.

ProgressIndicators feature a bar showing total units to completion, and total units finished. The description of the operation appears above the bar, and the status in text appears below. The description should tell someone exactly what the operation is doing. Examples of formatting include:

Status text is generally in units elapsed and total units. If the operation can be canceled, an “X” icon is used and should be placed in the upper right, aligned with the baseline of the operation name. When an error occurs, replace the status text with the error description using ms-fontColor-redDark.

Real-world examples include copying files to a storage location, saving edits to a file, and more. Use units that are informative and relevant to give the best idea to users of how long the operation will take to complete. Avoid time units as they are rarely accurate enough to be trustworthy. Also, combine steps of a complex operation into one total bar to avoid “rewinding” the bar. Instead change the operation description to reflect the change if necessary. Bars moving backwards reduce confidence in the service.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ProgressIndicator(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  ProgressIndicator(
    label = "Example title",
    description = "Example description"
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Rating

Description

Ratings show people’s opinions of a product, helping others make more informed purchasing decisions. People can also rate products they’ve purchased.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Rating(...)

Rating.shinyInput(inputId, ..., value = defaultValue)

updateRating.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    Rating.shinyInput(ns("rating"), value = 2),
    textOutput(ns("ratingValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$ratingValue <- renderText({
      sprintf("Value: %s", input$rating)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ResizeGroup

Description

ResizeGroup is a React component that can be used to help fit the right amount of content within a container. The consumer of the ResizeGroup provides some initial data, a reduce function, and a render function. The render function is responsible for populating the contents of a the container when given some data. The initial data should represent the data that should be rendered when the ResizeGroup has infinite width. If the contents returned by the render function do not fit within the ResizeGroup, the reduce function is called to get a version of the data whose rendered width should be smaller than the data that was just rendered.

An example scenario is shown below, where controls that do not fit on screen are rendered in an overflow menu. The data in this situation is a list of 'primary' controls that are rendered on the top level and a set of overflow controls rendered in the overflow menu. The initial data in this case has all the controls in the primary set. The implementation of onReduceData moves a control from the overflow well into the primary control set.

This component queries the DOM for the dimensions of elements. Too many of these dimension queries will negatively affect the performance of the component and could cause poor interactive performance on websites. One way to reduce the number of measurements performed by the component is to provide a cacheKey in the initial data and in the return value of onReduceData. Two data objects with the same cacheKey are assumed to have the same width, resulting in measurements being skipped for that data object. In the controls with an overflow example, the cacheKey is simply the concatenation of the keys of the controls that appear in the top level.

There is a boolean context property (isMeasured) added to let child components know if they are only being used for measurement purposes. When isMeasured is true, it will signify that the component is not the instance visible to the user. This will not be needed for most scenarios. It is intended to be used to to skip unwanted side effects of mounting a child component more than once. This includes cases where the component makes API requests, requests focus to one of its elements, expensive computations, and/or renders markup unrelated to its size. Be careful not to use this property to change the components rendered output in a way that effects it size in any way.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ResizeGroup(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

data <- list(
  items = list(
    "many", "strings", "with", "varying", "length", "sometimes", "very", "short",
    "other", "times", "extraordinarily", "long"
  )
)
onRenderData <- JS("data =>
  data.items.map(item =>
    jsmodule['react'].createElement('div',
      {
        style: {
          display: 'inline-block',
          backgroundColor: 'orange',
          padding: '10px',
          margin: '10px',
          fontSize: '20px',
        }
      },
      item
    )
  )
")
onReduceData <- JS("data => ({ items: data.items.slice(0, -1) })")

ui <- function(id) {
  ns <- NS(id)
  div(
    p("Resize the browser to see how the elements are hidden when they do not fit:"),
    ResizeGroup(
      data = data,
      onRenderData = onRenderData,
      onReduceData = onReduceData
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

ScrollablePane

Description

A scrollable pane (ScrollablePane) is a helper component that's used with the Sticky component. It will "stick" to the top or bottom of the scrollable region and remain visible.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

ScrollablePane(...)

Sticky(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

pane <- function(header, paragraphs) (
  div(
    Sticky(
      div(
        style = "background-color: #80CAF1; border-top: 1px solid; border-bottom: 1px solid",
        header
      )
    ),
    stringi::stri_rand_lipsum(paragraphs)
  )
)

ui <- function(id) {
  ns <- NS(id)
  ScrollablePane(
    styles = list(
      root = list(position = "relative", height = "500px", width = "400px")
    ),
    pane("Some text", 3),
    pane("A lot of text", 5),
    pane("Just a short ending", 1)
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Description

A search box (SearchBox) provides an input field for searching content within a site or app to find specific items.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

SearchBox(...)

SearchBox.shinyInput(inputId, ..., value = defaultValue)

updateSearchBox.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    SearchBox.shinyInput(ns("search"), placeholder = "Search"),
    textOutput(ns("searchValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$searchValue <- renderText({
      sprintf("Value: %s", input$search)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Separator

Description

A separator visually separates content into groups.

You can render content in the separator by specifying the component's children. The component's children can be plain text or a component like Icon. The content is center-aligned by default.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Separator(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Separator("Text")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Shimmer

Description

Shimmer is a temporary animation placeholder for when a service call takes time to return data and we don't want to block rendering the rest of the UI.

If a smooth transition from Shimmer to content is desired, wrap the content node with a Shimmer element and use the isDataLoaded prop to trigger the transition. In cases where the content node is not wrapped in a Shimmer, use the shimmerElements or customElementsGroup props, and once data arrives, manually replace the Shimmer UI with the intended content. See the examples below for reference.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Shimmer(...)

ShimmerElementsGroup(...)

ShimmeredDetailsList(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  tagList(
    div(
      p("Basic Shimmer with no elements provided. It defaults to a line of 16px height."),
      Shimmer(),
      Shimmer(width = "75%"),
      Shimmer(width = "50%")
    ),
    tags$head(tags$style(
      ".ms-Shimmer-container { margin: 10px 0 }"
    ))
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Slider

Description

A slider provides a visual indication of adjustable content, as well as the current setting in the total range of content. Use a slider when you want people to set defined values (such as volume or brightness), or when people would benefit from instant feedback on the effect of setting changes.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Slider(...)

Slider.shinyInput(inputId, ..., value = defaultValue)

updateSlider.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    Slider.shinyInput(ns("slider"), value = 0, min = -100, max = 100),
    textOutput(ns("sliderValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$sliderValue <- renderText({
      sprintf("Value: %s", input$slider)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

SpinButton

Description

A spin button (SpinButton) allows someone to incrementally adjust a value in small steps. It’s mainly used for numeric values, but other values are supported too.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

SpinButton(...)

SpinButton.shinyInput(inputId, ..., value = defaultValue)

updateSpinButton.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Use this if you intend for the SpinButton to be an uncontrolled component which maintains its own value. Mutually exclusive with value.

Note: The buttons are in a checked state when arrow keys are used to incremenent/decrement the SpinButton. Use rootChecked instead of rootPressed for styling when that is the case.

The default is calculated based on the precision of step: i.e. if step = 1, precision = 0. step = 0.0089, precision = 4. step = 300, precision = 2. step = 23.00, precision = 2.

Note: The buttons are in a checked state when arrow keys are used to incremenent/decrement the SpinButton. Use rootChecked instead of rootPressed for styling when that is the case.

Use this if you intend to pass in a new value as a result of change events. Mutually exclusive with defaultValue.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    SpinButton.shinyInput(ns("spin"), value = 15, min = 0, max = 50, step = 5),
    textOutput(ns("spinValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$spinValue <- renderText({
      sprintf("Value: %s", input$spin)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Spinner

Description

A Spinner is an outline of a circle which animates around itself indicating to the user that things are processing. A Spinner is shown when it's unsure how long a task will take making it the indeterminate version of a ProgressIndicator. They can be various sizes, located inline with content or centered. They generally appear after an action is being processed or committed. They are subtle and generally do not take up much space, but are transitions from the completed task.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Spinner(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Spinner(size = 3, label = "Loading, please wait...")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Stack

Description

A Stack is a container-type component that abstracts the implementation of a flexbox in order to define the layout of its children components.

Stack Properties

Although the Stack component has a number of different properties, there are three in particular that define the overall layout that the component has:

  1. Direction: Refers to whether the stacking of children components is horizontal or vertical. By default the Stack component is vertical, but can be turned horizontal by adding the horizontal property when using the component.

  2. Alignment: Refers to how the children components are aligned inside the container. This is controlled via the verticalAlign and horizontalAlign properties. One thing to notice here is that while flexbox containers align always across the cross axis, Stack aims to remove the mental strain involved in this process by making the verticalAlign and horizontalAlign properties always follow the vertical and horizontal axes, respectively, regardless of the direction of the Stack.

  3. Spacing: Refers to the space that exists between children components inside the Stack. This is controlled via the gap and verticalGap properties.

Stack Items

The Stack component provides an abstraction of a flexbox container but there are some flexbox related properties that are applied on specific children of the flexbox instead of being applied on the container. This is where ⁠Stack Items⁠ comes into play.

A ⁠Stack Item⁠ abstracts those properties that are or can be specifically applied on flexbox's children, like grow and shrink.

To use a ⁠Stack Item⁠ in an application, the Stack component should be imported and Stack.Item should be used inside of a Stack. This is done so that the existence of the ⁠Stack Item⁠ is inherently linked to the Stack component.

Stack Wrapping

Aside from the previously mentioned properties, there is another property called wrap that determines if items overflow the Stack container or wrap around it. The wrap property only works in the direction of the Stack, which means that the children components can still overflow in the perpendicular direction (i.e. in a ⁠Vertical Stack⁠, items might overflow horizontally and vice versa).

Stack Nesting

Stacks can be nested inside one another in order to be able to configure the layout of the application as desired.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Stack(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Stack(
    tokens = list(childrenGap = 10),
    reversed = TRUE,
    span("Item One"),
    span("Item Two"),
    span("Item Three")
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

SwatchColorPicker

Description

A swatch color picker (SwatchColorPicker) displays color options as a grid. It can be shown by itself, with a header and dividers, or as a button that expands to show the swatch color picker.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

SwatchColorPicker(...)

SwatchColorPicker.shinyInput(inputId, ..., value = defaultValue)

updateSwatchColorPicker.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Note: When the reference to this prop changes, regardless of how many color cells change, all of the color cells will be re-rendered (potentially bad perf) because we memoize based on this prop's reference.

NOTE: This property is a temporary workaround to force the component to be fully controllable without breaking existing behavior

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Examples

library(shiny)
library(shiny.fluent)

colorCells <- list(
  list(id = "orange", color = "#ca5010"),
  list(id = "cyan", color = "#038387"),
  list(id = "blueMagenta", color = "#8764b8"),
  list(id = "magenta", color = "#881798"),
  list(id = "white", color = "#ffffff")
)

ui <- function(id) {
  ns <- NS(id)
  div(
    SwatchColorPicker.shinyInput(ns("color"), value = "orange",
      colorCells = colorCells, columnCount = length(colorCells)
    ),
    textOutput(ns("swatchValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$swatchValue <- renderText({
      sprintf("Value: %s", input$color)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

TeachingBubble

Description

A teaching bubble (TeachingBubble) brings attention to a new or important feature, with the goal of increasing engagement with the feature. A teaching bubble typically follows a coach mark.

Use teaching bubbles sparingly. Consider how frequently people will see it, and how many they’ll see across their entire experience.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

TeachingBubble(...)

TeachingBubbleContent(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Layout

Content

A teaching bubble should include:

Title

You have 25 characters (including spaces) to draw people in and get them interested. Limit to one line of text, and use sentence casing (capitalize only the first word and any proper nouns) with no punctuation.

Body copy

Lead with why the feature is useful rather than describe what it is. What does it make possible? Keep it within 120 characters (including spaces).

Action buttons

Limit button labels to 15 characters (including spaces). Provide people with an explicit action to dismiss the teaching bubble, such as “Got it”. Include a secondary button to give people the option to take action, such as “Show me” or “Edit settings”. When two buttons are needed, make the call-to-action button the primary button and the dismissal button (such as “No thanks”) the secondary button. Use sentence casing (capitalize only the first word and any proper nouns) with no punctuation. On a sequenced teaching bubble, use "Next" for the action button label and "Got it" for the final sequenced teaching bubble action button with text that closes the experience.

Link (Optional)

If there are additional steps people need to know about, or helpful information they may want to read, consider linking to a help article. Typically, these links are labeled “Learn more” with no punctuation at the end.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    DefaultButton.shinyInput(
      ns("toggleTeachingBubble"),
      id = "target",
      text = "Toggle TeachingBubble"
    ),
    reactOutput(ns("teachingBubble"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    showBubble <- reactiveVal(FALSE)
    observeEvent(input$toggleTeachingBubble, showBubble(!showBubble()))
    output$teachingBubble <- renderReact({
      if (showBubble()) {
        TeachingBubble(
          target = "#target",
          headline = "Very useful!"
        )
      }
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Text

Description

Text is a component for displaying text. You can use Text to standardize text across your web app.

You can specify the variant prop to apply font styles to Text. This variant pulls from the Fluent UI React theme loaded on the page. If you do not specify the variant prop, by default, Text applies the styling from specifying the variant value to medium.

The Text control is inline wrap by default. You can specify block to enable block and nowrap to enable nowrap. For ellipsis on overflow to work properly, block and nowrap should be manually set to true.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Text(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

Note that in order for ellipsis on overflow to work properly, block and nowrap should be set to true.

Note that in order for ellipsis on overflow to work properly, block and nowrap should be set to true.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  Text(variant = "xLarge", "Some text with a nice Fluent UI font")
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Theme

Description

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

ThemeProvider is a utility that applies contextual theming to its child components. See the official docs for details.

Usage

ThemeProvider(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Examples

# Example 1
library(shiny)
library(shiny.fluent)

options <- list(
  list(key = "A", text = "Option A"),
  list(key = "B", text = "Option B")
)
theme <- list(
  palette = list(
    themePrimary = "#8dd400",
    themeLighterAlt = "#060800",
    themeLighter = "#172200",
    themeLight = "#2a3f00",
    themeTertiary = "#557f00",
    themeSecondary = "#7cba00",
    themeDarkAlt = "#97d816",
    themeDark = "#a6de35",
    themeDarker = "#bce766",
    neutralLighterAlt = "#323130",
    neutralLighter = "#31302f",
    neutralLight = "#2f2e2d",
    neutralQuaternaryAlt = "#2c2b2a",
    neutralQuaternary = "#2a2928",
    neutralTertiaryAlt = "#282726",
    neutralTertiary = "#c8c8c8",
    neutralSecondary = "#d0d0d0",
    neutralPrimaryAlt = "#dadada",
    neutralPrimary = "#ffffff",
    neutralDark = "#f4f4f4",
    black = "#f8f8f8",
    white = "#323130"
  )
)

ui <- function(id) {
  ns <- NS(id)
  ThemeProvider(
    theme = theme,
    Stack(
      tokens = list(childrenGap = "10px"),
      style = list(width = 250),
      PrimaryButton(text = "PrimaryButton"),
      Checkbox(label = "Checkbox"),
      ChoiceGroup(label = "ChoiceGroup", options = options)
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

# Example 2
library(shiny)
library(shiny.fluent)

options <- list(
  list(key = "A", text = "Option A"),
  list(key = "B", text = "Option B")
)

# Use JSON created in Theme Designer
# https://fabricweb.z5.web.core.windows.net/pr-deploy-site/refs/heads/master/theming-designer/
theme <- '{
  "themePrimary": "#324f09",
  "themeLighterAlt": "#dfead1",
  "themeLighter": "#c4d7ab",
  "themeLight": "#abc388",
  "themeTertiary": "#92b069",
  "themeSecondary": "#7c9c4e",
  "themeDarkAlt": "#678937",
  "themeDark": "#547624",
  "themeDarker": "#426214",
  "neutralLighterAlt": "#f8ebce",
  "neutralLighter": "#f4e8cb",
  "neutralLight": "#eadec2",
  "neutralQuaternaryAlt": "#dacfb5",
  "neutralQuaternary": "#d0c5ad",
  "neutralTertiaryAlt": "#c8bea6",
  "neutralTertiary": "#595858",
  "neutralSecondary": "#373636",
  "neutralPrimaryAlt": "#2f2e2e",
  "neutralPrimary": "#000000",
  "neutralDark": "#151515",
  "black": "#0b0b0b",
  "white": "#fff2d4"
}'

ui <- function(id) {
  ns <- NS(id)
  ThemeProvider(
    theme = parseTheme(json = theme),
    Stack(
      tokens = list(childrenGap = "10px"),
      style = list(width = 250),
      PrimaryButton(text = "PrimaryButton"),
      Checkbox(label = "Checkbox"),
      ChoiceGroup(label = "ChoiceGroup", options = options)
    )
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Toggle

Description

A toggle represents a physical switch that allows someone to choose between two mutually exclusive options.  For example, “On/Off”, “Show/Hide”. Choosing an option should produce an immediate result.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

Toggle(...)

Toggle.shinyInput(inputId, ..., value = defaultValue)

updateToggle.shinyInput(
  session = shiny::getDefaultReactiveDomain(),
  inputId,
  ...
)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

Details

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).

Best practices

Layout

Content

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  div(
    Toggle.shinyInput(ns("toggle"), value = TRUE),
    textOutput(ns("toggleValue"))
  )
}

server <- function(id) {
  moduleServer(id, function(input, output, session) {
    output$toggleValue <- renderText({
      sprintf("Value: %s", input$toggle)
    })
  })
}

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Tooltip

Description

A good tooltip briefly describes unlabeled controls or provides a bit of additional information about labeled controls, when this is useful. It can also help customers navigate the UI by offering additional—not redundant—information about control labels, icons, and links. A tooltip should always add valuable information; use sparingly.

There are two components you can use to display a tooltip:

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

TooltipHost(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Details

If set, only show the tooltip if the specified element (Self or Parent) has overflow. When set to Parent, the parent element is also used as the tooltip's target element.

Note that even with Self mode, the TooltipHost does not check whether any children have overflow.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Content

For a UI label that needs some explanation:

For a truncated label or a label that’s likely to truncate in some languages:

Examples

library(shiny)
library(shiny.fluent)

ui <- function(id) {
  ns <- NS(id)
  TooltipHost(
    content = "This is the tooltip content",
    delay = 0,
    Text("Hover over me")
  )
}

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

if (interactive()) {
  shinyApp(ui("app"), function(input, output) server("app"))
}

Divider

Description

A Divider is a line that is used to visually differentiate different parts of a UI. They are commonly used in headers and command bars. This divider automatically center algins itself within the parent container and can be customized to be shown in different heights and colors.

For more details and examples visit the official docs. The R package cannot handle each and every case, so for advanced use cases you need to work using the original docs to achieve the desired result.

Usage

VerticalDivider(...)

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.

Best practices

Use a divider component to show a sectional or continuity change in the content between two blocks of information. The spacing around the divider is generally determined by the content surrounding it.

There are two recommended divider color combinations:

  1. #C8C8C8/neutralTertiaryAlt divider when used within an #F4F4F4/neutralLighter layout

  2. #EAEAEA/neutralLight divider when used within an #FFFFFF/white layout


Documentation template for remaining components

Description

Documentation template for remaining components

Arguments

...

Props to pass to the component. The allowed props are listed below in the Details section.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app.


Basic Fluent UI page

Description

Creates a Fluent UI page with sensible defaults (included Fabric CSS classes, proper class given to the body tag, suppressed Bootstrap).

Usage

fluentPage(..., suppressBootstrap = TRUE)

Arguments

...

The contents of the document body.

suppressBootstrap

Whether to suppress Bootstrap.

Details

The Bootstrap library is suppressed by default, as it doesn't work well with Fluent UI in general.

Value

Object which can be passed as the UI of a Shiny app.


A dataset of sample people based on Fluent UI examples

Description

A dataset of sample people based on Fluent UI examples

Usage

fluentPeople

Format

An object of class tbl_df (inherits from tbl, data.frame) with 7 rows and 11 columns.

Source

https://developer.microsoft.com/en-us/fluentui#/controls/web/peoplepicker


A randomly generated dataset of imaginary sales deals

Description

Sales deals to Top 10 companies from the Fortune 500 dataset (located at https://hifld-geoplatform.opendata.arcgis.com/datasets/fortune-500-corporate-headquarters) are randomly generated for each person in fluentPeople.

Usage

fluentSalesDeals

Format

An object of class tbl_df (inherits from tbl, data.frame) with 100 rows and 30 columns.


parseTheme

Description

Reads a theme JSON generated by Theme Designer: https://fabricweb.z5.web.core.windows.net/pr-deploy-site/refs/heads/master/theming-designer/ and parses it to an object digestable by ThemeProvider

Usage

parseTheme(path = NULL, json = NULL)

Arguments

path

A path to JSON file containing the theme created in Theme Designer

json

A JSON string containing the theme created in Theme Designer

Value

A list with Fluent theme that can be used in ThemeProvider

See Also

ThemeProvider() for usage of this function


Objects exported from other packages

Description

These objects are imported from other packages. Follow the links below to see their documentation.

shiny.react

JS, reactOutput, renderReact, setInput, triggerEvent


Run example shiny.fluent apps.

Description

Based on shiny::runExample, and takes the same arguments.

Usage

runExample(
  example = NA,
  port = getOption("shiny.port"),
  launch.browser = getOption("shiny.launch.browser", interactive()),
  host = getOption("shiny.host", "127.0.0.1"),
  display.mode = c("auto", "normal", "showcase")
)

Arguments

example

Example to run. NA to list the examples.

port

The TCP port that the application should listen on

launch.browser

Whether to open the app in a browser

host

The IPv4 address to listen on.

display.mode

Display mode for the app.

Value

This function normally does not return; interrupt R to stop the application (usually by pressing Ctrl+C or Esc).


Shiny Fluent JS dependency

Description

Shiny Fluent JS dependency

Usage

shinyFluentDependency()

Value

HTML dependency object.


Documentation template for components with .shinyInput wrappers

Description

Documentation template for components with .shinyInput wrappers

Arguments

inputId

ID of the component.

value

Starting value.

session

Object passed as the session argument to Shiny server.

...

Props to pass to the component. The allowed props are listed below in the Details section.

Value

Object with shiny.tag class suitable for use in the UI of a Shiny app. The update functions return nothing (called for side effects).