# Introduction to micromodal

## Getting started

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:

1. The modal’s trigger (usually a button or a link) must have the attribute `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-trigger` = "modal-1"

2. If you need to add something to dismiss the modal (eg. button or link), give it the attribute `data-micromodal-close`. In `{shiny}` this is the equivalent of:

    `data-micromodal-close` = NA

## Examples

See live demo here.

### Simple usage

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)

### With uiOutput + renderUI

If need be, you can render the modal and it’s trigger dynamically.

#### I. Render modal

    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)

#### II. Render modal + trigger

    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()`

### Inside modules

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)