MCP HubMCP Hub
스킬 목록으로 돌아가기

design-shiny-ui

pjt222
업데이트됨 Yesterday
1 조회
17
2
17
GitHub에서 보기
디자인design

정보

이 스킬은 개발자가 bslib를 사용한 테마 지정, 반응형 그리드를 위한 layout_columns, 그리고 커스텀 CSS/SCSS를 활용하여 현대적인 Shiny UI 인터페이스를 설계하도록 돕습니다. 새로운 앱을 처음부터 구축하거나, 기존의 유동적 페이지 앱을 현대화하거나, 접근성과 반응형 디자인을 보장하면서 브랜드 테마를 적용하는 데 유용합니다. 이 스킬은 페이지 레이아웃, 접근성 개선, 다양한 화면 크기에서의 브랜드 일관성을 처리합니다.

빠른 설치

Claude Code

추천
기본
npx skills add pjt222/agent-almanac -a claude-code
플러그인 명령대체
/plugin add https://github.com/pjt222/agent-almanac
Git 클론대체
git 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 저장소

pjt222/agent-almanac
경로: i18n/ja/skills/design-shiny-ui
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

연관 스킬

executing-plans

디자인

executing-plans 스킬은 검토 체크포인트가 포함된 통제된 배치로 실행할 완전한 구현 계획이 있을 때 사용합니다. 이 스킬은 계획을 불러와 비판적으로 검토한 후, 소규모 배치(기본값 3개 작업)로 작업을 실행하면서 각 배치 사이에 진행 상황을 아키텍트 검토를 위해 보고합니다. 이를 통해 내재된 품질 관리 체크포인트를 갖춘 체계적인 구현이 보장됩니다.

스킬 보기

requesting-code-review

디자인

이 스킬은 코드 변경 사항을 요구 사항에 따라 분석하기 위해 코드 리뷰어 하위 에이전트를 호출합니다. 작업 완료 후, 주요 기능 구현 후, 또는 메인 브랜치에 병합하기 전에 사용해야 합니다. 이 리뷰는 현재 구현체와 원래 계획을 비교하여 문제를 조기에 발견하는 데 도움이 됩니다.

스킬 보기

connect-mcp-server

디자인

이 스킬은 개발자들이 HTTP, stdio 또는 SSE 전송 방식을 통해 MCP 서버를 Claude Code에 연결하는 포괄적인 가이드를 제공합니다. GitHub, Notion 및 사용자 정의 API와 같은 외부 서비스를 통합하기 위한 설치, 구성, 인증 및 보안을 다룹니다. MCP 통합 설정, 외부 도구 구성 또는 Claude의 모델 컨텍스트 프로토콜 작업 시 활용하세요.

스킬 보기

web-cli-teleport

디자인

이 스킬은 작업 분석을 기반으로 개발자가 Claude Code 웹 인터페이스와 CLI 인터페이스 중 선택할 수 있도록 돕고, 두 환경 간 원활한 세션 텔레포트를 가능하게 합니다. 웹, CLI 또는 모바일 환경 전환 시 세션 상태와 컨텍스트를 관리하여 워크플로를 최적화합니다. 다양한 단계에서 서로 다른 도구가 필요한 복잡한 프로젝트에 사용하세요.

스킬 보기