gt icon indicating copy to clipboard operation
gt copied to clipboard

Correct way to do sticky headers on non-interactive tables?

Open slodge opened this issue 1 year ago • 2 comments

Prework

  • [x] Read and agree to the code of conduct and contributing guidelines.
  • [x] If there is already a relevant issue, whether open or closed, comment on the existing thread instead of posting a new issue.
  • [x] For any problems you identify, a minimal reproducible example so the maintainer can troubleshoot. A reproducible example is:
    • [x] Runnable: post enough R code and data so any onlooker can create the error on their own computer.
    • [x] Minimal: reduce runtime wherever possible and remove complicated details that are irrelevant to the issue at hand.
    • [x] Readable: format your code according to the tidyverse style guide.

Question

I've been trying to get sticky headers to work and have found it quite hard to get working well.

I'm wondering if there are any recommendations for the best way(s) to do sticky headers.

Examples

This simple Shiny app has problems where the scrolling content scrolls above the header

library(tidyverse)
library(gt)
library(reactable)
library(shiny)

g_output <- gt_output("iris_table")

ui <- fluidPage(
  shiny::fluidRow(
    column(width=4,
           h4("Great"),
           tags$div(id="great",
                    style="height:400px;",
                    g_output)
           )
  )
)

server <- function(input, output, session) {
  output$iris_table <- render_gt({
    iris |> 
      gt() |> 
      tab_options(column_labels.background.color = "pink") |> 
      tab_options(
        container.height = px(400)
      ) |> 
      tab_style(
        style = css(position = "sticky", top = px(0)),
        locations = list(cells_column_spanners(), cells_column_labels())
      ) 
  })
  
}

shinyApp(ui, server)

image

It can be fixed by tweaking some tab_option and tab_style calls:

library(tidyverse)
library(gt)
library(reactable)
library(shiny)

g_output <- gt_output("iris_table")

ui <- fluidPage(
  shiny::fluidRow(
    column(width=4,
           h4("Great"),
           tags$div(id="great",
                    style="height:400px;",
                    g_output)
           )
  )
)

server <- function(input, output, session) {
  output$iris_table <- render_gt({
    iris |> 
      gt() |> 
      tab_options(column_labels.background.color = "pink") |> 
      tab_options(
        container.height = px(400),
        container.padding.y = px(0)
      ) |> 
      tab_style(
        style = css(position = "sticky", top = px(-1), zIndex = 100),
        locations = list(cells_column_spanners(), cells_column_labels())
      ) 
  })
  
}

shinyApp(ui, server)

giving image

but this feels quite technical and unpleasant (especially things like px(-1) - are there any recommendations for better ways to achieve this?

Additional Question

I've really struggled (not found a solution yet) to get column_spanners to work with fixed headers:

library(tidyverse)
library(gt)
library(reactable)
library(shiny)

g_output <- gt_output("iris_table")

ui <- fluidPage(
  shiny::fluidRow(
    column(width=4,
           h4("Great"),
           tags$div(id="great",
                    style="height:400px;",
                    g_output)
           )
  )
)

server <- function(input, output, session) {
  output$iris_table <- render_gt({
    iris |> 
      gt() |> 
      tab_options(column_labels.background.color = "pink") |> 
      tab_options(
        container.height = px(400),
        container.padding.y = px(0)
      ) |> 
      tab_spanner("Petals", columns = c(Petal.Length, Petal.Width)) |>
      tab_style(
        style = css(position = "sticky", top = px(0), zIndex = 100),
        locations = list(cells_column_spanners(), cells_column_labels())
      ) 
  })
  
}

shinyApp(ui, server)

gives image

Is there any recommendation for working with fixed headers and spanner columns? Does my locations and/or css code just need some tweaking?

slodge avatar Jan 19 '24 15:01 slodge

As a feature request, maybe a column_labels.sticky argument in tab_options() would be great too!

olivroy avatar Jun 19 '24 20:06 olivroy

As soon as the spanner issue is solved I’m all for including this as a basic feature :)

rich-iannone avatar Jun 19 '24 20:06 rich-iannone