Skip to content

Commit e4625bb

Browse files
theme helper functions
five sets of theme helpers for seven plotting and table packages
1 parent 50c2791 commit e4625bb

File tree

14 files changed

+647
-0
lines changed

14 files changed

+647
-0
lines changed

DESCRIPTION

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,19 @@ Imports:
2929
yaml
3030
Suggests:
3131
curl,
32+
flextable,
33+
ggiraph,
34+
ggplot2,
35+
gt,
36+
heatmaply,
3237
knitr,
38+
palmerpenguins,
39+
patchwork,
40+
plotly,
3341
rsconnect (>= 0.8.26),
3442
testthat (>= 3.1.7),
43+
thematic,
44+
tidyverse,
3545
withr,
3646
xfun
3747
VignetteBuilder:

R/theme.R

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
#' Create a theme for a plotting or table package
2+
#'
3+
#' Create a theme using background and foreground colors (`theme_colors_*`) or
4+
#' using a **brand.yml** file (`theme_brand_*`).
5+
#'
6+
#' The use of the theme will depend on the package. See the vignettes for
7+
#' usage examples.
8+
#'
9+
#' @param bg The background color
10+
#' @param fg The foreground color
11+
#' @param brand_yml The path to a brand.yml file
12+
13+
14+
#' @rdname theme_helpers
15+
#'
16+
#' @export
17+
theme_colors_flextable <- function(bg, fg) {
18+
(function(x) {
19+
if (!inherits(x, "flextable")) {
20+
stop("theme_colors_flextable only supports flextable objects.")
21+
}
22+
x <- flextable::bg(x, bg = bg, part = "all")
23+
x <- flextable::color(x, color = fg, part = "all")
24+
flextable::autofit(x)
25+
})
26+
}
27+
28+
#' @rdname theme_helpers
29+
#'
30+
#' @export
31+
theme_brand_flextable <- function(brand_yml) {
32+
brand <- yaml::yaml.load_file(brand_yml)
33+
theme_colors_flextable(brand$color$background, brand$color$foreground)
34+
}
35+
36+
37+
#' @rdname theme_helpers
38+
#'
39+
#' @export
40+
theme_colors_ggplot <- function(bg, fg) {
41+
if (!requireNamespace("ggplot2", quietly = TRUE)) {
42+
return(NULL)
43+
}
44+
ggplot2::`%+%`(ggplot2::theme_minimal(base_size = 11),
45+
ggplot2::theme(
46+
panel.border = ggplot2::element_blank(),
47+
panel.grid.major.y = ggplot2::element_blank(),
48+
panel.grid.minor.y = ggplot2::element_blank(),
49+
panel.grid.major.x = ggplot2::element_blank(),
50+
panel.grid.minor.x = ggplot2::element_blank(),
51+
text = ggplot2::element_text(colour = fg),
52+
axis.text = ggplot2::element_text(colour = fg),
53+
rect = ggplot2::element_rect(colour = bg, fill = bg),
54+
plot.background = ggplot2::element_rect(fill = bg, colour = NA),
55+
axis.line = ggplot2::element_line(colour = fg),
56+
axis.ticks = ggplot2::element_line(colour = fg)
57+
))
58+
}
59+
60+
#' @rdname theme_helpers
61+
#'
62+
#' @export
63+
theme_brand_ggplot <- function(brand_yml) {
64+
brand <- yaml::yaml.load_file(brand_yml)
65+
theme_colors_ggplot(brand$color$background, brand$color$foreground)
66+
}
67+
68+
69+
#' @rdname theme_helpers
70+
#'
71+
#' @export
72+
theme_colors_gt <- function(bg, fg) {
73+
(function(table) {
74+
table |>
75+
gt::tab_options(
76+
table.background.color = bg,
77+
table.font.color = fg,
78+
)
79+
})
80+
}
81+
82+
#' @rdname theme_helpers
83+
#'
84+
#' @export
85+
theme_brand_gt <- function(brand_yml) {
86+
brand <- yaml::yaml.load_file(brand_yml)
87+
theme_colors_gt(brand$color$background, brand$color$foreground)
88+
}
89+
90+
#' @rdname theme_helpers
91+
#'
92+
#' @export
93+
theme_colors_plotly <- function(bg, fg) {
94+
(function(plot) {
95+
plot |> plotly::layout(paper_bgcolor = bg,
96+
plot_bgcolor = bg,
97+
font = list(color = fg)
98+
)
99+
})
100+
}
101+
102+
#' @rdname theme_helpers
103+
#'
104+
#' @export
105+
theme_brand_plotly <- function(brand_yml) {
106+
brand <- yaml::yaml.load_file(brand_yml)
107+
theme_colors_plotly(brand$color$background, brand$color$foreground)
108+
}
109+
110+
111+
#' @rdname theme_helpers
112+
#'
113+
#' @export
114+
theme_colors_thematic <- function(bg, fg) {
115+
(function() {
116+
thematic::thematic_rmd(
117+
bg = bg,
118+
fg = fg,
119+
)})
120+
}
121+
122+
#' @rdname theme_helpers
123+
#'
124+
#' @export
125+
theme_brand_thematic <- function(brand_yml) {
126+
brand <- yaml::yaml.load_file(brand_yml)
127+
theme_colors_thematic(brand$color$background, brand$color$foreground)
128+
}

_pkgdown.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,10 @@ reference:
4545
- is_using_quarto
4646
- quarto_binary_sitrep
4747

48+
- title: "Theme Helpers"
49+
desc: >
50+
These simple helper functions adapt plotting and table packages to use background and
51+
foreground colors, or brand.yml colors.
52+
contents:
53+
- starts_with("theme_colors")
54+
- starts_with("theme_brand")

tests/testthat/test-theme.R

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
2+
test_that("render flextable", {
3+
skip_if_no_quarto()
4+
quarto_render("theme/flextable.qmd", quiet = TRUE)
5+
expect_true(file.exists("theme/flextable.html"))
6+
unlink("theme/flextable.html")
7+
})
8+
9+
10+
test_that("render ggiraph", {
11+
skip_if_no_quarto()
12+
quarto_render("theme/ggiraph.qmd", quiet = TRUE)
13+
expect_true(file.exists("theme/ggiraph.html"))
14+
unlink("theme/ggiraph.html")
15+
})
16+
17+
18+
test_that("render ggplot", {
19+
skip_if_no_quarto()
20+
quarto_render("theme/ggplot.qmd", quiet = TRUE)
21+
expect_true(file.exists("theme/ggplot.html"))
22+
unlink("theme/ggplot.html")
23+
})
24+
25+
26+
test_that("render gt", {
27+
skip_if_no_quarto()
28+
quarto_render("theme/gt.qmd", quiet = TRUE)
29+
expect_true(file.exists("theme/gt.html"))
30+
unlink("theme/gt.html")
31+
})
32+
33+
34+
test_that("render heatmaply", {
35+
skip_if_no_quarto()
36+
quarto_render("theme/heatmaply.qmd", quiet = TRUE)
37+
expect_true(file.exists("theme/heatmaply.html"))
38+
unlink("theme/heatmaply.html")
39+
})
40+
41+
42+
test_that("render plotly-r", {
43+
skip_if_no_quarto()
44+
quarto_render("theme/plotly-r.qmd", quiet = TRUE)
45+
expect_true(file.exists("theme/plotly-r.html"))
46+
unlink("theme/plotly-r.html")
47+
})
48+
49+
50+
test_that("render thematic", {
51+
skip_if_no_quarto()
52+
quarto_render("theme/thematic.qmd", quiet = TRUE)
53+
expect_true(file.exists("theme/thematic.html"))
54+
unlink("theme/thematic.html")
55+
})
56+

tests/testthat/theme/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/.quarto/

tests/testthat/theme/flextable.qmd

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
title: "knitr dark mode - flextable"
3+
brand:
4+
light: united-brand.yml
5+
dark: slate-brand.yml
6+
execute:
7+
echo: false
8+
warning: false
9+
---
10+
11+
```{r}
12+
#| echo: false
13+
#| warning: false
14+
library(flextable)
15+
library(quarto)
16+
17+
united_theme <- theme_brand_flextable('united-brand.yml')
18+
slate_theme <- theme_brand_flextable('slate-brand.yml')
19+
```
20+
21+
```{r}
22+
#| renderings: [light, dark]
23+
24+
ft <- flextable(airquality[ sample.int(10),])
25+
ft <- add_header_row(ft,
26+
colwidths = c(4, 2),
27+
values = c("Air quality", "Time")
28+
)
29+
ft <- theme_vanilla(ft)
30+
ft <- add_footer_lines(ft, "Daily air quality measurements in New York, May to September 1973.")
31+
ft <- color(ft, part = "footer", color = "#666666")
32+
ft <- set_caption(ft, caption = "New York Air Quality Measurements")
33+
34+
ft |> united_theme()
35+
ft |> slate_theme()
36+
```
37+
38+
Here's a [link](https://example.com).
39+
40+
{{< lipsum 2 >}}

tests/testthat/theme/ggiraph.qmd

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
title: "dark mode - ggiraph"
3+
brand:
4+
light: united-brand.yml
5+
dark: slate-brand.yml
6+
---
7+
8+
```{r}
9+
#| echo: false
10+
#| warning: false
11+
library(quarto)
12+
library(ggplot2)
13+
library(ggiraph)
14+
15+
united_theme <- theme_brand_ggplot("united-brand.yml")
16+
slate_theme <- theme_brand_ggplot("slate-brand.yml")
17+
```
18+
19+
```{r}
20+
#| renderings: [light, dark]
21+
cars <- ggplot(mtcars, aes(mpg, wt)) +
22+
geom_point_interactive(aes(colour = factor(cyl), tooltip = rownames(mtcars))) +
23+
scale_colour_manual(values = c("darkorange", "purple", "cyan4"))
24+
25+
girafe(ggobj = cars + united_theme)
26+
girafe(ggobj = cars + slate_theme)
27+
```

tests/testthat/theme/ggplot.qmd

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
---
2+
title: "knitr dark mode - ggplot"
3+
brand:
4+
light: united-brand.yml
5+
dark: slate-brand.yml
6+
---
7+
``
8+
9+
```{r}
10+
#| echo: false
11+
#| warning: false
12+
library(quarto)
13+
library(ggplot2)
14+
15+
united_theme <- theme_brand_ggplot("united-brand.yml")
16+
slate_theme <- theme_brand_ggplot("slate-brand.yml")
17+
```
18+
19+
```{r}
20+
#| renderings: [light, dark]
21+
cars <- ggplot(mtcars, aes(mpg, wt)) +
22+
geom_point(aes(colour = factor(cyl))) +
23+
scale_colour_manual(values = c("darkorange", "purple", "cyan4"))
24+
25+
cars + united_theme
26+
cars + slate_theme
27+
```

0 commit comments

Comments
 (0)