A comprehensive guide to using the shinyModals R package for building modern, interactive modal dialogs in Shiny applications.
- Getting Started
- Basic Usage
- Modal Components
- Modal Features
- Themes
- Notifications
- Advanced Examples
- API Reference
# Install from local source
devtools::install_local("path/to/shinyModals")
# Or from GitHub (if published)
# devtools::install_github("username/shinyModals")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)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")
})
}# 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()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 texticon(shiny.tag, optional): An icon from Font Awesome usingicon()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)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
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
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)
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
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
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
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
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
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
)The ESC key always closes modals (built-in).
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:
- default - Clean, minimal design
- dark - Dark background with light text
- ocean - Blue gradient, calm feel
- sunset - Orange/red gradient, warm
- forest - Green tones, natural look
- minimal - Ultra-clean, white on white
- neon - Bright colors, modern
- corporate - Professional blue, business
- warm - Amber/orange tones, inviting
- cool - Cyan/blue tones, fresh
- rose - Pink/rose tones, elegant
- glass - Glassmorphism effect, transparent
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 are pre-styled modals for common user messages.
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
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
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
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
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}_confirmand{id}_cancel
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
})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) |
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")
})
}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() })
}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")
})
}# 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
})Initialize modal system (required once per app)
use_shiny_modals()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()
)Create modal header
modal_header(
title, # character, required
icon = NULL, # icon() or NULL
close_button = TRUE # logical
)Create modal body
modal_body(...) # Any Shiny UI elementsCreate modal footer
modal_footer(...) # Usually action buttonsDisplay a modal
show_modal("my_modal")Hide a modal
hide_modal("my_modal")Toggle modal visibility
toggle_modal("my_modal")Hide all open modals
hide_all_modals()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
)Use preset theme
modal_theme_preset("ocean") # or any of 12 theme namesSuccess notification
notification_success(
id,
title,
message,
button_text = "OK",
auto_dismiss = FALSE,
position = "center",
glow = FALSE,
buttons = NULL
)Error notification
notification_error(
id,
title,
message,
button_text = "OK",
auto_dismiss = FALSE,
position = "center",
glow = FALSE,
buttons = NULL
)Warning notification
notification_warning(
id,
title,
message,
button_text = "OK",
auto_dismiss = FALSE,
position = "center",
glow = FALSE,
buttons = NULL
)Info notification
notification_info(
id,
title,
message,
button_text = "OK",
auto_dismiss = FALSE,
position = "center",
glow = FALSE,
buttons = NULL
)Confirmation notification
notification_confirm(
id,
title,
message,
confirm_text = "Confirm",
cancel_text = "Cancel",
position = "center",
glow = FALSE,
buttons = NULL
)- Always Initialize: Call
use_shiny_modals()once in your UI - Unique IDs: Each modal must have a unique
id - Button Classes: Use
.btn-primary,.btn-secondary,.btn-dangerfor styling - Auto-dismiss: Use for non-critical information only
- Glow Effect: Reserve for important alerts and confirmations
- Preset Themes: Start with presets, customize with
modal_theme()if needed - Nested Modals: Z-index managed automatically, stack as needed
- Custom Buttons: Use for complex workflows with multiple actions
- Accessibility: All modals close with ESC key
- Responsive: Works on desktop and mobile
Modals not showing?
- Make sure
use_shiny_modals()is called in UI - Check that modal
idmatches inshow_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
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