Search code examples
rquarto

How to programmatically generate tabset-panel in quarto?


I've provided a small reproducible example below. I would like to generate tabs in quarto for each of the ggplot objects within a named list plots. The below quarto document would render the figures in their own 2nd level heading, but not in tabs as expected.

---
title: "Untitled"
format: html
---

```{r}
library(tidyverse)

data <- iris %>% as_tibble()

plots <- data %>%
  group_nest(Species) %>% 
  deframe() %>% 
  map(., ~ {
    ggplot(.x, aes(x = Sepal.Length, y = Sepal.Width)) + 
      geom_point()
  })

```

# Iris Plots 

::: {.panel-tabset}
```{r}
#| column: screen
#| fig-width: 12
#| fig-height: 8
#| fig-align: center
#| results: asis

iwalk(plots, ~ {
  cat('## ', .y, '\n\n')
  
  print(.x)
  
  cat('\n\n')
  
})

```

:::

The document would correctly render the plots within tabs as expected when the chunk-options (all except results:asis) were removed.

# Iris Plots 

::: {.panel-tabset}
```{r}
#| results: asis

iwalk(plots, ~ {
  cat('## ', .y, '\n\n')
  
  print(.x)
  
  cat('\n\n')
  
})

```

:::

Solution

  • Updated Answer

    Now if you want to generate tabsets which would expand the whole width of the screen, wrap the .panel-tabset div with the .column-screen div.

    Note that, we have to use more : for .column-screen than that of .panel-tabset div. We have used three : for .panel-tabset, so we have to use four more of the : to create div for column-screen.


    ---
    title: "Panel tabs"
    format: html
    ---
    
    ```{r}
    library(tidyverse)
    
    data <- iris %>% as_tibble()
    
    plots <- data %>%
      group_nest(Species) %>% 
      deframe() %>% 
      map(., ~ {
        ggplot(.x, aes(x = Sepal.Length, y = Sepal.Width)) + 
          geom_point() +
          theme_bw(
            base_size = 18 # to increase the size of the plot elements
          )
      }) 
    
    ```
    
    # Iris Plots 
    
    :::: {.column-screen}
    ::: {.panel-tabset}
    ```{r}
    #| results: asis
    #| fig-width: 14
    #| fig-height: 6
    
    iwalk(plots, ~ {
      cat('## ', .y, '\n\n')
      
      print(.x)
      
      cat('\n\n')
      
    })
    
    ```
    
    :::
    :::: 
    
    

    Now the panel tabsets are expanded to the width of the screen.

    panel_tab_with_screen_width

    Also Note that, I have increased the size of elements of the plot (e.g. axis.title, axis.text etc.) with base_size = 18 in plot-theme.


    Old Answer

    Your first approach would work if you just remove the column: screen and fig-align: center from the chunk option.

    Because these two chunk options are preventing .panel-tabset from properly creating the divs for rendering tabsets.

    So this works after removing these two chunk option (and you don't need fig-align: center since figures in tabsets are by default centered.


    # Iris Plots 
    
    ::: {.panel-tabset}
    ```{r}
    #| fig-width: 12
    #| fig-height: 8
    #| results: asis
    
    iwalk(plots, ~ {
      cat('## ', .y, '\n\n')
      
      print(.x)
      
      cat('\n\n')
      
    })
    
    ```