MCP HubMCP Hub
Retour aux compétences

design-shiny-ui

pjt222
Mis à jour 2 days ago
8 vues
17
2
17
Voir sur GitHub
Métadesign

À propos

Cette compétence aide les développeurs à construire et moderniser les interfaces utilisateur d'applications Shiny en utilisant bslib pour le thème, les mises en page responsives avec `layout_columns`, et des composants comme les value boxes et les cartes. Elle couvre l'application de CSS/SCSS personnalisé, la garantie de l'accessibilité, et le maintien de la cohérence de la marque sur toutes les tailles d'écran. Utilisez-la lors de la création d'une nouvelle application à partir de zéro ou lors de la mise à niveau d'une application existante avec `fluidPage` vers un design moderne et responsive.

Installation rapide

Claude Code

Recommandé
Principal
npx skills add pjt222/agent-almanac -a claude-code
Commande PluginAlternatif
/plugin add https://github.com/pjt222/agent-almanac
Git CloneAlternatif
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/design-shiny-ui

Copiez et collez cette commande dans Claude Code pour installer cette compétence

Documentation

Design Shiny UI

Design responsive, accessible Shiny application interfaces using bslib theming, modern layout primitives, and custom CSS.

When to Use

  • Building a new Shiny app UI from scratch
  • Modernizing an existing Shiny app from fluidPage to bslib
  • Applying brand theming (colors, fonts) to a Shiny app
  • Making a Shiny app responsive across screen sizes
  • Improving accessibility of a Shiny application

Inputs

  • Required: Application purpose and target audience
  • Required: Layout type (sidebar, navbar, fillable, dashboard)
  • Optional: Brand colors and fonts
  • Optional: Whether to use custom CSS/SCSS (default: bslib only)
  • Optional: Accessibility requirements (WCAG level)

Procedure

Step 1: Choose the Page Layout

bslib provides several page constructors:

# Sidebar layout — most common for data apps
ui <- page_sidebar(
  title = "My App",
  sidebar = sidebar("Controls here"),
  "Main content here"
)

# Navbar layout — for multi-page apps
ui <- page_navbar(
  title = "My App",
  nav_panel("Tab 1", "Content 1"),
  nav_panel("Tab 2", "Content 2"),
  nav_spacer(),
  nav_item(actionButton("help", "Help"))
)

# Fillable layout — content fills available space
ui <- page_fillable(
  card(
    full_screen = TRUE,
    plotOutput("plot")
  )
)

# Dashboard layout — grid of value boxes and cards
ui <- page_sidebar(
  title = "Dashboard",
  sidebar = sidebar(open = "closed", "Filters"),
  layout_columns(
    fill = FALSE,
    value_box("Revenue", "$1.2M", theme = "primary"),
    value_box("Users", "4,521", theme = "success"),
    value_box("Uptime", "99.9%", theme = "info")
  ),
  layout_columns(
    card(plotOutput("chart1")),
    card(plotOutput("chart2"))
  )
)

Got: Page layout matches the application's navigation and content needs.

If fail: If the layout doesn't look right, check that you're using page_sidebar() / page_navbar() (bslib) not fluidPage() / navbarPage() (base shiny). The bslib versions have better defaults and theming support.

Step 2: Configure the bslib Theme

my_theme <- bslib::bs_theme(
  version = 5,                      # Bootstrap 5
  bootswatch = "flatly",            # Optional preset theme
  bg = "#ffffff",                   # Background color
  fg = "#2c3e50",                   # Foreground (text) color
  primary = "#2c3e50",              # Primary brand color
  secondary = "#95a5a6",            # Secondary color
  success = "#18bc9c",
  info = "#3498db",
  warning = "#f39c12",
  danger = "#e74c3c",
  base_font = bslib::font_google("Source Sans Pro"),
  heading_font = bslib::font_google("Source Sans Pro", wght = 600),
  code_font = bslib::font_google("Fira Code"),
  "navbar-bg" = "#2c3e50"
)

ui <- page_sidebar(
  theme = my_theme,
  title = "Themed App",
  # ...
)

Use the interactive theme editor during development:

bslib::bs_theme_preview(my_theme)

Got: App renders with consistent brand colors, fonts, and Bootstrap 5 components.

If fail: If fonts don't load, check internet access (Google Fonts requires it) or switch to system fonts: font_collection("system-ui", "-apple-system", "Segoe UI"). If theme variables don't apply, check that you're passing theme to the page function.

Step 3: Build the Layout with Cards and Columns

ui <- page_sidebar(
  theme = my_theme,
  title = "Analysis Dashboard",
  sidebar = sidebar(
    width = 300,
    title = "Filters",
    selectInput("dataset", "Dataset", choices = c("iris", "mtcars")),
    sliderInput("sample", "Sample %", 10, 100, 100, step = 10),
    hr(),
    actionButton("refresh", "Refresh", class = "btn-primary w-100")
  ),

  # KPI row — non-filling
  layout_columns(
    fill = FALSE,
    col_widths = c(4, 4, 4),
    value_box(
      title = "Observations",
      value = textOutput("n_obs"),
      showcase = bsicons::bs_icon("table"),
      theme = "primary"
    ),
    value_box(
      title = "Variables",
      value = textOutput("n_vars"),
      showcase = bsicons::bs_icon("columns-gap"),
      theme = "info"
    ),
    value_box(
      title = "Missing",
      value = textOutput("n_missing"),
      showcase = bsicons::bs_icon("exclamation-triangle"),
      theme = "warning"
    )
  ),

  # Main content row
  layout_columns(
    col_widths = c(8, 4),
    card(
      card_header("Distribution"),
      full_screen = TRUE,
      plotOutput("main_plot")
    ),
    card(
      card_header("Summary"),
      tableOutput("summary_table")
    )
  )
)

Key layout primitives:

  • layout_columns() — responsive grid with col_widths
  • card() — content container with optional header/footer
  • value_box() — KPI display with icon and theme
  • layout_sidebar() — nested sidebar within cards
  • navset_card_tab() — tabbed cards

Got: Responsive grid layout that adapts to screen size.

If fail: If columns stack unexpectedly on wide screens, check col_widths sum equals 12 (Bootstrap grid). If cards overlap, ensure fill = FALSE on non-filling rows.

Step 4: Add Dynamic UI Elements

server <- function(input, output, session) {
  output$dynamic_filters <- renderUI({
    data <- current_data()
    tagList(
      selectInput("col", "Column", choices = names(data)),
      if (is.numeric(data[[input$col]])) {
        sliderInput("range", "Range",
          min = min(data[[input$col]], na.rm = TRUE),
          max = max(data[[input$col]], na.rm = TRUE),
          value = range(data[[input$col]], na.rm = TRUE)
        )
      } else {
        selectInput("values", "Values",
          choices = unique(data[[input$col]]),
          multiple = TRUE
        )
      }
    )
  })

  # Conditional panels (no server round-trip)
  # In UI:
  # conditionalPanel(
  #   condition = "input.show_advanced == true",
  #   numericInput("alpha", "Alpha", 0.05)
  # )
}

Got: UI elements update dynamically based on user selections and data.

If fail: If dynamic UI flickers, use conditionalPanel() (CSS-based) instead of renderUI() where possible. If dynamic inputs lose their values on re-render, add session$sendInputMessage() to restore state.

Step 5: Add Custom CSS/SCSS (Optional)

For styles beyond bslib theme variables:

# Inline CSS
ui <- page_sidebar(
  theme = my_theme,
  tags$head(tags$style(HTML("
    .sidebar { border-right: 2px solid var(--bs-primary); }
    .card-header { font-weight: 600; }
    .value-box .value { font-size: 2.5rem; }
  "))),
  # ...
)

# External CSS file (place in www/ directory)
ui <- page_sidebar(
  theme = my_theme,
  tags$head(tags$link(rel = "stylesheet", href = "custom.css")),
  # ...
)

For SCSS integration with bslib:

my_theme <- bslib::bs_theme(version = 5) |>
  bslib::bs_add_rules(sass::sass_file("www/custom.scss"))

Got: Custom styles applied without breaking bslib theming.

If fail: If custom CSS conflicts with bslib, use Bootstrap CSS variables (var(--bs-primary)) instead of hardcoded colors. This ensures theme changes propagate to custom styles.

Step 6: Ensure Accessibility

# Add ARIA labels to inputs
selectInput("category", "Category",
  choices = c("A", "B", "C")
) |> tagAppendAttributes(`aria-describedby` = "category-help")

# Add alt text to plots
output$plot <- renderPlot({
  plot(data(), main = "Distribution of Values")
}, alt = "Histogram showing the distribution of selected values")

# Ensure sufficient color contrast in theme
my_theme <- bslib::bs_theme(
  version = 5,
  bg = "#ffffff",      # White background
  fg = "#212529"       # Dark text — 15.4:1 contrast ratio
)

# Use semantic HTML
tags$main(
  role = "main",
  tags$h1("Dashboard"),
  tags$section(
    `aria-label` = "Key Performance Indicators",
    layout_columns(
      # value boxes...
    )
  )
)

Got: App meets WCAG 2.1 AA standards for color contrast, keyboard navigation, and screen reader compatibility.

If fail: Test with browser dev tools accessibility audit (Lighthouse). Check color contrast ratios with WebAIM's contrast checker. Ensure all interactive elements are keyboard-focusable.

Validation

  • Page layout renders correctly on desktop and mobile widths
  • bslib theme applies consistently to all components
  • Value boxes display with correct themes and icons
  • Cards resize properly in the responsive grid
  • Custom CSS uses Bootstrap variables, not hardcoded values
  • All plots have alt text for screen readers
  • Color contrast meets WCAG AA (4.5:1 for text)
  • Interactive elements are keyboard accessible

Pitfalls

  • Mixing old and new Shiny UI: Don't mix fluidPage() with bslib components. Use page_sidebar(), page_navbar(), or page_fillable() exclusively.
  • Hardcoded colors in CSS: Use var(--bs-primary) instead of #2c3e50. Hardcoded colors break when the theme changes.
  • Missing fill = FALSE on non-filling rows: Value box rows and summary rows usually shouldn't stretch to fill available space. Set fill = FALSE.
  • Google Fonts in offline environments: If the app deploys to an air-gapped network, use system fonts or self-hosted font files instead of font_google().
  • Ignoring mobile: Test with the browser responsive mode. layout_columns automatically stacks on narrow screens, but custom CSS may not.

Related Skills

  • scaffold-shiny-app — initial app setup including theme configuration
  • build-shiny-module — create modular UI components
  • optimize-shiny-performance — performance-conscious rendering
  • review-web-design — visual design review for layout, typography, and colour
  • review-ux-ui — usability and accessibility review

Dépôt GitHub

pjt222/agent-almanac
Chemin: i18n/caveman-lite/skills/design-shiny-ui
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

Compétences associées

content-collections

Méta

Cette compétence propose une configuration éprouvée en production pour Content Collections, un outil axé sur TypeScript qui transforme des fichiers Markdown/MDX en collections de données typées de manière sûre avec une validation Zod. Utilisez-la lors de la création de blogs, de sites de documentation ou d'applications Vite + React riches en contenu pour garantir la sécurité de typage et la validation automatique du contenu. Elle couvre tout, de la configuration du plugin Vite et de la compilation MDX à l'optimisation des déploiements et la validation des schémas.

Voir la compétence

polymarket

Méta

Cette compétence permet aux développeurs de créer des applications avec la plateforme de marchés prédictifs Polymarket, incluant l'intégration d'API pour le trading et les données de marché. Elle fournit également une diffusion de données en temps réel via WebSocket pour surveiller les transactions en direct et l'activité du marché. Utilisez-la pour mettre en œuvre des stratégies de trading ou pour créer des outils traitant les mises à jour de marché en direct.

Voir la compétence

creating-opencode-plugins

Méta

Cette compétence aide les développeurs à créer des plugins OpenCode qui s'interconnectent avec plus de 25 types d'événements tels que les commandes, les fichiers et les opérations LSP. Elle fournit la structure du plugin, les spécifications de l'API événementielle et les modèles d'implémentation pour les modules JavaScript/TypeScript. Utilisez-la lorsque vous avez besoin d'intercepter, de surveiller ou d'étendre le cycle de vie de l'assistant IA OpenCode avec une logique personnalisée pilotée par les événements.

Voir la compétence

sglang

Méta

SGLang est un framework de service LLM haute performance spécialisé dans la génération rapide et structurée pour les workflows JSON, regex et agentiques grâce à son cache de préfixe RadixAttention. Il offre une inférence nettement plus rapide, particulièrement pour les tâches avec des préfixes répétés, ce qui le rend idéal pour les sorties complexes et structurées ainsi que les conversations multi-tours. Choisissez SGLang plutôt que des alternatives comme vLLM lorsque vous avez besoin d'un décodage contraint ou que vous construisez des applications avec un partage étendu de préfixes.

Voir la compétence