design-shiny-ui
关于
This skill helps developers design modern Shiny UI interfaces using bslib for theming, layout_columns for responsive grids, and custom CSS/SCSS. It's useful for building new apps from scratch, modernizing legacy fluidPage apps, or applying brand themes while ensuring accessibility and responsive design. The skill handles page layout, accessibility improvements, and brand consistency across different screen sizes.
快速安装
Claude Code
推荐npx skills add pjt222/agent-almanac -a claude-code/plugin add https://github.com/pjt222/agent-almanacgit clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/design-shiny-ui在 Claude Code 中复制并粘贴此命令以安装该技能
技能文档
name: design-shiny-ui description: > テーマ設定にbslib、レスポンシブグリッドにlayout_columns、バリューボックス、 カード、カスタムCSS/SCSSを使ってShinyアプリケーションUIを設計します。 ページレイアウト、アクセシビリティ、ブランドの一貫性を扱います。新しいShinyアプリ UIをゼロから構築するとき、既存のアプリをfluidPageからbslibにモダナイズするとき、 ブランドのテーマを適用するとき、Shinyアプリを様々な画面サイズでレスポンシブにするとき、 またはShinyアプリのアクセシビリティを改善するときに使用します。 locale: ja source_locale: en source_commit: 6f65f316 translator: claude-opus-4-6 translation_date: 2026-03-16 license: MIT allowed-tools: Read Write Edit Bash Grep Glob metadata: author: Philipp Thoss version: "1.0" domain: shiny complexity: intermediate language: R tags: shiny, bslib, ui, theming, layout, css, accessibility, responsive
Shiny UIの設計
bslibのテーマ設定、モダンなレイアウトプリミティブ、カスタムCSSを使ってレスポンシブでアクセシブルなShinyアプリケーションインターフェースを設計します。
使用タイミング
- 新しいShinyアプリUIをゼロから構築するとき
- 既存のShinyアプリをfluidPageからbslibにモダナイズするとき
- Shinyアプリにブランドのテーマ(色、フォント)を適用するとき
- Shinyアプリを様々な画面サイズでレスポンシブにするとき
- Shinyアプリケーションのアクセシビリティを改善するとき
入力
- 必須: アプリケーションの目的とターゲットオーディエンス
- 必須: レイアウトタイプ(sidebar、navbar、fillable、dashboard)
- オプション: ブランドの色とフォント
- オプション: カスタムCSS/SCSSを使用するか(デフォルト:bslibのみ)
- オプション: アクセシビリティ要件(WCAGレベル)
手順
ステップ1: ページレイアウトの選択
bslibはいくつかのページコンストラクターを提供します:
# サイドバーレイアウト — データアプリに最も一般的
ui <- page_sidebar(
title = "My App",
sidebar = sidebar("Controls here"),
"Main content here"
)
# Navbarレイアウト — 複数ページアプリに
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レイアウト — コンテンツが利用可能なスペースを埋める
ui <- page_fillable(
card(
full_screen = TRUE,
plotOutput("plot")
)
)
# ダッシュボードレイアウト — バリューボックスとカードのグリッド
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"))
)
)
期待結果: ページレイアウトがアプリケーションのナビゲーションとコンテンツのニーズと一致します。
失敗時: レイアウトが正しく見えない場合は、fluidPage()/navbarPage()(ベースshiny)ではなくpage_sidebar()/page_navbar()(bslib)を使用しているか確認してください。bslibバージョンはデフォルトとテーマサポートが優れています。
ステップ2: bslibテーマの設定
my_theme <- bslib::bs_theme(
version = 5, # Bootstrap 5
bootswatch = "flatly", # オプションのプリセットテーマ
bg = "#ffffff", # 背景色
fg = "#2c3e50", # 前景(テキスト)色
primary = "#2c3e50", # プライマリブランドカラー
secondary = "#95a5a6", # セカンダリカラー
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",
# ...
)
開発中はインタラクティブなテーマエディタを使用します:
bslib::bs_theme_preview(my_theme)
期待結果: アプリが一貫したブランドの色、フォント、Bootstrap 5コンポーネントでレンダリングされます。
失敗時: フォントが読み込まれない場合は、インターネットアクセスを確認してください(Google Fontsには必要)またはシステムフォントに切り替えてください:font_collection("system-ui", "-apple-system", "Segoe UI")。テーマ変数が適用されない場合は、themeをページ関数に渡しているか確認してください。
ステップ3: カードとカラムを使ったレイアウトの構築
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行 — 非フィリング
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"
)
),
# メインコンテンツ行
layout_columns(
col_widths = c(8, 4),
card(
card_header("Distribution"),
full_screen = TRUE,
plotOutput("main_plot")
),
card(
card_header("Summary"),
tableOutput("summary_table")
)
)
)
主要なレイアウトプリミティブ:
layout_columns()—col_widthsを持つレスポンシブグリッドcard()— オプションのヘッダー/フッターを持つコンテンツコンテナvalue_box()— アイコンとテーマを持つKPI表示layout_sidebar()— カード内のネストしたサイドバーnavset_card_tab()— タブ付きカード
期待結果: 画面サイズに適応するレスポンシブグリッドレイアウト。
失敗時: 広い画面で列が予期せずスタックする場合は、col_widthsの合計が12(Bootstrapグリッド)になるか確認してください。カードが重なる場合は、非フィリング行にfill = FALSEを設定してください。
ステップ4: ダイナミックUI要素の追加
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
)
}
)
})
# 条件付きパネル(サーバーラウンドトリップなし)
# UI内:
# conditionalPanel(
# condition = "input.show_advanced == true",
# numericInput("alpha", "Alpha", 0.05)
# )
}
期待結果: UI要素がユーザーの選択とデータに基づいてダイナミックに更新されます。
失敗時: ダイナミックUIがちらつく場合は、可能であればrenderUI()の代わりにconditionalPanel()(CSSベース)を使用してください。再レンダリング時にダイナミックな入力が値を失う場合は、状態を復元するためにsession$sendInputMessage()を追加してください。
ステップ5: カスタムCSS/SCSSの追加(オプション)
bslibのテーマ変数を超えたスタイルのために:
# インライン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; }
"))),
# ...
)
# 外部CSSファイル(www/ディレクトリに配置)
ui <- page_sidebar(
theme = my_theme,
tags$head(tags$link(rel = "stylesheet", href = "custom.css")),
# ...
)
bslibとのSCSS統合:
my_theme <- bslib::bs_theme(version = 5) |>
bslib::bs_add_rules(sass::sass_file("www/custom.scss"))
期待結果: bslibのテーマを壊さずにカスタムスタイルが適用されます。
失敗時: カスタムCSSがbslibと競合する場合は、ハードコードされた色の代わりにBootstrap CSS変数(var(--bs-primary))を使用してください。これにより、テーマ変更がカスタムスタイルに伝播します。
ステップ6: アクセシビリティの確保
# 入力にARIAラベルを追加
selectInput("category", "Category",
choices = c("A", "B", "C")
) |> tagAppendAttributes(`aria-describedby` = "category-help")
# プロットにaltテキストを追加
output$plot <- renderPlot({
plot(data(), main = "Distribution of Values")
}, alt = "Histogram showing the distribution of selected values")
# テーマで十分な色のコントラストを確保
my_theme <- bslib::bs_theme(
version = 5,
bg = "#ffffff", # 白い背景
fg = "#212529" # 暗いテキスト — 15.4:1のコントラスト比
)
# セマンティックHTMLを使用
tags$main(
role = "main",
tags$h1("Dashboard"),
tags$section(
`aria-label` = "Key Performance Indicators",
layout_columns(
# バリューボックス...
)
)
)
期待結果: アプリが色のコントラスト、キーボードナビゲーション、スクリーンリーダーの互換性についてWCAG 2.1 AA基準を満たします。
失敗時: ブラウザのデベロッパーツールのアクセシビリティ監査(Lighthouse)でテストしてください。WebAIMのコントラストチェッカーで色のコントラスト比を確認してください。すべてのインタラクティブ要素がキーボードでフォーカスできることを確認してください。
バリデーション
- ページレイアウトがデスクトップとモバイルの幅で正しくレンダリングされる
- bslibのテーマがすべてのコンポーネントに一貫して適用される
- バリューボックスが正しいテーマとアイコンで表示される
- カードがレスポンシブグリッドで適切にリサイズされる
- カスタムCSSがハードコードされた値ではなくBootstrap変数を使用する
- すべてのプロットがスクリーンリーダー用のaltテキストを持つ
- 色のコントラストがWCAG AA(テキストに対して4.5:1)を満たす
- インタラクティブ要素がキーボードでアクセス可能
よくある落とし穴
- 古いShiny UIと新しいShiny UIの混在:
fluidPage()とbslibコンポーネントを混在させないでください。page_sidebar()、page_navbar()、またはpage_fillable()だけを使用してください。 - CSSでのハードコードされた色:
#2c3e50の代わりにvar(--bs-primary)を使用してください。テーマが変更されるとハードコードされた色は壊れます。 - 非フィリング行に
fill = FALSEがない: バリューボックス行とサマリー行は通常、利用可能なスペースを埋めるべきではありません。fill = FALSEを設定してください。 - オフライン環境でのGoogle Fonts: アプリがエアギャップネットワークにデプロイされる場合は、
font_google()の代わりにシステムフォントまたはセルフホストのフォントファイルを使用してください。 - モバイルの無視: ブラウザのレスポンシブモードでテストしてください。
layout_columnsは狭い画面で自動的にスタックしますが、カスタムCSSはそうでない場合があります。
関連スキル
scaffold-shiny-app— テーマ設定を含む初期アプリセットアップbuild-shiny-module— モジュラーUIコンポーネントの作成optimize-shiny-performance— パフォーマンスを意識したレンダリングreview-web-design— レイアウト、タイポグラフィ、色のビジュアルデザインレビューreview-ux-ui— ユーザビリティとアクセシビリティのレビュー
GitHub 仓库
相关推荐技能
executing-plans
设计该Skill用于当开发者提供完整实施计划时,以受控批次方式执行代码实现。它会先审阅计划并提出疑问,然后分批次执行任务(默认每批3个任务),并在批次间暂停等待审查。关键特性包括分批次执行、内置检查点和架构师审查机制,确保复杂系统实现的可控性。
requesting-code-review
设计该Skill可在完成任务、实现主要功能或合并代码前自动调度代码审查子代理,确保实现符合需求和计划。它支持通过指定git SHA范围进行精准的代码变更审查,帮助开发者在关键节点及时发现潜在问题。核心原则是"早审查、勤审查",适用于开发流程的各个关键阶段。
connect-mcp-server
设计这个Skill指导开发者如何将MCP服务器连接到Claude Code,支持HTTP、stdio和SSE三种传输协议。它涵盖了从安装配置到认证安全的完整流程,适用于集成GitHub、Notion、数据库等外部服务。当开发者需要添加集成、配置外部工具或提及MCP相关功能时,这个Skill能提供实用的操作指南。
web-cli-teleport
设计该Skill帮助开发者根据任务特性选择Claude Code的Web或CLI界面,并指导如何在两种环境间无缝迁移会话。它能分析任务复杂度、迭代需求等要素,推荐最优工作界面和工作流。关键特性包括会话状态管理、环境切换指导和上下文优化建议。
