The goal of micromodal is to create simple and elegant modal dialogs which are WAI-ARIA guidelines compliant with minimal configuration.
Things to keep in mind:
data-micromodal-trigger
with a value of the
modal’s id. So if the modal has the id “modal-1”, then you will
have:data-micromodal-close
. In
{shiny}
this is the equivalent of:See live demo here.
Though a bit long, this example clearly depicts all there is to know
about using {micromodal}
.
library(shiny)
library(micromodal)
server <- \(input, output, session) {
}
ui <- bslib::page(
title = "Micromodal",
theme = bslib::bs_theme(version = 5),
# inform shiny to use {micromodal}:
use_micromodal(),
# your normal UI code:
tags$div(
class = "container",
tags$div(
class = "container my-5",
tags$h1("Micromodal.js in Shiny", class = "mb-5"),
# trigger for "modal-1"
actionButton(
inputId = "show_modal_1",
label = "Exhibit 1",
class = "btn-outline-primary px-3",
`data-micromodal-trigger` = "modal-1"
),
# trigger for "modal-2"
actionButton(
inputId = "show_modal_2",
label = "Exhibit 2",
class = "btn-outline-primary px-3",
`data-micromodal-trigger` = "modal-2"
)
),
# modal-1:
micromodal(
id = "modal-1",
title = "Login",
content = tagList(
textInput(
inputId = "name",
label = "Name",
width = "400px"
),
passwordInput(
inputId = "password",
label = tags$div(
tags$span("Password"),
tags$span("(required)", class = "text-muted fw-light")
),
width = "400px"
) |> tagAppendAttributes(class = "mb-0"),
tags$div(
"Must be atleast 6 characters long.",
class = "text-muted fw-light"
)
),
footer = tagList(
tags$button(
class = "modal__btn modal__btn-primary",
"Continue"
),
tags$a(
href = "#",
class = "ms-3",
`data-micromodal-close` = NA,
`aria-label` = "Close this dialog window",
"Cancel"
)
)
),
# modal-2:
micromodal(
id = "modal-2",
title = "Micromodal",
content = tagList(
tags$p("This is a completely accessible modal."),
tags$p(
"Try hitting the",
tags$code("tab"),
"key* and notice how the focus stays",
"within the modal itself. To close modal hit the",
tags$code("esc"),
"button, click on the overlay or just click the close button."
),
tags$p("*", tags$code("alt + tab"), "in safari")
),
footer = tagList(
tags$button(
class = "modal__btn modal__btn-primary",
"Continue"
),
tags$button(
class = "modal__btn ms-2",
`data-micromodal-close` = NA,
`aria-label` = "Close this dialog window",
"Close"
)
)
)
)
)
shinyApp(ui, server)
If need be, you can render the modal and it’s trigger dynamically.
library(shiny)
library(micromodal)
ui <- fluidPage(
use_micromodal(),
selectInput(
inputId = "selector",
label = "Pick a letter",
choices = letters
),
actionButton(
inputId = "trigger",
label = "Trigger modal",
`data-micromodal-trigger` = "modal-1"
),
uiOutput(outputId = "mymodal")
)
server <- \(input, output, session) {
output$mymodal <- renderUI({
tagList(
micromodal(
id = "modal-1",
title = "Rendered serverside",
content = tagList(
tags$p(
"You selected the letter '",
input$selector,
"'"
)
)
)
)
})
}
shinyApp(ui, server)
library(shiny)
library(micromodal)
ui <- fluidPage(
use_micromodal(),
selectInput(
inputId = "selector",
label = "Pick a letter",
choices = letters
),
uiOutput(outputId = "mymodal")
)
server <- \(input, output, session) {
output$mymodal <- renderUI({
tagList(
actionButton(
inputId = "trigger",
label = "Trigger modal",
`data-micromodal-trigger` = "modal-1"
),
micromodal(
id = "modal-1",
title = "Rendered serverside",
content = tagList(
tags$p(
"You selected the letter '",
input$selector,
"'"
)
)
)
)
})
}
shinyApp(ui, server)
NB: micromodal might not work with other *Output
+ render*
eg. plotOutput()
As far as usage of {micromodal}
in modules is concerned,
I only need to remind you of one thing:
It’s always a missing call to
NS()
Thank me later.
library(shiny)
library(micromodal)
# module UI:
sayhi_ui <- \(id) {
ns <- NS(id)
tagList(
tags$h1("Hello"),
actionLink(
inputId = ns("sayhi"),
label = "Say Hi",
`data-micromodal-trigger` = ns("greetings_modal")
),
micromodal(
id = ns("greetings_modal"),
title = "Greetings folks!",
content = tags$p(
"I'd like to thank you for joining us here today."
)
)
)
}
# module server is not necessary in our case, just putting it here
# for formality:
sayhi_server <- \(id) {
moduleServer(
id = id,
module = \(input, output, session) {
}
)
}
ui <- bslib::page(
title = "In Modules",
theme = bslib::bs_theme(version = 5),
use_micromodal(),
tags$div(
class = "container",
sayhi_ui("hi")
)
)
server <- \(input, output, session) {}
shinyApp(ui, server)