rshinyshinydashboardbs4dash

Layout of sidebar tabs and skin for bs4dash/shinydashboard


I am working on the UI of a Shiny app ... and it looks super ugly. I am running into three problems:

  1. I am trying to use skin = 'light' in certain parts to experiment with the colours (starting off with the sidebar!). When I use this, it doesn't work. Instead, the word 'light' is printed in the sidebar.
  2. The full header title is "Performance Indicators" - there isn't enough space to show the title. Adding width = '450px' into the header = dashboardHeader() function results in a Error in FUN(X[[i]], ...) : Expected an object with class 'shiny.tag'. error.
  3. Why are the tabItems set out side by side? I would like to have them aligned vertically.

enter image description here

How do I solve these three issues?

The code for the app is below:

library(shiny)
library(bs4Dash)
library(shinyWidgets)
library(plotly)
library(DT)




shinyApp(
  ui = dashboardPage(
    header = dashboardHeader(
      title = "Performance Indicators"
    ),
    
    sidebar = dashboardSidebar(
      
      skin = 'light',
      
      sidebarMenu(
        bs4SidebarMenuItem(tabName = "subtab1",
                           text = "Page 1"
                           # ,icon = shiny::icon("chart-bar")
        ),
        bs4SidebarMenuItem(tabName = "subtab2",
                           text = "Page 2"
                           # ,icon = shiny::icon("chart-bar")
        ),
        bs4SidebarMenuItem(tabName = "subtab3",
                           text = "Page 3"
                           # ,icon = shiny::icon("chart-bar")
        )
      )
    ),
    body = dashboardBody(
      tabItems(
        tabItem(tabName = "subtab1",
                fluidRow(
                  column(2,
                         box(
                           title = strong("Settings"),
                           solidHeader = TRUE,
                           width = 12,
                           dateRangeInput('dateRange',
                                          label = 'For the time period:',
                                          #DEFAULT
                                          start = Sys.Date()-365, end = Sys.Date()-1),
                           
                           radioButtons("time_breakdown", label = "Time period breakdown",
                                        choices = c("Daily", "Weekly", "Monthly"), 
                                        selected = "Weekly"),
                           
                           pickerInput(
                             inputId = "conversion_type",
                             label = "Conversion Type", 
                             choices = NULL
                           ),
                           
                           pickerInput(
                             inputId = "first_breakdown",
                             label = "First breakdown:", 
                             choices = NULL,
                             options = list(`actions-box` = TRUE, `live-search` = TRUE)),
                           
                           pickerInput(
                             inputId = "sec_breakdown",
                             label = "Second breakdown:", 
                             choices = NULL,
                             selected = "",
                             options = list(title = "Please select", `live-search` = TRUE))
                         )
                  ),
                  
                  column(6,
                         box(
                           title = strong("Page 1"),
                           solidHeader = TRUE,
                           width = 12,
                           plotlyOutput('graph_acq'))),
                  column(4,
                         box(
                           width = 12,
                           title = strong("MOM-YOY Breakdown"),
                           solidHeader = TRUE,
                           radioGroupButtons(
                             inputId = "mom_yoy_period",
                             label = "Time Period", 
                             choices = c("Weekly", "Monthly"),
                             status = "acq_class",
                             selected = "Weekly"
                           ),
                           DTOutput("yoy_wow"))
                  )
                  
                )
                
        ),
        tabItem(tabName = "subtab2",
                fluidRow(
                  column(3,
                         box(width = 12,
                             title = strong("Settings"),
                             solidHeader = TRUE,
                             pickerInput(
                               inputId = "week_range",
                               label = "Week Range", 
                               choices = week_boundaries$description,
                               selected = week_boundaries$description[2]),
                             
                             pickerInput(
                               inputId = "application_last_week",
                               label = "Application", 
                               choices = NULL,
                               options = list(`actions-box` = TRUE, `live-search` = TRUE),
                               multiple = TRUE),
                             
                             prettyCheckboxGroup(
                               inputId = "channel_last_week",
                               label = "Channel:", 
                               choices = NULL,
                               status = "primary",
                               outline = TRUE,
                               animation = "jelly"
                             )
                             
                         )
                  ),
                  column(2,
                         box(width = 12,
                             title = "Step 1",
                             solidHeader = FALSE,
                             status = "warning",
                             footer = fluidRow(
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h2('444')
                                 )
                               ),
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h3('Target: 444')
                                 )
                               )
                             )
                         )
                  ),
                  column(2,
                         box(width = 12,
                             title = "Step 2",
                             solidHeader = FALSE,
                             status = "warning",
                             footer = fluidRow(
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h2('444')
                                 )
                               ),
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h3('Target: 444')
                                 )
                               )
                             )
                         )
                  ),
                  column(2,
                         box(width = 12,
                             title = "Step 3",
                             solidHeader = FALSE,
                             status = "warning",
                             footer = fluidRow(
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h2('444')
                                 )
                               ),
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h3('Target: 444')
                                 )
                               )
                               
                             )
                         )
                  ),
                  column(2,
                         box(width = 12,
                             title = "Step 4",
                             solidHeader = FALSE,
                             status = "warning",
                             footer = fluidRow(
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h2('444')
                                 )
                               ),
                               column(
                                 width = 6,
                                 descriptionBlock(
                                   h3('Target: 444')
                                 )
                               )
                             )
                         )
                  )
                ),
                fluidRow(
                  column(6,
                         box(width = 12,
                             plotlyOutput("last_week_funnel")
                             
                         )
                         
                  ),
                  
                  column(3,
                         box(width = 12,
                             title = "Activations WOW",
                             solidHeader = TRUE,
                             DTOutput("wow_activations"))
                  )
                )
                
        ),
        
        tabItem(tabName = "subtab3",
                
                fluidRow(
                  column(2,
                         box(width = 12,
                             title = strong("Page 3"),
                             solidHeader = TRUE,
                             dateRangeInput('dateRange_page3',
                                            label = 'For the time period:',
                                            start = Sys.Date()-365, end = Sys.Date()),
                             
                             radioButtons("time_breakdown_first_market", label = "Time period breakdown",
                                          choices = c("Daily", "Weekly", "Monthly"), 
                                          selected = "Daily"),
                             
                             h5("Breakdown"),
                             
                             pickerInput(
                               inputId = "first_breakdown_first_market",
                               label = "First breakdown:", 
                               choices = NULL,
                               options = list(`actions-box` = TRUE, `live-search` = TRUE)),
                             
                             pickerInput(
                               inputId = "sec_breakdown_first_market",
                               label = "Second breakdown:", 
                               choices = NULL,
                               selected = "",
                               options = list(title = "Please select", `live-search` = TRUE))
                             
                         )
                  ),
                  column(10,
                         box(
                           width = 12,
                           height = 1200,
                           plotlyOutput("graph")
                         )
                         
                  )
                  
                )   
        )
      )
      
    ),
    controlbar = dashboardControlbar()
    
    
  ),
  server = function(input, output) {
    
  }
  
)

Thank you so much!


Solution

  • Please try to make your example minimal and reproducible. Currently it's none.

    It's not minimal because you have included almost 300 lines of code. Do you really expect us to go through that? It's not reproducible because when I run the code it gives Error: object 'week_boundaries' not found

    Your question is not about specific UI elements but of layout in general. So I removed the UI elements and replaced them with 'p("text") to make it simple. It fixes all the issues that you mentioned.

    library(shiny)
    library(bs4Dash)
    library(shinyWidgets)
    library(plotly)
    library(DT)
    
    shinyApp(
      ui = dashboardPage(
        header = dashboardHeader(
          title = "Performance Indicators"
        ),
        sidebar = dashboardSidebar(
          skin = 'light',
          sidebarMenu(
            bs4SidebarMenuItem(tabName = "subtab1",
                               text = "Page 1"
                               # ,icon = shiny::icon("chart-bar")
            ),
            bs4SidebarMenuItem(tabName = "subtab2",
                               text = "Page 2"
                               # ,icon = shiny::icon("chart-bar")
            ),
            bs4SidebarMenuItem(tabName = "subtab3",
                               text = "Page 3"
                               # ,icon = shiny::icon("chart-bar")
            )
          )
        ),
        body = dashboardBody(
          tabItems(
            tabItem(tabName = "subtab1",
                    fluidRow(
                      column(2,p("text")),
                      column(6,p("text")),
                      column(4,p("text"))
                    )),
            tabItem(tabName = "subtab2",
                    fluidRow(
                      column(3,p("text1")
                      ),
                      column(2,p("text")),
                      column(2,p("text")),
                      column(2,p("text")),
                      column(2,p("text"))
                    ),
                    fluidRow(
                      column(6,p("text")),
                      column(3,p("text"))
                    )
            ),
            tabItem(tabName = "subtab3",
                    fluidRow(
                      column(2,p("text")),
                      column(10,p("text"))
                    )   
            )
          )
        ),
        controlbar = dashboardControlbar()
    
      ),
      server = function(input, output) {
        
      }
      
    )
    

    enter image description here

    I would suggest you to start from this and incrementally add the UI elements that you need one by one by replacing p("text") value. Run the dashboard after adding every few elements and check which values messes up the layout that will help you to narrow down the problem.