Skip to content

Commit 8578da7

Browse files
committed
Add styling for interactive tables
1 parent aebc2b1 commit 8578da7

File tree

3 files changed

+164
-36
lines changed

3 files changed

+164
-36
lines changed

NEWS.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
## Interactive table support
88

9-
* Interactive tables will show no border if `opt_table_lines(extent = "none")` is specified (#1307).
9+
* Interactive tables respect`opt_table_lines(extent = "none")` and `opt_table_lines(extent = "all")` is specified (#1307).
1010

1111
* Interactive tables now respect more styling options.
1212

1313
* `column_labels.background.color`, `row_group.background.color`, `row_group.font.weight`, `table_body.hlines.style`,
14-
`table.font.weight`, `table.font.size`, `stub.font.weight` (#1693).
14+
`table.font.weight`, `table.font.size`, `stub.font.weight`, `stub_background.color` (#1693).
1515

1616
* `opt_interactive()` now works when columns are merged with `cols_merge()` (@olivroy, #1785).
1717

R/render_as_i_html.R

+96-28
Original file line numberDiff line numberDiff line change
@@ -171,35 +171,57 @@ render_as_ihtml <- function(data, id) {
171171

172172
table_width <- opt_val(data = data, option = "table_width")
173173
table_background_color <- opt_val(data = data, option = "table_background_color")
174+
table_font_size <- opt_val(data = data, "table_font_size")
174175
table_font_names <- opt_val(data = data, option = "table_font_names")
175176
table_font_color <- opt_val(data = data, option = "table_font_color")
177+
table_border_right_style <- opt_val(data, "table_border_right_style")
178+
table_border_right_color <- opt_val(data, "table_border_right_color")
179+
table_border_left_style <- opt_val(data, "table_border_left_style")
180+
table_border_left_color <- opt_val(data, "table_border_left_color")
181+
table_border_top_color <- opt_val(data, "table_border_top_color")
182+
183+
heading_border_bottom_color <- opt_val(data, "heading_border_bottom_color")
176184

177185
column_labels_border_top_style <- opt_val(data = data, option = "column_labels_border_top_style")
178186
column_labels_border_top_width <- opt_val(data = data, option = "column_labels_border_top_width")
179187
column_labels_border_top_color <- opt_val(data = data, option = "column_labels_border_top_color")
180188
column_labels_border_bottom_style <- opt_val(data = data, option = "column_labels_border_bottom_style")
181189
column_labels_border_bottom_width <- opt_val(data = data, option = "column_labels_border_bottom_width")
182190
column_labels_border_bottom_color <- opt_val(data = data, option = "column_labels_border_bottom_color")
191+
183192
# Don't allow NA
184193
column_labels_background_color <- opt_val(data = data, option = "column_labels_background_color")
185-
# Apply stub font weight to
186-
stub_font_weight <- opt_val(data = data, option = "stub_font_weight")
187-
188194
if (is.na(column_labels_background_color)) {
189195
# apply all column labels formatting to both heading + groupCol styling (nothing specific for spanners styling in gt?)
190196
column_labels_background_color <- "transparent"
191197
}
192-
# Part of #1307
193-
borderless_borders <- opt_val(data = data, option = "table_body_hlines_style") == "none"
194198

195199
column_labels_font_weight <- opt_val(data = data, option = "column_labels_font_weight")
200+
# Apply stub font weight to
201+
stub_font_weight <- opt_val(data = data, option = "stub_font_weight")
196202
# Apply font weight to groupname_col title
197-
row_group_font_weight <- opt_val(data = data, "row_group_font_weight")
198-
table_body_font_weight <- opt_val(data = data, "table_font_weight")
203+
row_group_font_weight <- opt_val(data = data, "row_group_font_weight")
204+
row_group_background_color <- opt_val(data = data, "row_group_background_color")
205+
206+
table_body_font_weight <- opt_val(data = data, "table_font_weight")
207+
table_body_hlines_style <- opt_val(data = data, "table_body_hlines_style")
208+
table_body_hlines_color <- opt_val(data = data, "table_body_hlines_color")
209+
table_body_hlines_width <- opt_val(data = data, "table_body_hlines_width")
210+
table_body_vlines_style <- opt_val(data = data, "table_body_vlines_style")
211+
table_body_vlines_color <- opt_val(data = data, "table_body_vlines_color")
212+
table_body_vlines_width <- opt_val(data = data, "table_body_vlines_width")
213+
214+
horizontal_borders <- opt_val(data = data, option = "table_body_hlines_style")
215+
veritcal_borders <- opt_val(data = data, option = "table_body_vlines_style")
216+
borderless_borders <- horizontal_borders == "none" && veritcal_borders == "none"
217+
all_borders <- horizontal_borders != "none" && veritcal_borders != "none"
218+
199219
# for row names + summary label
200-
stub_font_weight <- opt_val(data = data, "stub_font_weight")
201-
# #1693 table font size
202-
table_font_size <- opt_val(data = data, "table_font_size")
220+
stub_border_color <- opt_val(data, "stub_border_color")
221+
stub_border_style <- opt_val(data, "stub_border_style")
222+
# Apply stub font weight to
223+
stub_font_weight <- opt_val(data = data, option = "stub_font_weight")
224+
stub_background_color <- opt_val(data = data, option = "stub_background_color")
203225

204226
emoji_symbol_fonts <-
205227
c(
@@ -222,7 +244,13 @@ render_as_ihtml <- function(data, id) {
222244
row_name_col_def <- list(reactable::colDef(
223245
name = rowname_label,
224246
style = list(
225-
fontWeight = stub_font_weight
247+
fontWeight = stub_font_weight,
248+
color = if (!is.na(stub_background_color)) unname(ideal_fgnd_color(stub_background_color)) else NULL,
249+
borderRight = stub_border_color,
250+
borderRightStyle = stub_border_style,
251+
backgroundColor = stub_background_color#,
252+
253+
# borderLeft, borderRight are possible
226254
)
227255
# TODO pass on other attributes of row names column if necessary.
228256
))
@@ -347,7 +375,13 @@ render_as_ihtml <- function(data, id) {
347375
reactable::colDef(
348376
name = group_label,
349377
style = list(
350-
`font-weight` = row_group_font_weight
378+
`font-weight` = row_group_font_weight,
379+
color = if (is.na(row_group_background_color)) NULL else unname(ideal_fgnd_color(row_group_background_colorfgggee )),
380+
backgroundColor = row_group_background_color,
381+
borderStyle = "none",
382+
borderColor = "transparent",
383+
borderTopColor = "transparent",
384+
borderBottomColor = "gray38"
351385
),
352386
# The total number of rows is wrong in colGroup, possibly due to the JS fn
353387
grouped = grp_fn,
@@ -382,7 +416,7 @@ render_as_ihtml <- function(data, id) {
382416
styles_tbl <- dt_styles_get(data = data)
383417
body_styles_tbl <- dplyr::filter(styles_tbl, locname %in% c("data", "stub"))
384418
body_styles_tbl <- dplyr::arrange(body_styles_tbl, colnum, rownum)
385-
body_styles_tbl <- dplyr::select(body_styles_tbl, colname, rownum, html_style)
419+
body_styles_tbl <- dplyr::select(body_styles_tbl, "colname", "rownum", "html_style")
386420

387421
# Generate styling rule per combination of `colname` and
388422
# `rownum` in `body_styles_tbl`
@@ -431,28 +465,40 @@ render_as_ihtml <- function(data, id) {
431465

432466
# Generate the table header if there are any heading components
433467
if (has_header_section) {
468+
# These don't work in non-interactive context.
469+
heading_title_font_weight <- opt_val(data, "heading_title_font_weight")
470+
heading_subtitle_font_weight <- opt_val(data, "heading_subtitle_font_weight")
471+
heading_background_color <- opt_val(data, "heading_background_color")
434472

435473
tbl_heading <- dt_heading_get(data = data)
436-
437474
heading_component <-
438475
htmltools::div(
439476
style = htmltools::css(
440477
`font-family` = font_family_str,
478+
`background-color` = heading_background_color,
441479
`border-top-style` = "solid",
442480
`border-top-width` = "2px",
443481
`border-top-color` = "#D3D3D3",
482+
`border-bottom-color` = "#D3D3D3",
444483
`padding-bottom` = if (use_search) "8px" else NULL
445484
),
446485
htmltools::div(
447486
class = "gt_heading gt_title gt_font_normal",
448-
style = htmltools::css(`text-size` = "bigger"),
487+
style = htmltools::css(
488+
`text-size` = "bigger",
489+
`font-weight` = heading_title_font_weight
490+
),
449491
htmltools::HTML(tbl_heading$title)
450492
),
451493
htmltools::div(
452494
class = paste(
453495
"gt_heading", "gt_subtitle",
454496
if (use_search) "gt_bottom_border" else NULL
455497
),
498+
style = htmltools::css(
499+
`font-weight` = heading_subtitle_font_weight,
500+
`border-bottom-color` = "#D3D3D3"
501+
),
456502
htmltools::HTML(tbl_heading$subtitle)
457503
)
458504
)
@@ -476,14 +522,16 @@ render_as_ihtml <- function(data, id) {
476522
footnotes_component <- NULL
477523
}
478524

525+
table_border_bottom_style <- opt_val(data, "table_border_bottom_style")
526+
479527
footer_component <-
480528
htmltools::div(
481529
style = htmltools::css(
482530
`font-family` = font_family_str,
483531
`border-top-style` = "solid",
484532
`border-top-width` = "2px",
485533
`border-top-color` = "#D3D3D3",
486-
`border-bottom-style` = "solid",
534+
`border-bottom-style` = table_border_bottom_style,
487535
`border-bottom-width` = "2px",
488536
`border-bottom-color` = "#D3D3D3",
489537
`padding-top` = "6px",
@@ -542,6 +590,7 @@ render_as_ihtml <- function(data, id) {
542590
headerClass = NULL,
543591
headerStyle = list(
544592
fontWeight = "normal",
593+
color = if (is.na(column_labels_background_color)) NULL else unname(ideal_fgnd_color(column_labels_background_color)),
545594
backgroundColor = column_labels_background_color,
546595
borderBottomStyle = column_labels_border_bottom_style,
547596
borderBottomWidth = column_labels_border_bottom_width,
@@ -573,18 +622,25 @@ render_as_ihtml <- function(data, id) {
573622
#1693
574623
fontSize = table_font_size
575624
),
576-
tableStyle = list(
577-
borderTopStyle = column_labels_border_top_style,
578-
borderTopWidth = column_labels_border_top_width,
579-
borderTopColor = column_labels_border_top_color
625+
# borders in the body
626+
rowStyle = list(
627+
fontWeight = table_body_font_weight,
628+
borderTopStyle = table_body_hlines_style,
629+
borderTopColor = table_body_hlines_color,
630+
borderTopWidth = table_body_hlines_width,
631+
BorderRightStyle = table_body_vlines_style,
632+
BorderRightColor = table_body_vlines_color,
633+
BorderRightWidth = table_body_vlines_width
580634
),
581635
# cells_column_labels()
582636
headerStyle = list(
583637
fontWeight = column_labels_font_weight,
584638
backgroundColor = column_labels_background_color,
585639
borderBottomStyle = column_labels_border_bottom_style,
586640
borderBottomWidth = column_labels_border_bottom_width,
587-
borderBottomColor = column_labels_border_bottom_color
641+
borderBottomColor = column_labels_border_bottom_color,
642+
borderTopColor = "transparent",
643+
borderTopStyle = "none"
588644
),
589645
# individually defined for the margins left+right
590646
# cells_spanner_labels() styling
@@ -595,19 +651,30 @@ render_as_ihtml <- function(data, id) {
595651
borderBottomWidth = column_labels_border_bottom_width,
596652
borderBottomColor = column_labels_border_bottom_color
597653
),
598-
tableBodyStyle = NULL,
654+
# body = table
655+
tableStyle = list(
656+
borderRightStyle = table_border_right_style,
657+
borderRightColor = table_border_right_color,
658+
borderLeftStyle = table_border_left_style,
659+
borderLeftColor = table_border_right_style,
660+
borderBttomColor = heading_border_bottom_color
661+
),
599662
# stub styling?
600663
# rowGroupStyle = list(
664+
# backgroundColor = row_group_background_color,
601665
# fontWeight = row_group_font_weight
602666
# ),
603-
rowStyle = NULL,
667+
# exclude pagination and search
668+
tableBodyStyle = NULL,
604669
rowStripedStyle = NULL,
605670
rowHighlightStyle = NULL,
606671
rowSelectedStyle = NULL,
607672
# cells_body styling
608-
cellStyle = list(
609-
fontWeight = table_body_font_weight
610-
),
673+
# cellStyle = list(
674+
# fontWeight = table_body_font_weight,
675+
# backgroundColor = table_background_color
676+
# ),
677+
# grand_summary style
611678
footerStyle = NULL,
612679
inputStyle = NULL,
613680
filterInputStyle = NULL,
@@ -645,7 +712,7 @@ render_as_ihtml <- function(data, id) {
645712
showPagination = use_pagination,
646713
showPageInfo = use_pagination_info,
647714
minRows = 1,
648-
paginateSubRows = FALSE,
715+
paginateSubRows = TRUE,
649716
details = NULL,
650717
defaultExpanded = expand_groupname_col,
651718
selection = NULL,
@@ -654,7 +721,8 @@ render_as_ihtml <- function(data, id) {
654721
onClick = NULL,
655722
highlight = use_highlight,
656723
outlined = FALSE,
657-
bordered = FALSE,
724+
# equivalent to opt_table_lines(extent = "all")
725+
bordered = all_borders,
658726
# equivalent to opt_table_lines(extent = "none")
659727
borderless = borderless_borders,
660728
striped = use_row_striping,

vignettes/gt-interactive.qmd

+66-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
---
22
title: "gt interactive tables"
33
format: html
4+
html-table-processing: none
45
description: >
56
An overview of interactive tables with gt
67
---
@@ -10,6 +11,8 @@ knitr::opts_chunk$set(
1011
collapse = TRUE,
1112
comment = "#>"
1213
)
14+
# generate the same table ID
15+
set.seed(112)
1316
```
1417

1518
gt provides an option to make interactive html tables via the [reactable](https://glin.github.io/reactable/index.html) package.
@@ -19,27 +22,84 @@ It also provides an interactive to creating gt tables as plots.
1922
Let's use the following base for our gt table.
2023

2124
```{r}
22-
library(gt)
25+
devtools::load_all("~/rrr-forks/gt")
26+
#library(gt)
2327
gt_tbl <- exibble |>
24-
gt()
28+
gt(groupname_col = "group", rowname_col = "row") |>
29+
tab_header(
30+
"Title",
31+
"Subtitle"
32+
) |>
33+
tab_footnote(
34+
"A footnote"
35+
) |>
36+
tab_spanner(
37+
"Spanner",
38+
columns = c(date, time)
39+
)
2540
```
2641

2742
To create an interactive table, you have simply have to pipe `opt_interactive()` to your existing gt pipeline.
2843

44+
::: {.panel-tabset}
45+
46+
## Html
47+
2948
```{r}
3049
gt_tbl
3150
```
3251

52+
## Interactive
53+
3354
```{r}
3455
gt_tbl |>
3556
opt_interactive()
3657
```
3758

38-
# Current limitations
59+
:::
60+
61+
## Examples
62+
63+
Some styling is respected in `opt_interactive()`
64+
65+
```{r}
66+
styled <- gt_tbl |>
67+
tab_options(
68+
heading.title.font.weight = "bold",
69+
stub.background.color = "lightblue",
70+
table.border.bottom.style = "dotted",
71+
column_labels.background.color = "pink",
72+
table.font.weight = "italic",
73+
stub.font.weight = "bolder",
74+
table_body.vlines.color = "brown",
75+
table_body.vlines.style = "dashed"
76+
)
77+
```
78+
79+
::: {.panel-tabset}
80+
## Html
81+
82+
```{r}
83+
#| echo: false
84+
styled
85+
```
86+
87+
## Interactive
88+
89+
```{r}
90+
#| echo: false
91+
styled %>% opt_interactive()
92+
```
3993

40-
* Some features like `tab_style()` may not be fully supported.
94+
:::
95+
96+
97+
98+
99+
# Current limitations
41100

42-
* `summary_rows()` and `grand_summary_rows()` have yet to be implemented.
101+
- Some features like `tab_style()` may not be fully supported.
43102

44-
* Your interactive table may be visually different from your non-interactive table.
103+
- `summary_rows()` and `grand_summary_rows()` have yet to be implemented.
45104

105+
- Your interactive table may be visually different from your non-interactive table.

0 commit comments

Comments
 (0)