PROBLEM: R Shiny – Make wellPanel pop-up follow as you scroll with CSS
Hi Stack Users,
I've created a Shiny application that has a data table wherein when a user clicks on a row, a hidden wellPanel will pop-up beside it to show more details related to that row.
The length of the pop-up wellPanel is long but the length of the table is longer (row count non-negotiable). I would like to make the wellPanel follow as I scroll UNTIL the top part of the wellPanel reaches the top visible part of the page. At that point, the wellPanel sticks until the bottom of the page is reached (see images of preferred state below).
Using CSS position: fixed
didn’t do the trick because above the table and the panel, there are instructions for the intended users. As a result, using position: fixed
just permanently sticks the wellPanel to one-part of the webpage and some information gets cut out (see sample app below).
Now, I’m not a web developer/designer by background so my knowledge of CSS is very very minimal, but I had hoped that the CSS solution in this previous post (How do you make a div follow as you scroll? / specifically: https://www.w3schools.com/css/css_positioning.asp) using position: sticky
would work but it still didn't do it.
Hoping to hear from the experts in the community. Thanks!
Miklos
Simplified sample of my app along with images showing preferred state below:
setup.R
#### LOAD PACKAGES ######################
require(shiny)
require(shinyjs)
require(data.table)
require(dplyr)
require(DT)
#### PREPARE DATA ######################
id <- c('10001','10002','10003','10004','10005',
'10006','10007','10008','10009','10010',
'10011','10012','10013','10014','10015',
'10016','10017','10018','10019','10020',
'10021','10022','10023','10024','10025',
'10026','10027','10028','10029','10030',
'10031','10032','10033','10034','10035',
'10036','10037','10038','10039','10040'
)
info <- c('Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info',
'Info','Info','Info','Info','Info'
)
info2 <- sample(1:100,40,replace=T)
info3 <- sample(1:100,40,replace=T)
info4 <- sample(1:100,40,replace=T)
info5 <- sample(1:100,40,replace=T)
info6 <- sample(1:100,40,replace=T)
info7 <- sample(1:100,40,replace=T)
info8 <- sample(1:100,40,replace=T)
info9 <- sample(1:100,40,replace=T)
info10 <- sample(1:100,40,replace=T)
info11 <- sample(1:100,40,replace=T)
info12 <- sample(1:100,40,replace=T)
info13 <- sample(1:100,40,replace=T)
info14 <- sample(1:100,40,replace=T)
info15 <- sample(1:100,40,replace=T)
info16 <- sample(1:100,40,replace=T)
dt <- data.table(id=id,info=info,info2=info2,
info3=info3,info4=info4,info5=info5,
info6=info6,info7=info7,info8=info8,
info9=info9,info10=info10,info11=info11,
info12=info12,info13=info13,info14=info14,
info15=info15,info16=info16
)
#### INSTANTIATE FUNCTIONS ######################
get_instructions <- function() {
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
"
}
render_my_table <- function(dt, sel) {
if(missing(sel)) {
sel = list(mode='single')
} else {
sel = list(mode='single', selected = sel)
}
return (DT::datatable(dt[, list("ID" = id, "Info"=info)],
selection = sel, filter="top",
options = list(sDom = '<"top">lrt<"bottom">ip',
lengthChange = FALSE,
pageLength = 40)))
}
generate_popup_details <- function(user) {
c(
paste("Info 2: ", user$info2),
paste("Info 3: ", user$info3),
paste("Info 4: ", user$info4),
paste("Info 5: ", user$info5),
paste("Info 6: ", user$info6),
paste("Info 7: ", user$info7),
paste("Info 8: ", user$info8),
paste("Info 9: ", user$info9),
paste("Info 10: ", user$info10),
paste("Info 11: ", user$info11),
paste("Info 12: ", user$info12),
paste("Info 13: ", user$info13),
paste("Info 14: ", user$info14),
paste("Info 15: ", user$info15),
paste("Info 16: ", user$info16)
)
}
ui.R
source("setup.R")
shinyUI(fluidPage(
useShinyjs(),
titlePanel("My Shiny Application"),
hr(),
h3("Some Instructions to Users:"),
h5(get_instructions()),
hr(),
mainPanel("",
fluidRow(
splitLayout(div(DT::dataTableOutput('my_table')),
div(
shinyjs::hidden(
wellPanel(id="my_panel", style = "position:fixed;",
h3("More Information",align="center"),
htmlOutput("my_popup")
)
)
)
)
)
)
))
server.R
source("setup.R")
function(input, output, session) {
output$my_table = DT::renderDataTable({
render_my_table(dt)
}, server=TRUE)
observeEvent(input$my_table_cell_clicked, {
row = as.numeric(input$my_table_rows_selected)
user = dt[row]
if(nrow(user) == 0) {
return ()
}
output$my_popup <- renderUI({
HTML(paste(generate_popup_details(user) ,collapse="<br/>"))
})
shinyjs::showElement(id= "my_panel")
})
}
PREFERRED STATE:
App upon load
User reaches bottom of the page and wellPanel stays at the top part of the visible page
You can give your Shiny app a special look with cascading style sheets (CSS). CSS is a style language which gives HTML documents a sophisticated look. Since the Shiny app user-interface (UI) is an HTML document, you can use CSS to control how you want your Shiny app to look.
To add CSS to an individual element, pass it to the style argument of the Shiny function that you use to create that element. In the script below, I set the style of the title of the Shiny app with the style argument of h1 in headerPanel. The style relies on a font that I import with tags$style in tags$head.
The create this row within a Shiny application you’d use the following code: Note that the total size of the nested columns is 9, the same as their parent column. The Bootstrap grid system supports responsive CSS, which enables your application to automatically adapt its layout for viewing on different sized devices.
Inline CSS p (style = "color:red;", "Red text"). However, if you correctly followed the previous part about HTML dependencies, the best way in Shiny is to create a dependency, and attach it to a tag: Following this method, you make the file accessible on the server, thereby easing the debugging process. When should we apply the above method?
Use this JavaScript code:
js <- "
$(document).ready(function(){
var tbl = document.getElementById('my_table');
$('#my_panel').css('top', tbl.getBoundingClientRect().top);
$(window).scroll(function() {
var tbltop = tbl.getBoundingClientRect().top;
var x = tbltop < 0 ? 0 : tbltop;
$('#my_panel').css('top', x);
});
});"
To include in the app like this:
ui <- fluidPage(
tags$head(tags$script(HTML(js))),
useShinyjs(),
......
(Do not change anything else).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With