Skills shiny-bslib
Build modern Shiny dashboards and applications using bslib (Bootstrap 5). Use when creating new Shiny apps, modernizing legacy apps (fluidPage, fluidRow/column, tabsetPanel, wellPanel, shinythemes), or working with bslib page layouts, grid systems, cards, value boxes, navigation, sidebars, filling layouts, theming, accordions, tooltips, popovers, toasts, or bslib inputs. Assumes familiarity with basic Shiny.
git clone https://github.com/posit-dev/skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/posit-dev/skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/shiny/shiny-bslib" ~/.claude/skills/posit-dev-skills-shiny-bslib && rm -rf "$T"
shiny/shiny-bslib/SKILL.mdModern Shiny Apps with bslib
Build professional Shiny dashboards using bslib's Bootstrap 5 components and layouts. This skill focuses on modern UI/UX patterns that replace legacy Shiny approaches.
Quick Start
Single-page dashboard:
library(shiny) library(bslib) ui <- page_sidebar( title = "My Dashboard", theme = bs_theme(version = 5), # "shiny" preset by default sidebar = sidebar( selectInput("variable", "Variable", choices = names(mtcars)) ), layout_column_wrap( width = 1/3, fill = FALSE, value_box(title = "Users", value = "1,234", theme = "primary"), value_box(title = "Revenue", value = "$56K", theme = "success"), value_box(title = "Growth", value = "+18%", theme = "info") ), card( full_screen = TRUE, card_header("Plot"), plotOutput("plot") ) ) server <- function(input, output, session) { output$plot <- renderPlot({ hist(mtcars[[input$variable]], main = input$variable) }) } shinyApp(ui, server)
Multi-page dashboard:
ui <- page_navbar( title = "Analytics Platform", theme = bs_theme(version = 5), nav_panel("Overview", overview_ui), nav_panel("Analysis", analysis_ui), nav_panel("Reports", reports_ui) )
Core Concepts
Page Layouts
-- Single-page dashboard with sidebar (most common)page_sidebar()
-- Multi-page app with top navigation barpage_navbar()
-- Viewport-filling layout for custom arrangementspage_fillable()
-- Scrolling layout for long-form contentpage_fluid()
See page-layouts.md for detailed guidance.
Grid Systems
-- Uniform grid with auto-wrapping (recommended for most cases)layout_column_wrap()
-- 12-column Bootstrap grid with precise controllayout_columns()
See grid-layouts.md for detailed guidance.
Cards
Primary container for dashboard content. Support headers, footers, multiple body sections, and full-screen expansion.
See cards.md for detailed guidance.
Value Boxes
Display key metrics and KPIs with optional icons, sparklines, and built-in theming.
See value-boxes.md for detailed guidance.
Navigation
- Page-level:
for multi-page appspage_navbar() - Component-level:
,navset_card_underline()
,navset_tab()
for tabbed contentnavset_pill()
See navigation.md for detailed guidance.
Sidebars
- Page-level:
orpage_sidebar()page_navbar(sidebar = ...) - Component-level:
within cardslayout_sidebar() - Supports conditional content, dynamic open/close, accordions
See sidebars.md for detailed guidance.
Filling Layouts
The fill system controls how components resize to fill available space. Key concepts: fillable containers, fill items, fill carriers. Fill activates when containers have defined heights.
See filling.md for detailed guidance.
Theming
with Bootswatch themes for quick stylingbs_theme()- Custom colors:
,bg
,fg
affect hundreds of CSS rulesprimary - Fonts:
for typographyfont_google() - Dynamic theming:
+input_dark_mode()session$setCurrentTheme()
See theming.md for detailed guidance.
UI Components
- Accordions -- Collapsible sections, especially useful in sidebars
- Tooltips -- Hover-triggered help text
- Popovers -- Click-triggered containers for secondary UI/inputs
- Toasts -- Temporary notification messages
See accordions.md, tooltips-popovers.md, and toasts.md.
Icons
Recommended:
package (Bootstrap Icons, designed for bslib):bsicons
bsicons::bs_icon("graph-up") bsicons::bs_icon("people", size = "2em")
Browse icons: https://icons.getbootstrap.com/
Alternative:
package:fontawesome
fontawesome::fa("envelope")
Accessibility for icon-only triggers: When an icon is used as the sole trigger for a tooltip, popover, or similar interactive element (no accompanying text), it must be accessible to screen readers. By default, icon packages mark icons as decorative (
aria-hidden="true"), which hides them from assistive technology.
: Providebsicons::bs_icon()
— this automatically setstitlea11y = "sem"tooltip( bs_icon("info-circle", title = "More information"), "Tooltip content here" )
: Setfontawesome::fa()
and providea11y = "sem"titletooltip( fa("circle-info", a11y = "sem", title = "More information"), "Tooltip content here" )
The
title should describe the purpose of the trigger (e.g., "More information", "Settings"), not the icon itself (e.g., not "info circle icon").
Special Inputs
-- Toggle switch (modern checkbox alternative)input_switch()
-- Dark mode toggleinput_dark_mode()
-- Button for long-running operationsinput_task_button()
-- Code editor with syntax highlightinginput_code_editor()
-- Textarea with explicit submissioninput_submit_textarea()
See inputs.md for detailed guidance.
Common Workflows
Building a Dashboard
- Choose page layout:
(single-page) orpage_sidebar()
(multi-page)page_navbar() - Add theme with
(consider Bootswatch for quick start)bs_theme() - Create sidebar with inputs for filtering/controls
- Add value boxes at top for key metrics (set
on container)fill = FALSE - Arrange cards with
orlayout_column_wrap()layout_columns() - Enable
on all visualization cardsfull_screen = TRUE - Add
for plot themingthematic::thematic_shiny()
Modernizing an Existing App
See migration.md for a complete mapping of legacy patterns to modern equivalents. Key steps:
- Replace
withfluidPage()
orpage_sidebar()page_navbar() - Replace
/fluidRow()
withcolumn()layout_columns() - Wrap outputs in
card(full_screen = TRUE) - Add
theme = bs_theme(version = 5) - Convert key metrics to
componentsvalue_box() - Replace
withtabsetPanel()navset_card_underline()
Guidelines
- Prefer bslib page functions (
,page_sidebar()
,page_navbar()
,page_fillable()
) over legacy equivalents (page_fluid()
,fluidPage()
)navbarPage() - Use
orlayout_column_wrap()
for grid layouts instead oflayout_columns()
/fluidRow()
, which don't support filling layoutscolumn() - Wrap outputs in
when building dashboards -- full-screen expansion is a high-value featurecard(full_screen = TRUE) - Set
onfill = FALSE
containers holding value boxes (they shouldn't stretch to fill height)layout_column_wrap() - Pin Bootstrap version: include
or a preset themetheme = bs_theme(version = 5) - Use
in the server so base R and ggplot2 plots match the app themethematic::thematic_shiny() - Use responsive widths like
inwidth = "250px"
for auto-adjusting columnslayout_column_wrap() - Group sidebar inputs with
when sidebars have many controlsaccordion() - See migration.md for mapping legacy Shiny patterns to modern bslib equivalents
Avoid Common Errors
- Avoid directly nesting
containers.card()
functions are already cards;navset_card_*()
content goes directly inside them without wrapping innav_panel()card() - Only use
andlayout_columns()
for laying out multiple elements. Single children should be passed directly to their container functions.layout_column_wrap() - Never nest
functions. Only use one top-level page function per app.page_*()
Reference Files
- migration.md -- Legacy Shiny to modern bslib migration guide
- page-layouts.md -- Page-level layout functions and patterns
- grid-layouts.md -- Multi-column grid systems
- cards.md -- Card components and features
- value-boxes.md -- Value boxes for metrics and KPIs
- navigation.md -- Navigation containers and patterns
- sidebars.md -- Sidebar layouts and organization
- filling.md -- Fillable containers and fill items
- theming.md -- Basic theming (colors, fonts, Bootswatch). See shiny-bslib-theming skill for advanced theming
- accordions.md -- Collapsible sections and sidebar organization
- tooltips-popovers.md -- Hover tooltips and click-triggered popovers
- toasts.md -- Temporary notification messages
- inputs.md -- Special bslib input widgets
- best-practices.md -- bslib-specific patterns and common gotchas