diff --git a/R/render.R b/R/render.R index d3c07ca69..6570652ef 100644 --- a/R/render.R +++ b/R/render.R @@ -128,6 +128,7 @@ data_template <- function(pkg = ".", depth = 0L) { out$navbar <- data_navbar(pkg, depth = depth) out$footer <- data_footer(pkg) + out$lightswitch <- uses_lightswitch(pkg) print_yaml(out) } diff --git a/inst/BS5/assets/lightswitch.js b/inst/BS5/assets/lightswitch.js new file mode 100644 index 000000000..9467125ae --- /dev/null +++ b/inst/BS5/assets/lightswitch.js @@ -0,0 +1,85 @@ + +/*! + * 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') { + document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) + } else { + document.documentElement.setAttribute('data-bs-theme', theme) + } +} + +function bsSetupThemeToggle () { + 'use strict' + + const showActiveTheme = (theme, focus = false) => { + 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 + } + + themeSwitcher.setAttribute('aria-label', activeLabel) + themeSwitcher.querySelector('span').classList.value = activeIcon; + + 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') + setTheme(theme) + setStoredTheme(theme) + showActiveTheme(theme, true) + }) + }) + }) +} + +setTheme(getPreferredTheme()); +bsSetupThemeToggle(); diff --git a/inst/BS5/assets/pkgdown.js b/inst/BS5/assets/pkgdown.js index bdb4c706a..9757bf9ef 100644 --- a/inst/BS5/assets/pkgdown.js +++ b/inst/BS5/assets/pkgdown.js @@ -152,88 +152,3 @@ 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') { - document.documentElement.setAttribute('data-bs-theme', (window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light')) - } else { - document.documentElement.setAttribute('data-bs-theme', theme) - } -} - -function bsSetupThemeToggle () { - 'use strict' - - const showActiveTheme = (theme, focus = false) => { - 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 - } - - themeSwitcher.setAttribute('aria-label', activeLabel) - themeSwitcher.querySelector('span').classList.value = activeIcon; - - 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') - setTheme(theme) - setStoredTheme(theme) - showActiveTheme(theme, true) - }) - }) - }) -} - -setTheme(getPreferredTheme()); -bsSetupThemeToggle(); diff --git a/inst/BS5/templates/head.html b/inst/BS5/templates/head.html index 09c3ef6a5..94b79040b 100644 --- a/inst/BS5/templates/head.html +++ b/inst/BS5/templates/head.html @@ -18,6 +18,10 @@ {{/has_favicons}} +{{#lightswitch}} + +{{/lightswitch}} + {{{headdeps}}} diff --git a/tests/testthat/_snaps/init.md b/tests/testthat/_snaps/init.md index 27b862751..c71a7dff9 100644 --- a/tests/testthat/_snaps/init.md +++ b/tests/testthat/_snaps/init.md @@ -19,6 +19,7 @@ init_site(pkg) Message -- Initialising site ----------------------------------------------------------- + Copying /BS5/assets/lightswitch.js to lightswitch.js Copying /BS5/assets/link.svg to link.svg Copying /BS5/assets/pkgdown.js to pkgdown.js Copying pkgdown/extra.css to extra.css diff --git a/tests/testthat/_snaps/render.md b/tests/testthat/_snaps/render.md index 514d8979d..420a49623 100644 --- a/tests/testthat/_snaps/render.md +++ b/tests/testthat/_snaps/render.md @@ -61,6 +61,7 @@ footer: left:

Developed by Hadley Wickham, RStudio.

right:

Site built with pkgdown {version}.

+ lightswitch: no # check_opengraph validates inputs