Skip to content

Latest commit

 

History

History
920 lines (732 loc) · 19.2 KB

File metadata and controls

920 lines (732 loc) · 19.2 KB

shinyModals Complete Guide

A comprehensive guide to using the shinyModals R package for building modern, interactive modal dialogs in Shiny applications.

Table of Contents

  1. Getting Started
  2. Basic Usage
  3. Modal Components
  4. Modal Features
  5. Themes
  6. Notifications
  7. Advanced Examples
  8. API Reference

Getting Started

Installation

# Install from local source
devtools::install_local("path/to/shinyModals")

# Or from GitHub (if published)
# devtools::install_github("username/shinyModals")

Setup in Your App

Every Shiny app using shinyModals must call use_shiny_modals() once in the UI:

library(shiny)
library(shinyModals)

ui <- fluidPage(
  use_shiny_modals(),  # Initialize modals
  
  # Your app content here
  actionButton("show_modal", "Open Modal")
)

server <- function(input, output, session) {
  # Your server logic here
}

shinyApp(ui, server)

Basic Usage

Creating and Showing a Modal

ui <- fluidPage(
  use_shiny_modals(),
  
  actionButton("show_modal", "Show Modal"),
  
  shiny_modal(
    id = "my_modal",
    header = modal_header("Welcome"),
    body = modal_body(p("This is a simple modal")),
    footer = modal_footer(
      actionButton("close_btn", "Close", class = "btn-primary")
    )
  )
)

server <- function(input, output, session) {
  observeEvent(input$show_modal, {
    show_modal("my_modal")
  })
  
  observeEvent(input$close_btn, {
    hide_modal("my_modal")
  })
}

Modal Control Functions

# Show a modal
show_modal("my_modal")

# Hide a modal
hide_modal("my_modal")

# Toggle a modal (show if hidden, hide if shown)
toggle_modal("my_modal")

# Hide all open modals
hide_all_modals()

Modal Components

Header Component

The header appears at the top of the modal. It typically contains a title and close button.

modal_header(
  title = "Modal Title",
  icon = icon("star"),        # Optional: add an icon
  close_button = TRUE         # Optional: show/hide close button (default: TRUE)
)

Parameters:

  • title (character): The header text
  • icon (shiny.tag, optional): An icon from Font Awesome using icon()
  • close_button (logical): Whether to show the × button (default: TRUE)

Examples:

# Simple header
modal_header("Settings")

# Header with icon
modal_header("User Profile", icon = icon("user"))

# Header without close button
modal_header("Important", close_button = FALSE)

Body Component

The body contains the main content of the modal. It can include any Shiny UI elements.

modal_body(
  h3("Content Title"),
  p("This is the main content of the modal."),
  textInput("name", "Enter your name"),
  # Any Shiny UI elements
)

Features:

  • Overflow control (scrollable content)
  • Flexible sizing
  • Supports any Shiny input/output widgets

Footer Component

The footer typically contains action buttons.

modal_footer(
  actionButton("confirm", "Confirm", class = "btn-primary"),
  actionButton("cancel", "Cancel", class = "btn-secondary")
)

Tips:

  • Use class = "btn-primary" for primary actions (green)
  • Use class = "btn-secondary" for secondary actions (gray)
  • Use class = "btn-danger" for destructive actions (red)
  • Leave empty for no footer

Modal Features

Size Control

Control the width of your modal with preset sizes or custom values.

# Using preset sizes
shiny_modal(
  id = "large_modal",
  header = modal_header("Large Modal"),
  body = modal_body("Content"),
  size = "l"  # Options: "xs", "s", "m", "l", "xl"
)

# Custom sizes
shiny_modal(
  id = "custom_modal",
  header = modal_header("Custom Size"),
  body = modal_body("Content"),
  size = "600px"  # Any CSS width value: px, %, vw, etc.
)

Preset Sizes:

  • "xs" - 300px (very small)
  • "s" - 450px (small)
  • "m" - 600px (medium, default)
  • "l" - 800px (large)
  • "xl" - 1000px (extra large)

Position Control

Display modals from different positions on the screen.

shiny_modal(
  id = "positioned_modal",
  header = modal_header("Title"),
  body = modal_body("Content"),
  position = "top"  # Options: "center", "left", "right", "top", "bottom"
)

Positions:

  • "center" - Center of screen (default)
  • "top" - Top of screen
  • "bottom" - Bottom of screen
  • "left" - Left side of screen
  • "right" - Right side of screen

Backdrop Effects

Control the background appearance when a modal is open.

shiny_modal(
  id = "modal_with_backdrop",
  header = modal_header("Title"),
  body = modal_body("Content"),
  backdrop_effect = "blur"  # Options: "fade", "blur", "none"
)

Effects:

  • "fade" - Darken the background (default)
  • "blur" - Blur the background (modern look)
  • "none" - No effect on background

Animations

Choose how the modal appears.

shiny_modal(
  id = "animated_modal",
  header = modal_header("Title"),
  body = modal_body("Content"),
  animation = "scale"  # Options: "fade", "scale", "slide"
)

Animations:

  • "fade" - Simple fade in
  • "scale" - Grow from center
  • "slide" - Slide up from bottom

Overflow Control

Control how content behaves when it exceeds the modal height.

shiny_modal(
  id = "scrollable_modal",
  header = modal_header("Title"),
  body = modal_body(
    # Long content here
    p(paste(rep("Lorem ipsum dolor sit amet...", 50), collapse = "\n"))
  ),
  overflow = "auto"  # Options: "auto", "scroll", "hidden", "visible"
)

Options:

  • "auto" - Scrollbar appears only when needed (default)
  • "scroll" - Always show scrollbar
  • "hidden" - No scrollbar, content clips
  • "visible" - Content can overflow modal bounds

Draggable Modals

Allow users to drag the modal around the screen.

shiny_modal(
  id = "draggable_modal",
  header = modal_header("Drag me!"),
  body = modal_body("Click the header and drag"),
  draggable = TRUE
)

Features:

  • Click and hold the header to drag
  • Position resets when modal reopens
  • Works with all other features

Close on Backdrop Click

Control whether clicking outside the modal closes it.

shiny_modal(
  id = "modal",
  header = modal_header("Title"),
  body = modal_body("Content"),
  close_on_backdrop_click = TRUE  # Default: TRUE
)

ESC Key Support

The ESC key always closes modals (built-in).


Themes

Preset Themes

Choose from 12 beautiful pre-designed themes:

shiny_modal(
  id = "themed_modal",
  header = modal_header("Themed Modal"),
  body = modal_body("This modal uses a preset theme"),
  theme = modal_theme_preset("ocean")
)

Available Themes:

  1. default - Clean, minimal design
  2. dark - Dark background with light text
  3. ocean - Blue gradient, calm feel
  4. sunset - Orange/red gradient, warm
  5. forest - Green tones, natural look
  6. minimal - Ultra-clean, white on white
  7. neon - Bright colors, modern
  8. corporate - Professional blue, business
  9. warm - Amber/orange tones, inviting
  10. cool - Cyan/blue tones, fresh
  11. rose - Pink/rose tones, elegant
  12. glass - Glassmorphism effect, transparent

Custom Themes

Create your own theme using CSS variables:

custom_theme <- modal_theme(
  header_bg = "#2c3e50",           # Header background color
  header_text = "white",            # Header text color
  body_bg = "#ecf0f1",             # Body background color
  body_text = "#2c3e50",           # Body text color
  border_color = "#34495e",        # Border color
  border_radius = "8px",           # Corner rounding
  shadow = "0 10px 30px rgba(0,0,0,0.3)"  # Box shadow
)

shiny_modal(
  id = "custom_modal",
  header = modal_header("Custom Theme"),
  body = modal_body("Your content"),
  theme = custom_theme
)

Notifications

Notifications are pre-styled modals for common user messages.

Success Notification

Used for successful operations:

notification_success(
  id = "success_notif",
  title = "Success!",
  message = "Your changes have been saved.",
  button_text = "OK",
  position = "center",
  glow = FALSE
)

# In server:
observeEvent(input$show_success, {
  show_modal("success_notif")
})

Features:

  • Green header with checkmark icon
  • Auto-dismiss option (closes after 5 seconds)
  • Optional glow effect

Error Notification

Used for error messages:

notification_error(
  id = "error_notif",
  title = "Error",
  message = "Something went wrong. Please try again.",
  button_text = "Dismiss",
  glow = TRUE  # Use glow for emphasis
)

Features:

  • Red header with X icon
  • Perfect for critical errors
  • Glow effect draws attention

Warning Notification

Used for warnings:

notification_warning(
  id = "warning_notif",
  title = "Warning",
  message = "This action will delete 5 items. Continue?",
  button_text = "I understand"
)

Features:

  • Amber/orange header with alert icon
  • Good for cautionary messages

Info Notification

Used for information:

notification_info(
  id = "info_notif",
  title = "Information",
  message = "New features are available. Update your app.",
  button_text = "Learn More",
  auto_dismiss = TRUE
)

Features:

  • Blue header with info icon
  • Can auto-dismiss for non-critical messages

Confirmation Notification

Used for yes/no decisions:

notification_confirm(
  id = "confirm_notif",
  title = "Delete Item?",
  message = "Are you sure? This cannot be undone.",
  confirm_text = "Yes, Delete",
  cancel_text = "No, Cancel",
  glow = TRUE
)

# In server:
observeEvent(input$confirm_notif_confirm, {
  # Handle confirmation
  showNotification("Item deleted!", type = "message")
  hide_modal("confirm_notif")
})

observeEvent(input$confirm_notif_cancel, {
  hide_modal("confirm_notif")
})

Features:

  • Blue header with question icon
  • Two buttons: confirm and cancel
  • Input IDs: {id}_confirm and {id}_cancel

Custom Buttons

Override default notification buttons with custom Shiny buttons:

notification_success(
  id = "custom_buttons_notif",
  title = "Success!",
  message = "What would you like to do next?",
  buttons = list(
    actionButton("btn_home", "Go Home", class = "btn-primary"),
    actionButton("btn_edit", "Edit Item", class = "btn-info"),
    actionButton("btn_close", "Close", class = "btn-secondary")
  )
)

# In server:
observeEvent(input$btn_home, {
  hide_modal("custom_buttons_notif")
  # Navigate home
})

observeEvent(input$btn_edit, {
  hide_modal("custom_buttons_notif")
  # Open edit modal
})

Notification Parameters

All notifications support:

Parameter Type Default Description
id character Required Unique modal identifier
title character Required Notification title
message character Required Main message
button_text character "OK" Text for dismiss button
auto_dismiss logical FALSE Auto-close after 5 seconds
position character "center" Modal position
glow logical FALSE Add pulsing glow effect
buttons list NULL Custom button list (overrides button_text)

Advanced Examples

Modal with Input Validation

ui <- fluidPage(
  use_shiny_modals(),
  
  actionButton("show_form", "Show Form"),
  
  shiny_modal(
    id = "form_modal",
    header = modal_header("User Form"),
    body = modal_body(
      textInput("username", "Username", placeholder = "Enter username"),
      textInput("email", "Email", placeholder = "Enter email"),
      textOutput("validation_message")
    ),
    footer = modal_footer(
      actionButton("submit_form", "Submit", class = "btn-primary"),
      actionButton("cancel_form", "Cancel", class = "btn-secondary")
    ),
    theme = modal_theme_preset("ocean")
  )
)

server <- function(input, output, session) {
  observeEvent(input$show_form, {
    show_modal("form_modal")
  })
  
  observeEvent(input$submit_form, {
    # Validate inputs
    if (input$username == "") {
      output$validation_message <- renderText("Please enter username")
      return()
    }
    
    if (!grepl("^[^@]+@[^@]+$", input$email)) {
      output$validation_message <- renderText("Invalid email format")
      return()
    }
    
    # Valid - submit
    showNotification("Form submitted!", type = "message")
    hide_modal("form_modal")
  })
  
  observeEvent(input$cancel_form, {
    hide_modal("form_modal")
  })
}

Nested Modals (Stacking)

ui <- fluidPage(
  use_shiny_modals(),
  
  actionButton("open_1", "Open Modal 1"),
  
  shiny_modal(
    id = "modal_1",
    header = modal_header("Modal 1"),
    body = modal_body(
      p("This is the first modal"),
      actionButton("open_2", "Open Modal 2")
    ),
    footer = modal_footer(
      actionButton("close_1", "Close", class = "btn-primary")
    )
  ),
  
  shiny_modal(
    id = "modal_2",
    header = modal_header("Modal 2"),
    body = modal_body(
      p("This is the second modal, stacked on top!"),
      actionButton("open_3", "Open Modal 3")
    ),
    footer = modal_footer(
      actionButton("close_2", "Close", class = "btn-primary")
    )
  ),
  
  shiny_modal(
    id = "modal_3",
    header = modal_header("Modal 3"),
    body = modal_body(p("You can stack many modals!")),
    footer = modal_footer(
      actionButton("close_all", "Close All", class = "btn-danger")
    )
  )
)

server <- function(input, output, session) {
  observeEvent(input$open_1, { show_modal("modal_1") })
  observeEvent(input$open_2, { show_modal("modal_2") })
  observeEvent(input$open_3, { show_modal("modal_3") })
  
  observeEvent(input$close_1, { hide_modal("modal_1") })
  observeEvent(input$close_2, { hide_modal("modal_2") })
  observeEvent(input$close_3, { hide_modal("modal_3") })
  observeEvent(input$close_all, { hide_all_modals() })
}

Confirmation Workflow

ui <- fluidPage(
  use_shiny_modals(),
  
  actionButton("delete_item", "Delete Item", class = "btn-danger"),
  textOutput("status"),
  
  notification_confirm(
    id = "delete_confirm",
    title = "Delete Item?",
    message = "This action cannot be undone. Are you sure?",
    confirm_text = "Yes, Delete",
    cancel_text = "No, Keep It",
    glow = TRUE
  )
)

server <- function(input, output, session) {
  observeEvent(input$delete_item, {
    show_modal("delete_confirm")
  })
  
  observeEvent(input$delete_confirm_confirm, {
    # Perform deletion
    output$status <- renderText("Item deleted successfully!")
    hide_modal("delete_confirm")
  })
  
  observeEvent(input$delete_confirm_cancel, {
    output$status <- renderText("Deletion cancelled")
    hide_modal("delete_confirm")
  })
}

Auto-Dismiss Notification

# Show a notification that closes after 5 seconds
notification_info(
  id = "temp_message",
  title = "Processing...",
  message = "Your request is being processed. This message will close automatically.",
  auto_dismiss = TRUE
)

# In server:
observeEvent(input$start_process, {
  show_modal("temp_message")
  # The modal will automatically close after 5 seconds
})

API Reference

Core Functions

use_shiny_modals()

Initialize modal system (required once per app)

use_shiny_modals()

shiny_modal()

Create a custom modal

shiny_modal(
  id,                          # character, required
  header = NULL,               # modal_header()
  body = NULL,                 # modal_body()
  footer = NULL,               # modal_footer()
  size = "m",                  # "xs", "s", "m", "l", "xl", or custom CSS width
  position = "center",         # "center", "left", "right", "top", "bottom"
  backdrop_effect = "fade",    # "fade", "blur", "none"
  animation = "fade",          # "fade", "scale", "slide"
  overflow = "auto",           # "auto", "scroll", "hidden", "visible"
  draggable = FALSE,           # logical
  close_on_backdrop_click = TRUE,  # logical
  theme = NULL                 # modal_theme() or modal_theme_preset()
)

modal_header()

Create modal header

modal_header(
  title,                       # character, required
  icon = NULL,                 # icon() or NULL
  close_button = TRUE          # logical
)

modal_body()

Create modal body

modal_body(...)                # Any Shiny UI elements

modal_footer()

Create modal footer

modal_footer(...)              # Usually action buttons

show_modal(id)

Display a modal

show_modal("my_modal")

hide_modal(id)

Hide a modal

hide_modal("my_modal")

toggle_modal(id)

Toggle modal visibility

toggle_modal("my_modal")

hide_all_modals()

Hide all open modals

hide_all_modals()

Theme Functions

modal_theme()

Create custom theme

modal_theme(
  header_bg = NULL,
  header_text = NULL,
  body_bg = NULL,
  body_text = NULL,
  border_color = NULL,
  border_radius = NULL,
  shadow = NULL
)

modal_theme_preset(name)

Use preset theme

modal_theme_preset("ocean")    # or any of 12 theme names

Notification Functions

notification_success()

Success notification

notification_success(
  id,
  title,
  message,
  button_text = "OK",
  auto_dismiss = FALSE,
  position = "center",
  glow = FALSE,
  buttons = NULL
)

notification_error()

Error notification

notification_error(
  id,
  title,
  message,
  button_text = "OK",
  auto_dismiss = FALSE,
  position = "center",
  glow = FALSE,
  buttons = NULL
)

notification_warning()

Warning notification

notification_warning(
  id,
  title,
  message,
  button_text = "OK",
  auto_dismiss = FALSE,
  position = "center",
  glow = FALSE,
  buttons = NULL
)

notification_info()

Info notification

notification_info(
  id,
  title,
  message,
  button_text = "OK",
  auto_dismiss = FALSE,
  position = "center",
  glow = FALSE,
  buttons = NULL
)

notification_confirm()

Confirmation notification

notification_confirm(
  id,
  title,
  message,
  confirm_text = "Confirm",
  cancel_text = "Cancel",
  position = "center",
  glow = FALSE,
  buttons = NULL
)

Tips & Best Practices

  1. Always Initialize: Call use_shiny_modals() once in your UI
  2. Unique IDs: Each modal must have a unique id
  3. Button Classes: Use .btn-primary, .btn-secondary, .btn-danger for styling
  4. Auto-dismiss: Use for non-critical information only
  5. Glow Effect: Reserve for important alerts and confirmations
  6. Preset Themes: Start with presets, customize with modal_theme() if needed
  7. Nested Modals: Z-index managed automatically, stack as needed
  8. Custom Buttons: Use for complex workflows with multiple actions
  9. Accessibility: All modals close with ESC key
  10. Responsive: Works on desktop and mobile

Troubleshooting

Modals not showing?

  • Make sure use_shiny_modals() is called in UI
  • Check that modal id matches in show_modal()

Styles not working?

  • Clear browser cache
  • Restart Shiny app
  • Check CSS variable names

Nested modals not stacking?

  • Just call show_modal() for each modal
  • Z-index is handled automatically

Button clicks not working?

  • Check observeEvent() is listening to correct input ID
  • For notifications: {modal_id}_{button_id} format

Examples

Run the demo app to see all features in action:

source(system.file("examples", "demo_app.R", package = "shinyModals"))

Version: 0.4.0
Last Updated: December 10, 2025