From 4e1278b7626214af1c0166d963f5c38f1ff78141 Mon Sep 17 00:00:00 2001 From: Jay Hesselberth Date: Sun, 3 Sep 2023 08:55:00 -0600 Subject: [PATCH 01/31] Implement dark mode Copies relevant, recent work from rstudio/bslib kudos to @gadenbuie --- DESCRIPTION | 2 + inst/BS5/assets/pkgdown.js | 132 +++++++++++++++++++++++++++++++++++ inst/BS5/assets/pkgdown.scss | 65 +++++++++++++++++ pkgdown/_pkgdown.yml | 12 +++- 4 files changed, 210 insertions(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 25e38d08e..417184f65 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -62,6 +62,8 @@ VignetteBuilder: Config/Needs/website: usethis, servr Config/potools/style: explicit Config/testthat/edition: 3 +Remotes: + rstudio/bslib Encoding: UTF-8 Roxygen: list(markdown = TRUE) RoxygenNote: 7.2.2.9000 diff --git a/inst/BS5/assets/pkgdown.js b/inst/BS5/assets/pkgdown.js index 5fccd9c0e..36da1d295 100644 --- a/inst/BS5/assets/pkgdown.js +++ b/inst/BS5/assets/pkgdown.js @@ -153,4 +153,136 @@ async function searchFuse(query, callback) { }); })(window.jQuery || window.$) +/*! + * Color mode toggler for Bootstrap's docs (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors + * Licensed under the Creative Commons Attribution 3.0 Unported License. + * Updates for {pkgdown} by the {bslib} authors, also licensed under CC-BY-3.0. + */ +const getStoredTheme = () => localStorage.getItem('theme') +const setStoredTheme = theme => localStorage.setItem('theme', theme) + +const getPreferredTheme = () => { + const storedTheme = getStoredTheme() + if (storedTheme) { + return storedTheme + } + + return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light' +} + +const setTheme = theme => { + if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) { + document.documentElement.setAttribute('data-bs-theme', 'dark') + } else { + document.documentElement.setAttribute('data-bs-theme', theme) + } +} + +setTheme(getPreferredTheme()) + +function bsSetupThemeToggle () { + 'use strict' + + const showActiveTheme = (theme, focus = false) => { + const themeSwitcher = document.querySelector('#bd-theme') + + if (!themeSwitcher) { + return + } + + const themeSwitcherText = document.querySelector('#bd-theme-text') + const activeThemeIcon = document.querySelector('.theme-icon-active') + const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) + const svgOfActiveBtn = btnToActive.querySelector('.theme-icon').innerHTML + + document.querySelectorAll('[data-bs-theme-value]').forEach(element => { + element.classList.remove('active') + element.setAttribute('aria-pressed', 'false') + }) + + btnToActive.classList.add('active') + btnToActive.setAttribute('aria-pressed', 'true') + activeThemeIcon.innerHTML = svgOfActiveBtn + const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})` + themeSwitcher.setAttribute('aria-label', themeSwitcherLabel) + + if (focus) { + themeSwitcher.focus() + } + } + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', () => { + const storedTheme = getStoredTheme() + if (storedTheme !== 'light' && storedTheme !== 'dark') { + setTheme(getPreferredTheme()) + } + }) + + window.addEventListener('DOMContentLoaded', () => { + showActiveTheme(getPreferredTheme()) + + document.querySelectorAll('[data-bs-theme-value]') + .forEach(toggle => { + toggle.addEventListener('click', () => { + const theme = toggle.getAttribute('data-bs-theme-value') + setStoredTheme(theme) + setTheme(theme) + showActiveTheme(theme, true) + }) + }) + }) +} + +function colorPickerMarkup () { + const svgs = { + "sun-fill": ``, + "moon-stars-fill": ``, + "circle-half": `` + } + + const icons = { + "sun-fill": ``, + "moon-stars-fill": ``, + "circle-half": `` + } + + return ` + ` +} + +document.addEventListener('DOMContentLoaded', () => { + const switcher = document.querySelector('.navbar [href$="#dark-mode"]') + if (!switcher) return + + switcher.parentElement.classList.add('dropdown') + switcher.parentElement.innerHTML = colorPickerMarkup() + bsSetupThemeToggle() +}) diff --git a/inst/BS5/assets/pkgdown.scss b/inst/BS5/assets/pkgdown.scss index 2c9e003f6..cf69510c3 100644 --- a/inst/BS5/assets/pkgdown.scss +++ b/inst/BS5/assets/pkgdown.scss @@ -495,3 +495,68 @@ mark { .algolia-autocomplete .aa-dropdown-menu .aa-suggestion.aa-cursor { background-color: mix($primary, $body-bg, 10%); } + +/* ---- Dark Mode ---- */ +[data-bs-theme="dark"] { + .navbar.bg-info { + background-color: #333f48 !important; + } + + ::selection { + background: #344c5a; + } + + input[type="search"] { + border-color: var(--bs-border-color); + } + + pre { + background-color: #272b30; + } + + // low-tech image softening in dark mode + img { + opacity: 0.66; + transition: opacity 250ms ease-in-out; + } + + img:hover, + img:focus, + img:active { + opacity: 1; + } + + // github-dark.css // + pre code /* Normal */ {color:#e1e4e8} + pre code span.al /* Alert */ {color:#ff5555; font-weight: bold} + pre code span.an /* Annotation */ {color:#6a737d} + pre code span.at /* Attribute */ {color:#f97583} + pre code span.bn /* BaseN */ {color:#79b8ff} + pre code span.bu /* BuiltIn */ {color:#f97583} + pre code span.cf /* ControlFlow */ {color:#f97583} + pre code span.ch /* Char */ {color:#9ecbff} + pre code span.cn /* Constant */ {color:#79b8ff} + pre code span.co /* Comment */ {color:#6a737d} + pre code span.cv /* CommentVar */ {color:#6a737d} + pre code span.do /* Documentation */ {color:#6a737d} + pre code span.dt /* DataType */ {color:#f97583} + pre code span.dv /* DecVal */ {color:#79b8ff} + pre code span.er /* Error */ {color:#ff5555; text-decoration: underline} + pre code span.ex /* Extension */ {color:#f97583; font-weight: bold} + pre code span.fl /* Float */ {color:#79b8ff} + pre code span.fu /* Function */ {color:#b392f0} + pre code span.im /* Import */ {color:#9ecbff} + pre code span.in /* Information */ {color:#6a737d} + pre code span.kw /* Keyword */ {color:#f97583} + pre code span.op /* Operator */ {color:#e1e4e8} + pre code span.ot /* Others */ {color:#b392f0} + pre code span.pp /* Preprocessor */ {color:#f97583} + pre code span.re /* RegionMarker */ {color:#6a737d} + pre code span.sc /* SpecialChar */ {color:#79b8ff} + pre code span.ss /* SpecialString */ {color:#9ecbff} + pre code span.st /* String */ {color:#9ecbff} + pre code span.va /* Variable */ {color:#ffab70} + pre code span.vs /* VerbatimString */ {color:#9ecbff} + pre code span.wa /* Warning */ {color:#ff5555} + +} diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index b666746d7..cfd6356d8 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -21,8 +21,18 @@ template: border-radius: 0.5rem btn-border-radius: 0.25rem includes: - in_header: + in_header: > + + +navbar: + bg: info + type: light + structure: + right: [github, dark-mode] + components: + dark-mode: + href: "#dark-mode" development: mode: auto From 56a5f3166467099043597eadf2588b930ddd177a Mon Sep 17 00:00:00 2001 From: Jay Hesselberth Date: Sun, 28 Apr 2024 10:26:47 -0600 Subject: [PATCH 02/31] port over some tweaks from rstudio/bslib --- inst/BS5/assets/pkgdown.js | 12 +-- inst/BS5/assets/pkgdown.scss | 182 ++++++++++++++++++++++++++++++++++- pkgdown/_pkgdown.yml | 3 +- 3 files changed, 186 insertions(+), 11 deletions(-) diff --git a/inst/BS5/assets/pkgdown.js b/inst/BS5/assets/pkgdown.js index 25952cc80..db9276b58 100644 --- a/inst/BS5/assets/pkgdown.js +++ b/inst/BS5/assets/pkgdown.js @@ -173,8 +173,8 @@ const getPreferredTheme = () => { } const setTheme = theme => { - if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) { - document.documentElement.setAttribute('data-bs-theme', 'dark') + if (theme === 'auto') { + document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) } else { document.documentElement.setAttribute('data-bs-theme', theme) } @@ -236,12 +236,6 @@ function bsSetupThemeToggle () { } function colorPickerMarkup () { - const svgs = { - "sun-fill": ``, - "moon-stars-fill": ``, - "circle-half": `` - } const icons = { "sun-fill": ``, @@ -263,7 +257,7 @@ function colorPickerMarkup () {
  • diff --git a/inst/BS5/assets/pkgdown.scss b/inst/BS5/assets/pkgdown.scss index eaa3b9612..7b78b45ef 100644 --- a/inst/BS5/assets/pkgdown.scss +++ b/inst/BS5/assets/pkgdown.scss @@ -3,7 +3,7 @@ .row > main { // Ensure contents never become unreadably wide max-width: 50rem; - + // And that we can break and hypenate very long words overflow-wrap: break-word; hyphens: auto; @@ -509,6 +509,186 @@ mark { } /* ---- Dark Mode ---- */ + +@include media-breakpoint-down(sm) { + aside { + background-color: var(--bs-tertiary-bg); + border-color: var(--bs-border-color); + } +} + +@media (min-width: 800px) { + .usage { + display: flex; + * { + flex: 1; + } + } +} + +p a { + text-decoration-skip-ink: none; + text-decoration-thickness: from-font; +} + +a:focus, a:hover { + text-decoration: underline; +} + +.navbar-light .navbar-nav .active>.nav-link { + background: #D0E5FC; +} + +table.dataTable.table-bordered { + border-collapse: collapse !important; +} + +main h2 { + margin-top: 1lh; +} + +.html-widget { + margin-bottom: 0; +} + +/* ---- Callouts ---- */ +.callout { + position: relative; + border: 1px solid gray; + padding: 1rem; + margin: 1rem 0; + border-radius: var(--bs-border-radius); +} + +.callout > :last-child { + margin-bottom: 0; +} + +.callout > h3 { + position: relative; + margin: -1rem; + margin-bottom: 10px; + padding: 1rem; + font-size: 1.5rem; + border-top-left-radius: inherit; + border-top-right-radius: inherit; +} + +.callout > h3 > .anchor { + display: none; +} + +.callout.callout-warning { + --callout--border-color: #ffd700; + --callout--header-bg: #fffae0; + --callout--header-color: #473D00; + + [data-bs-theme="dark"] & { + --callout--border-color: #473D00; + --callout--header-color: #fffae0; + --callout--header-bg: #473D00; + } + + border-color: var(--callout--border-color); + + > h3 { + color: var(--callout--header-color); + background-color: var(--callout--header-bg); + + &:before { + content: "!"; + font-weight: bold; + font-size: 1.25rem; + font-family: serif; + margin-right: 0.5rem; + border-radius: 50%; + background-color: #ffd70080; + width: 2rem; + height: 2rem; + display: inline-flex; + align-items: center; + justify-content: center; + } + } +} + + +.callout.callout-note { + --callout--header-color: #373a3c; + --callout--header-bg: #e9f2fc; + --callout--border-color: #bdccdc; + + [data-bs-theme="dark"] & { + --callout--header-color: #e9f2fc; + --callout--header-bg: #1b425d; + --callout--border-color: #1b425d; + } + + border-color: var(--callout--border-color); + + > h3 { + color: var(--callout--header-color); + background-color: var(--callout--header-bg); + + &:before { + content: "i"; + font-weight: bold; + font-size: 1.25rem; + font-style: italic; + font-family: serif; + margin-right: 0.5rem; + border-radius: 50%; + background-color: #bdccdc80; + width: 2rem; + height: 2rem; + display: inline-flex; + align-items: center; + justify-content: center; + } + } +} + + +iframe, .bslib-page-fill { + height: 500px; + border: var(--bs-border-width) solid var(--bs-border-color); +} + +iframe.resizable { + resize: vertical; + min-height: 200px; +} + +aside .roles, +footer { + color: rgba(var(--bs-emphasis-color-rgb), 0.6); +} + +/* pkgdown fixes for dark mode */ +// these could probably end up in pkgdown? + +.card-footer.bg-white { + --bs-bg-opacity: 0.1; +} + +.navbar a { + text-decoration: none !important; +} + +.navbar-nav .nav-item>.nav-link:hover, +#toc>.nav a.nav-link:hover, +#toc>.nav a.nav-link:focus { + color: var(--bs-body-color); + background-color: rgba(var(--bs-info-rgb), 0.45); +} + +#toc>.nav a.nav-link.active { + [data-bs-theme="dark"] { + color: var(--bs-body-bg); + } + background-color: rgba(var(--bs-info-rgb), 0.75); +} + [data-bs-theme="dark"] { .navbar.bg-info { background-color: #333f48 !important; diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index f87d46ca4..5c32d51e6 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -18,9 +18,10 @@ authors: template: bootstrap: 5 bslib: - primary: "#0054AD" border-radius: 0.5rem btn-border-radius: 0.25rem + info: "#f8f9fa" + includes: in_header: > From 02e13ffc5e690e321d74b9e22b2b6bf2a86e2660 Mon Sep 17 00:00:00 2001 From: Jay Hesselberth Date: Sun, 28 Apr 2024 10:29:40 -0600 Subject: [PATCH 03/31] include search in navbar right --- pkgdown/_pkgdown.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 5c32d51e6..8c628c790 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -31,7 +31,7 @@ navbar: bg: info type: light structure: - right: [github, dark-mode] + right: [search, github, dark-mode] components: dark-mode: href: "#dark-mode" From 907c8df5b855b9161a68d7b395cc457ea1659909 Mon Sep 17 00:00:00 2001 From: Jay Hesselberth Date: Sun, 28 Apr 2024 10:47:12 -0600 Subject: [PATCH 04/31] document and news bullet --- NEWS.md | 1 + vignettes/customise.Rmd | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/NEWS.md b/NEWS.md index a71218b68..dd9ca6f95 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,6 @@ # pkgdown (development version) +* The dark mode introduced in Bootstrap 5.3 can now be used in pkgdown sites. See the customization vignette for details. * `as.pkgdown()` will no longer prompt you to install a missing template package from CRAN, since these are almost always found in GitHub (#2076). * `init_site()` once again describes one copy per line, and now uses a better prefix when copying assets from pkgdown itself (#2445). * Very wide words are now automatically broken across lines and hyphenated (when possible) when they'd otherwise create a horizontal scrollbar on mobile (#1888). diff --git a/vignettes/customise.Rmd b/vignettes/customise.Rmd index 0286bc923..34de29517 100644 --- a/vignettes/customise.Rmd +++ b/vignettes/customise.Rmd @@ -213,6 +213,23 @@ Unfortunately, these are defined relative to the page background, so if you have Because the navbar is styled with HTML, you'll need to `build_home_index(); init_site()` to see the effect of changing this parameter. +### Dark Mode + +You can use the dark mode introduced in [Bootstrap v5.3](https://getbootstrap.com/docs/5.3/customize/color-modes/) in your pkgdown site by making a few changes to your configuration. pkgdown contains changes to `pkgdown.js` and `pkgdown.css` to enable dark mode. + +Modify your `_pkgdown.yml` configuration file with: + +``` yaml +navbar: + structure: + right: [dark-mode] + components: + dark-mode: + href: "#dark-mode" +``` + +See the [pkgdown](https://pkgdown.r-lib.org/) and [bslib](https://rstudio.github.io/bslib/) websites for examples of dark mode (toggle in the upper right). + ## Layout {#layout} You can customise the contents of the navbar, footer, using the `navbar` and `footer` fields. From 00576bf85a2b36e6269e500cec96cc97323db32e Mon Sep 17 00:00:00 2001 From: Jay Hesselberth Date: Sun, 28 Apr 2024 10:49:45 -0600 Subject: [PATCH 05/31] acknowledge @gadenbuie --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index dd9ca6f95..d33e35a18 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,6 @@ # pkgdown (development version) -* The dark mode introduced in Bootstrap 5.3 can now be used in pkgdown sites. See the customization vignette for details. +* The dark mode introduced in Bootstrap 5.3 can now be used in pkgdown sites based on work in bslib by @gadenbuie. See the customization vignette for details. * `as.pkgdown()` will no longer prompt you to install a missing template package from CRAN, since these are almost always found in GitHub (#2076). * `init_site()` once again describes one copy per line, and now uses a better prefix when copying assets from pkgdown itself (#2445). * Very wide words are now automatically broken across lines and hyphenated (when possible) when they'd otherwise create a horizontal scrollbar on mobile (#1888). From 1d320dcc0df68545c7a79814039de234c220e109 Mon Sep 17 00:00:00 2001 From: Jay Hesselberth Date: Sun, 28 Apr 2024 10:53:20 -0600 Subject: [PATCH 06/31] add bootstrap icons css --- vignettes/customise.Rmd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vignettes/customise.Rmd b/vignettes/customise.Rmd index 34de29517..b44a7cc79 100644 --- a/vignettes/customise.Rmd +++ b/vignettes/customise.Rmd @@ -220,6 +220,11 @@ You can use the dark mode introduced in [Bootstrap v5.3](https://getbootstrap.co Modify your `_pkgdown.yml` configuration file with: ``` yaml +template: + includes: + in_header: + + navbar: structure: right: [dark-mode] From 8a5bf60836380de9c90e905c399b5de6d36ac074 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 21 May 2024 15:47:49 -0500 Subject: [PATCH 07/31] Static lightswitcher menu made with navbar menu --- R/navbar-menu.R | 27 +++++++--- R/navbar.R | 19 +++++-- inst/BS5/assets/pkgdown.js | 87 +++++++++------------------------ pkgdown/_pkgdown.yml | 5 -- tests/testthat/_snaps/navbar.md | 76 ++++++++++++++++++++++++++-- 5 files changed, 130 insertions(+), 84 deletions(-) diff --git a/R/navbar-menu.R b/R/navbar-menu.R index 3c54e54ef..feaa9a394 100644 --- a/R/navbar-menu.R +++ b/R/navbar-menu.R @@ -2,11 +2,17 @@ # Helpers for use within pkgdown itself - these must stay the same as the # yaml structure defined in vignette("customise") -menu_submenu <- function(text, menu) { +menu_submenu <- function(text, menu, icon = NULL, label = NULL, id = NULL) { if (length(menu) == 0) { return() } else { - list(text = text, menu = menu) + purrr::compact(list( + text = text, + icon = icon, + "aria-label" = label, + id = id, + menu = menu + )) } } menu_link <- function(text, href, target = NULL) { @@ -15,9 +21,14 @@ menu_link <- function(text, href, target = NULL) { menu_links <- function(text, href) { purrr::map2(text, href, menu_link) } +menu_theme <- function(text, icon, theme) { + purrr::compact(list(text = text, href = "#", theme = theme, icon = icon)) +} + menu_heading <- function(text, ...) list(text = text, ...) menu_separator <- function() list(text = "---------") -menu_search <- function() list(search = list()) +menu_search <- function() list(special = "search") +menu_lightswitch <- function() list(special = "lightswitch") menu_icon <- function(icon, href, label) { list(icon = icon, href = href, "aria-label" = label) } @@ -40,8 +51,8 @@ menu_type <- function(x, menu_depth = 0L) { "heading" } else if ((!is.null(x$text) || !is.null(x$icon)) && !is.null(x$href)) { "link" - } else if (!is.null(x$search)) { - "search" + } else if (!is.null(x$special)) { + x$special } else if (!is_named(x)) { "list" } else { @@ -64,7 +75,8 @@ navbar_html <- function(x, path_depth = 0L, menu_depth = 0L, side = c("left", "r heading = navbar_html_heading(x), link = navbar_html_link(x, menu_depth = menu_depth), separator = navbar_html_separator(), - search = navbar_html_search(x, path_depth = path_depth) + search = navbar_html_search(x, path_depth = path_depth), + lightswitch = navbar_html_lightswitch() ) class <- c( @@ -86,7 +98,7 @@ navbar_html_list <- function(x, path_depth = 0L, menu_depth = 0L, side = "left") } navbar_html_menu <- function(x, path_depth = 0L, menu_depth = 0L, side = "left") { - id <- paste0("dropdown-", make_slug(x$text)) + id <- paste0("dropdown-", x$id %||% make_slug(x$text)) button <- html_tag("button", type = "button", @@ -122,6 +134,7 @@ navbar_html_link <- function(x, menu_depth = 0) { href = x$href, target = x$target, "aria-label" = x$`aria-label`, + "data-bs-theme-value" = x$theme, navbar_html_text(x) ) } diff --git a/R/navbar.R b/R/navbar.R index d30ee9ae4..52f35f5cf 100644 --- a/R/navbar.R +++ b/R/navbar.R @@ -31,7 +31,7 @@ navbar_style <- function(navbar = list(), theme = "_default", bs_version = 3) { navbar_structure <- function() { print_yaml(list( left = c("intro", "reference", "articles", "tutorials", "news"), - right = c("search", "github") + right = c("search", "github", "lightswitch") )) } @@ -119,10 +119,23 @@ navbar_components <- function(pkg = ".") { menu <- list() menu$reference <- menu_link(tr_("Reference"), "reference/index.html") - - # in BS3, search is hardcoded in the template + if (pkg$bs_version == 5) { + # in BS3, search is hardcoded in the template menu$search <- menu_search() + + # TODO: only add if both light and dark theme specified? + menu$lightswitch <- menu_submenu( + text = NULL, + icon = "fa-sun", + label = tr_("Lightswitch"), + id = "lightswitch", + list( + menu_theme(tr_("Light"), icon = "fa-sun", theme = "light"), + menu_theme(tr_("Dark"), icon = "fa-moon", theme = "dark"), + menu_theme(tr_("Auto"), icon = "fa-adjust", theme = "auto") + ) + ) } if (!is.null(pkg$tutorials)) { diff --git a/inst/BS5/assets/pkgdown.js b/inst/BS5/assets/pkgdown.js index db9276b58..bdb4c706a 100644 --- a/inst/BS5/assets/pkgdown.js +++ b/inst/BS5/assets/pkgdown.js @@ -180,33 +180,32 @@ const setTheme = theme => { } } -setTheme(getPreferredTheme()) - function bsSetupThemeToggle () { 'use strict' const showActiveTheme = (theme, focus = false) => { - const themeSwitcher = document.querySelector('#bd-theme') + var activeLabel, activeIcon; + + document.querySelectorAll('[data-bs-theme-value]').forEach(element => { + const buttonTheme = element.getAttribute('data-bs-theme-value') + const isActive = buttonTheme == theme + + element.classList.toggle('active', isActive) + element.setAttribute('aria-pressed', isActive) + + if (isActive) { + activeLabel = element.textContent; + activeIcon = element.querySelector('span').classList.value; + } + }) + const themeSwitcher = document.querySelector('#dropdown-lightswitch') if (!themeSwitcher) { return } - const themeSwitcherText = document.querySelector('#bd-theme-text') - const activeThemeIcon = document.querySelector('.theme-icon-active') - const btnToActive = document.querySelector(`[data-bs-theme-value="${theme}"]`) - const svgOfActiveBtn = btnToActive.querySelector('.theme-icon').innerHTML - - document.querySelectorAll('[data-bs-theme-value]').forEach(element => { - element.classList.remove('active') - element.setAttribute('aria-pressed', 'false') - }) - - btnToActive.classList.add('active') - btnToActive.setAttribute('aria-pressed', 'true') - activeThemeIcon.innerHTML = svgOfActiveBtn - const themeSwitcherLabel = `${themeSwitcherText.textContent} (${btnToActive.dataset.bsThemeValue})` - themeSwitcher.setAttribute('aria-label', themeSwitcherLabel) + themeSwitcher.setAttribute('aria-label', activeLabel) + themeSwitcher.querySelector('span').classList.value = activeIcon; if (focus) { themeSwitcher.focus() @@ -223,60 +222,18 @@ function bsSetupThemeToggle () { window.addEventListener('DOMContentLoaded', () => { showActiveTheme(getPreferredTheme()) - document.querySelectorAll('[data-bs-theme-value]') + document + .querySelectorAll('[data-bs-theme-value]') .forEach(toggle => { toggle.addEventListener('click', () => { const theme = toggle.getAttribute('data-bs-theme-value') - setStoredTheme(theme) setTheme(theme) + setStoredTheme(theme) showActiveTheme(theme, true) }) }) }) } -function colorPickerMarkup () { - - const icons = { - "sun-fill": ``, - "moon-stars-fill": ``, - "circle-half": `` - } - - return ` - ` -} - -document.addEventListener('DOMContentLoaded', () => { - const switcher = document.querySelector('.navbar [href$="#dark-mode"]') - if (!switcher) return - - switcher.parentElement.classList.add('dropdown') - switcher.parentElement.innerHTML = colorPickerMarkup() - bsSetupThemeToggle() -}) +setTheme(getPreferredTheme()); +bsSetupThemeToggle(); diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml index 47d0226a4..01eea6dba 100644 --- a/pkgdown/_pkgdown.yml +++ b/pkgdown/_pkgdown.yml @@ -31,11 +31,6 @@ template: navbar: bg: info type: light - structure: - right: [search, github, dark-mode] - components: - dark-mode: - href: "#dark-mode" development: mode: auto diff --git a/tests/testthat/_snaps/navbar.md b/tests/testthat/_snaps/navbar.md index 45feb8853..56fc7a8db 100644 --- a/tests/testthat/_snaps/navbar.md +++ b/tests/testthat/_snaps/navbar.md @@ -4,7 +4,24 @@ text: Reference href: reference/index.html search: - search: [] + special: search + lightswitch: + icon: fa-sun + aria-label: Lightswitch + id: lightswitch + menu: + - text: Light + href: '#' + theme: light + icon: fa-sun + - text: Dark + href: '#' + theme: dark + icon: fa-moon + - text: Auto + href: '#' + theme: auto + icon: fa-adjust --- @@ -13,7 +30,24 @@ text: Reference href: reference/index.html search: - search: [] + special: search + lightswitch: + icon: fa-sun + aria-label: Lightswitch + id: lightswitch + menu: + - text: Light + href: '#' + theme: light + icon: fa-sun + - text: Dark + href: '#' + theme: dark + icon: fa-moon + - text: Auto + href: '#' + theme: auto + icon: fa-adjust github: icon: fab fa-github fa-lg href: https://github.com/r-lib/pkgdown @@ -26,7 +60,24 @@ text: Reference href: reference/index.html search: - search: [] + special: search + lightswitch: + icon: fa-sun + aria-label: Lightswitch + id: lightswitch + menu: + - text: Light + href: '#' + theme: light + icon: fa-sun + - text: Dark + href: '#' + theme: dark + icon: fa-moon + - text: Auto + href: '#' + theme: auto + icon: fa-adjust github: icon: fab fa-gitlab fa-lg href: https://gitlab.com/r-lib/pkgdown @@ -39,7 +90,24 @@ text: Reference href: reference/index.html search: - search: [] + special: search + lightswitch: + icon: fa-sun + aria-label: Lightswitch + id: lightswitch + menu: + - text: Light + href: '#' + theme: light + icon: fa-sun + - text: Dark + href: '#' + theme: dark + icon: fa-moon + - text: Auto + href: '#' + theme: auto + icon: fa-adjust intro: text: Get started href: test.html From cd17170bf74009aceb383d3c7d2f032b6d8b9991 Mon Sep 17 00:00:00 2001 From: Hadley Wickham Date: Tue, 21 May 2024 16:29:35 -0500 Subject: [PATCH 08/31] Simplify css --- R/navbar.R | 2 +- inst/BS5/assets/pkgdown.scss | 105 +++++++++++++++------------------ inst/BS5/templates/navbar.html | 2 +- pkgdown/_pkgdown.yml | 4 -- 4 files changed, 48 insertions(+), 65 deletions(-) diff --git a/R/navbar.R b/R/navbar.R index 52f35f5cf..fb2b9efba 100644 --- a/R/navbar.R +++ b/R/navbar.R @@ -21,7 +21,7 @@ navbar_style <- function(navbar = list(), theme = "_default", bs_version = 3) { list(type = navbar$type %||% "default") } else { # bg is usually light, dark, or primary, but can use any .bg-* - bg <- navbar$bg %||% purrr::pluck(bootswatch_bg, theme, .default = "light") + bg <- navbar$bg %||% purrr::pluck(bootswatch_bg, theme, .default = "body-tertiary") type <- navbar$type %||% if (bg == "light") "light" else "dark" list(bg = bg, type = type) diff --git a/inst/BS5/assets/pkgdown.scss b/inst/BS5/assets/pkgdown.scss index 76565f938..21e078ab0 100644 --- a/inst/BS5/assets/pkgdown.scss +++ b/inst/BS5/assets/pkgdown.scss @@ -33,30 +33,30 @@ -webkit-align-items: baseline; } -.navbar-light .navbar-nav .active > .nav-link { - background: $gray-200; - color: $body-color; -} -.navbar-dark .navbar-nav .active > .nav-link { - background: $gray-800; - color: $body-bg; -} - -.navbar-dark .navbar-nav .nav-item > .nav-link:hover, -.navbar-light .navbar-nav .nav-item > .nav-link:hover { - background: change-color($primary, $alpha: 0.1); -} - -.navbar-dark { - input[type="search"] { - border-color: $gray-600; - background-color: $gray-900; - color: $gray-200; - } -} +// .navbar-light .navbar-nav .active > .nav-link { +// background: $gray-200; +// color: $body-color; +// } +// .navbar-dark .navbar-nav .active > .nav-link { +// background: $gray-800; +// color: $body-bg; +// } + +// .navbar-dark .navbar-nav .nav-item > .nav-link:hover, +// .navbar-light .navbar-nav .nav-item > .nav-link:hover { +// background: change-color($primary, $alpha: 0.1); +// } + +// .navbar-dark { +// input[type="search"] { +// border-color: $gray-600; +// background-color: $gray-900; +// color: $gray-200; +// } +// } input[type="search"] { - border-color: $border-color; + // border-color: $border-color; width: 12rem; } @@ -685,7 +685,6 @@ main h2 { } } - iframe, .bslib-page-fill { height: 500px; border: var(--bs-border-width) solid var(--bs-border-color); @@ -708,51 +707,40 @@ footer { --bs-bg-opacity: 0.1; } -.navbar a { - text-decoration: none !important; -} +// .navbar a { +// text-decoration: none !important; +// } -.navbar-nav .nav-item>.nav-link:hover, -#toc>.nav a.nav-link:hover, -#toc>.nav a.nav-link:focus { - color: var(--bs-body-color); - background-color: rgba(var(--bs-info-rgb), 0.45); -} +// .navbar-nav .nav-item>.nav-link:hover, +// #toc>.nav a.nav-link:hover, +// #toc>.nav a.nav-link:focus { +// color: var(--bs-body-color); +// background-color: rgba(var(--bs-info-rgb), 0.45); +// } -#toc>.nav a.nav-link.active { - [data-bs-theme="dark"] { - color: var(--bs-body-bg); - } - background-color: rgba(var(--bs-info-rgb), 0.75); -} +// #toc>.nav a.nav-link.active { +// [data-bs-theme="dark"] { +// color: var(--bs-body-bg); +// } +// background-color: rgba(var(--bs-info-rgb), 0.75); +// } [data-bs-theme="dark"] { - .navbar.bg-info { - background-color: #333f48 !important; - } - - ::selection { - background: #344c5a; - } - - input[type="search"] { - border-color: var(--bs-border-color); - } + // .navbar.bg-light { + // background-color: $body-bg; + // } pre { - background-color: #272b30; + background-color: mix($body-color, $body-bg, 90%); + border-color: mix($body-color, $body-bg, 95%); } - // low-tech image softening in dark mode - img { + // low-tech plot softening in dark mode + .sourceCode img { opacity: 0.66; transition: opacity 250ms ease-in-out; - } - - img:hover, - img:focus, - img:active { - opacity: 1; + + &:hover, &:focus, &:active {opacity: 1;} } // github-dark.css // @@ -787,5 +775,4 @@ footer { pre code span.va /* Variable */ {color:#ffab70} pre code span.vs /* VerbatimString */ {color:#9ecbff} pre code span.wa /* Warning */ {color:#ff5555} - } diff --git a/inst/BS5/templates/navbar.html b/inst/BS5/templates/navbar.html index c13e8b08a..ba4c096bc 100644 --- a/inst/BS5/templates/navbar.html +++ b/inst/BS5/templates/navbar.html @@ -1,5 +1,5 @@ {{#navbar}} -