From shiny
Builds modern Shiny dashboards using bslib (Bootstrap 5) with page layouts, cards, value boxes, navigation, sidebars, and theming. Replaces legacy Shiny UI patterns.
How this skill is triggered — by the user, by Claude, or both
Slash command
/shiny:shiny-bslibThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
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.
references/accordions.mdreferences/best-practices.mdreferences/cards.mdreferences/filling.mdreferences/grid-layouts.mdreferences/inputs.mdreferences/migration.mdreferences/navigation.mdreferences/page-layouts.mdreferences/sidebars.mdreferences/theming.mdreferences/toasts.mdreferences/toolbars.mdreferences/tooltips-popovers.mdreferences/value-boxes.mdBuild professional Shiny dashboards using bslib's Bootstrap 5 components and layouts. This skill focuses on modern UI/UX patterns that replace legacy Shiny approaches.
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)
)
page_sidebar() -- Single-page dashboard with sidebar (most common)page_navbar() -- Multi-page app with top navigation barpage_fillable() -- Viewport-filling layout for custom arrangementspage_fluid() -- Scrolling layout for long-form contentSee page-layouts.md for detailed guidance.
layout_column_wrap() -- Uniform grid with auto-wrapping (recommended for most cases)layout_columns() -- 12-column Bootstrap grid with precise controlSee grid-layouts.md for detailed guidance.
Primary container for dashboard content. Support headers, footers, multiple body sections, and full-screen expansion.
See cards.md for detailed guidance.
Display key metrics and KPIs with optional icons, sparklines, and built-in theming.
See value-boxes.md for detailed guidance.
page_navbar() for multi-page appsnavset_card_underline(), navset_tab(), navset_pill() for tabbed contentSee navigation.md for detailed guidance.
page_sidebar() or page_navbar(sidebar = ...)layout_sidebar() within cardsresizable = TRUE by default — users can drag the edge to resize on desktopSee sidebars.md for detailed guidance.
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.
bs_theme() with Bootswatch themes for quick stylingbg, fg, primary affect hundreds of CSS rulesfont_google() for typographyinput_dark_mode() + session$setCurrentTheme()See theming.md for detailed guidance.
See accordions.md, tooltips-popovers.md, toasts.md, and toolbars.md.
Recommended: bsicons package (Bootstrap Icons, designed for bslib):
bsicons::bs_icon("graph-up")
bsicons::bs_icon("people", size = "2em")
Browse icons: https://icons.getbootstrap.com/
Alternative: fontawesome package:
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.
bsicons::bs_icon(): Provide title — this automatically sets a11y = "sem"
tooltip(
bs_icon("info-circle", title = "More information"),
"Tooltip content here"
)
fontawesome::fa(): Set a11y = "sem" and provide title
tooltip(
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").
input_switch() -- Toggle switch (modern checkbox alternative)input_dark_mode() -- Dark mode toggleinput_task_button() -- Button for long-running operationsinput_code_editor() -- Code editor with syntax highlightinginput_submit_textarea() -- Textarea with explicit submissionSee inputs.md for detailed guidance.
page_sidebar() (single-page) or page_navbar() (multi-page)bs_theme() (consider Bootswatch for quick start)fill = FALSE on container)layout_column_wrap() or layout_columns()full_screen = TRUE on all visualization cardsthematic::thematic_shiny() for plot themingSee migration.md for a complete mapping of legacy patterns to modern equivalents. Key steps:
fluidPage() with page_sidebar() or page_navbar()fluidRow()/column() with layout_columns()card(full_screen = TRUE)theme = bs_theme(version = 5)value_box() componentstabsetPanel() with navset_card_underline()page_sidebar(), page_navbar(), page_fillable(), page_fluid()) over legacy equivalents (fluidPage(), navbarPage())layout_column_wrap() or layout_columns() for grid layouts instead of fluidRow()/column(), which don't support filling layoutscard(full_screen = TRUE) when building dashboards -- full-screen expansion is a high-value featurefill = FALSE on layout_column_wrap() containers holding value boxes (they shouldn't stretch to fill height)theme = bs_theme(version = 5) or a preset themethematic::thematic_shiny() in the server so base R and ggplot2 plots match the app themewidth = "250px" in layout_column_wrap() for auto-adjusting columnsaccordion() when sidebars have many controlscard() containers. navset_card_*() functions are already cards; nav_panel() content goes directly inside them without wrapping in card()layout_columns() and layout_column_wrap() for laying out multiple elements. Single children should be passed directly to their container functions.page_*() functions. Only use one top-level page function per app.npx claudepluginhub posit-dev/skills --plugin quartoDesigns Shiny app UIs with bslib theming, responsive grids, value boxes, cards, and custom CSS/SCSS. Covers page layouts, accessibility, and brand consistency.
Customizes Shiny app appearance using bslib's Bootstrap 5 theming system: Bootswatch themes, custom colors/fonts, Sass variables, brand.yml integration, dark mode, dynamic theme switching, and plot theming with thematic.
Guides building SaaS dashboards, settings pages, data tables, and layouts with shadcn/ui + Tailwind. Covers component library selection, page composition, responsive design, dark mode, and UI states (loading, empty, error).