Fixed height of tabBox with scrollable content - css

Is there a way to show scrollbars for the content in tabBoxes if I want to fix the height? Additionally, the scrollbar should only work for the content not the tab header itself. The closest I came to a solution was to fix the height of the .tab-content but this obviously highly depends on the height of the tabBox and the height of the tab header within. Resizing the window might cause the tab header to increase in size which causes this workaround to fail. Also, this would fix the height of all .tab-content elements, so if I wanted to create new tabBoxes with different heights, this also would not work.
This is a minimal example of my attempt to solve the problem. If you resize the window such that the second tab does not fit in the first row, the scrollbar and content do not work properly anymore.
if (interactive()) {
library(shiny)
body <- dashboardBody(
tags$head(tags$style(HTML(".nav-tabs-custom { overflow-y: hidden; } .nav-tabs-custom>.tab-content { overflow-y: auto; height: 100px; }"))),
fluidRow(
tabBox(
height = "150px",
tabPanel(
title = "Tab Header 1 - Scrollbar failing when resizing",
p("Test 1"),
p("Test 2"),
p("Test 3"),
p("Test 4"),
p("Test 5")
),
tabPanel(
title = "Tab Header 2 - looooooooooooooooong",
p("Test 1"),
p("Test 2")
)
)
)
)
shinyApp(
ui = dashboardPage(dashboardHeader(disable = TRUE), dashboardSidebar(disable = TRUE), body),
server = function(input, output) {
}
)
}
Any help would be greatly appreciated.

The key is to add the css style overflow-y:scroll; to the div you need a scroll bar on. In this case, I have added it to a div within the first tabPanel by using:
div(style = 'overflow-y:scroll;', ...)
This requires that you wrap the objects that you want to scroll inside of a div().
I've edited your original example to show how to add scrolling to a large data table. also set the height to 500px manually in the same div so that you could see the scroll bar in action.
if (interactive()) {
library(shiny)
body <- dashboardBody(
fluidRow(
tabBox(
tabPanel(
title = "Tab Header 1 - Scrollbar failing when resizing",
div(style = 'overflow-y:scroll;height:500px;',
tableOutput('largedata')
)
),
tabPanel(
title = "Tab Header 2 - looooooooooooooooong",
p("Test 1"),
p("Test 2")
)
)
)
)
shinyApp(
ui = dashboardPage(dashboardHeader(disable = TRUE), dashboardSidebar(disable = TRUE), body),
server = function(input, output) {
output$largedata <- renderTable(mtcars)
}
)
}

Related

How to add more tabs and select-input sub-tab in shinydashboard app

I am having a problem with building an UI for shinydashboard app that has 2 tabs and has select-input sub-tab in the first tab.
The app works fine when there are no tabs, i.e. when there is only select-input menu.
The code that works is this:
ui <- dashboardPage(
dashboardHeader(title = "HAMAG BICRO: 2016 - 2022"),
dashboardSidebar(
selectInput("instrumenti", "Instrumenti",
choices = Instrumenti)),
dashboardBody(
fluidRow(
box(width=12,
title = "Geografski prikaz ulaganja",
leafletOutput("mymap", height=550))),
fluidRow(
box(title ="Odnos ulaganja i stanovništva", plotlyOutput("scatter", width=4,height=220)),
box(title ="Ulaganje po stanovniku", plotlyOutput("bar", width=6,height=250)),
tags$head(tags$style(HTML(' /* body */
.content-wrapper, .right-side {
background-color: #FFFFFF;
}'
))))))`
With this code (without tabs), I get this app:
[![enter image description here][1]][1]
However, I need more tabs in the app so I tried to do something like this:
ui <- dashboardPage(
dashboardHeader(title = "HAMAG BICRO: 2016 - 2022"),
dashboardSidebar(
sidebarMenu(
menuItem("Geo prikaz", tabName = "Geografski prikaz",
menuItem(selectInput("instrumenti", "Instrumenti",
choices = Instrumenti))),
menuItem("Vremenski prikaz", tabName = "Vremenski prikaz"))),
dashboardBody(
tabItems(
# First tab content
tabItem(tabName = "Geografski prikaz",
fluidRow(
box(width=12, title = "Geografski prikaz ulaganja", leafletOutput("mymap", height=550))),
fluidRow(
box(title ="Odnos ulaganja i stanovništva", plotlyOutput("scatter", width=4,height=220)),
box(title ="Ulaganje po stanovniku", plotlyOutput("bar", width=6,height=250)),
tags$head(tags$style(HTML(' /* body */
.content-wrapper, .right-side {
background-color: #FFFFFF;
}'
))))),
# Second tab content
tabItem(tabName = "Vremenski prikaz",
h2("napuniti")))))
I do get more or less correct UI, see here:
[![enter image description here][2]][2]
But, I don't have any content in it.
Can anybody see the problem? tnx
[1]: https://i.stack.imgur.com/9Kxmz.png
[2]: https://i.stack.imgur.com/0xwPl.png
The problem is on your tab ID's names. Removing the space should solve !
the menuItem and tabItem names must match and they shouldnt have white space!
The best pratice is to choose a small lower case name to identify the tabs, but the only MUST is to not have space. So you can try to change "Geografski prikaz" to "Geografski_prikaz" and "Vremenski prikaz" to "Vremenski_prikaz"

How to better position Next/Back button in shiny glide, in order to eliminate large white space?

The Shinyglide package is just what I need, using a carousel for grouped radio buttons giving the user many choices for data parsing.
However, the "Next" (and "Back") button occupies a large white space. I'd like to shift the button in line with the glide row (see image at bottom). Does anyone know how to do this? Is there a CSS trick? Reading through the Glide manual, the only choices are "top" and "bottom".
If moving the Next/Back button isn't possible, a secondary option is to insert (a somewhat superfluous) line of text but in line with the Next/Back buttons, to at least cover up the annoyingly large white space.
The actual panel this is for has much more information presented than in this example, so I'm trying to make the page as clean as possible.
Please see image at bottom that better explains what I'm trying to do.
Reproducible example:
library(dplyr)
library(DT)
library(shiny)
library(shinyglide)
ui <-
fluidPage(
fluidRow(div(style = "margin-top:15px"),
strong("Input choices shown in row below, click ´Next´ to see more choices:"),
column(12, glide(
height = "25",
controls_position = "top",
screen(
div(style = "margin-top:10px"),
wellPanel(
radioButtons(inputId = 'group1',
label = NULL,
choiceNames = c('By period','By MOA'),
choiceValues = c('Period','MOA'),
selected = 'Period',
inline = TRUE
),
style = "padding-top: 12px; padding-bottom: 0px;"
)
),
screen(
div(style = "margin-top:10px"),
wellPanel(
radioButtons(inputId = 'group2',
label = NULL,
choiceNames = c('Exclude CT','Include CT'),
choiceValues = c('Exclude','Include'),
selected = 'Exclude',
inline = TRUE
),
style = "padding-top: 12px; padding-bottom: 0px;"
)
)
)
)
),
DTOutput("plants")
)
server <- function(input, output, session) {
output$plants <- renderDT({iris %>% datatable(rownames = FALSE)})
}
shinyApp(ui, server)
You could use a custom control element with custom_controls, and then have it hover over the displayed screen on the top right with a container set to absolute positioning. Setting a limited width for the container will ensure that the back button won't fly too far out.
Something along these lines:
glide(custom_controls = div(class = "glide-controls", glideControls()), ...)
# Somewhere in the UI
tags$style(
".glide-controls { position: absolute; top: 18px; right: 15px; width: 160px; }"
)
Just make sure to also set controls_position = "bottom" so that the controls hover over the screen content, rather than under it.
A minimal example app:
library(shiny)
library(shinyglide)
ui <- fixedPage(
h3("Simple shinyglide app"),
tags$style(
".glide-controls { position: absolute; top: 18px; right: 15px; width: 160px; }"
),
glide(
custom_controls = div(class = "glide-controls", glideControls()),
screen(wellPanel(p("First screen."))),
screen(wellPanel(p("Second screen.")))
)
)
server <- function(input, output, session) {}
shinyApp(ui, server)

shinydashboard vs shinydashboardPlus - dashboardsidebar title differences

I have a Shiny app built with shinydashboard and I've just discovered shinydashboardPlus. One nice option is to have the sidebarMenu "minified", or when minimized it doesn't go away completely, but just displays the icons for each menuItem. However, with shinydashboardPlus, when minified, the title gets chopped off. With shinydashboard, the title stays intact, but the sidebar goes away completely.
Example code:
library(shiny)
library(shinydashboard)
#library(shinydashboardPlus)
# Basic dashboard page template
shinyApp(
ui = dashboardPage(
dashboardHeader(title = "Example"),
dashboardSidebar(#minified = TRUE,
sidebarMenu(
menuItem('Menu1', tabName = 'Menu1',
icon = icon('folder-open')),
menuItem('Menu2', tabName = 'Menu2',
icon = icon('code-branch'))
)
),
dashboardBody()
),
server = function(input, output) { }
)
Leaving the comment marks in place and running it uses shinydashboard, and gives this initially:
And when the hamburger is clicked to minimize the sidebar, the whole sidebar disappears:
If the comment marks are removed so that it runs using shinydashboardPlus, minimizing it gives this, where I have the icons in the sidebar, but the title is chopped:
Is there a way to get the shinydashboardPlus minification that shows just the icons, but doesn't chop off the title?
Here you go
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
# Basic dashboard page template
shinyApp(
ui = dashboardPage(
dashboardHeader(title = "Example"),
dashboardSidebar(#minified = TRUE,
sidebarMenu(
menuItem('Menu1', tabName = 'Menu1',
icon = icon('folder-open')),
menuItem('Menu2', tabName = 'Menu2',
icon = icon('code-branch'))
)
),
dashboardBody(
tags$style(
'
#media (min-width: 768px){
.sidebar-mini.sidebar-collapse .main-header .logo {
width: 230px;
}
.sidebar-mini.sidebar-collapse .main-header .navbar {
margin-left: 230px;
}
}
'
)
)
),
server = function(input, output) { }
)
change the width and margin-left numbers if you have extreme long titles.

Shinydashboard Tabbox Height

I'm trying to create a tabBox that spans the entire mainPanel. I'm able to get the width to span the entire screen but I'm unable to get the height to do the same. I do not wish to use absolute values in pixels (or some other unit) since I expect the app to be used across different screens.
I played with the example and an example of the modified tabBox is as below
fluidRow(
tabBox(
title = "First tabBox",
# The id lets us use input$tabset1 on the server to find the current tab
id = "tabset1", height = "450px",
tabPanel("Tab1", "First tab content"),
tabPanel("Tab2", "Tab content 2"),
width = 12
),
height = '20%',
width = 12
)
You can use the vh css unit that is defined as 1% of viewport height and then basically follow the example in this answer where you set the relative height in the css:
fluidRow(
tabBox(
tags$head(
tags$style(HTML(" #tabBox { height:90vh !important; } "))
),
id="tabBox",
title = "tabBox",
width = 12
)
You can of course also put this in an external css file, especially if you are going to do more than one of these css tricks. With 100% goes slightly over the bottom edge because of the header. Around 90% seems to work fine.

R shiny scroll wellPanel

Is it possible to scroll a wellPanel or column?
I have a simple ui scheme here.
shinyUI(
fluidPage(
sidebarLayout(
sidebarPanel(
wellPanel(),
wellPanel()
),
mainPanel(
fluidRow(
column(3,
wellPanel()
)
)
)
)
)
)
I would like to make some of those wellPanels (with forms inside) scrollable.
I tried adding this piece of code seen below under 'sidebarPanel(', but that made my whole sidebarpanel to scroll. I am looking to make a 'wellPanel' or a 'column' scrollable.
tags$head(tags$style(
type = 'text/css',
'form-group { max-height: 600px; overflow-y: auto; }')
Thanks
Thanks to Carlos Sanchez, here is the answer:
wellPanel(id = "tPanel",style = "overflow-y:scroll; max-height: 600px",
other-stuff..)

Resources