Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add dark-mode toggle switch #787

Merged
merged 45 commits into from
Sep 8, 2023
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
6653f5e
original dark mode switch
gadenbuie Sep 6, 2023
d9790d6
feat(dark-mode-switch): Add dark mode switch from shinycomponent
gadenbuie Sep 6, 2023
33f2a08
chore: Tweak title message
gadenbuie Sep 6, 2023
588d927
chore: completely unset vertical correction
gadenbuie Sep 6, 2023
723535c
feat(dark-mode-switch): Reflect color mode in attribute and respond t…
gadenbuie Sep 6, 2023
4aa3aea
feat(toggle_dark_mode_switch): Add `toggle_dark_mode_switch()`
gadenbuie Sep 6, 2023
f9111b3
chore: Add note about `--vertical-correction`
gadenbuie Sep 6, 2023
ff5d96d
chore: Use `updated()` method to handle setting preference and shiny …
gadenbuie Sep 6, 2023
e74282c
chore: add comment about use of BslibElement
gadenbuie Sep 6, 2023
34552c5
`yarn build` (GitHub Actions)
gadenbuie Sep 6, 2023
7eb8290
chore: Move comment back into place
gadenbuie Sep 6, 2023
5fc01d7
fix: Only consult system preference if no theme value is set in compo…
gadenbuie Sep 6, 2023
922912c
refactor: Consolidate `reflectPreference()` method
gadenbuie Sep 6, 2023
433c0c4
fix: `themeValue` might be temporarily undefined but is set in connec…
gadenbuie Sep 6, 2023
a2662e7
fix(toggle_dark_mode_switch): Warn instead of throwing if unknown `mode`
gadenbuie Sep 6, 2023
e126c82
doc(input_dark_mode): Document and export
gadenbuie Sep 6, 2023
203cd2e
chore: Directly set `title` and `aria-label` in `render()` method
gadenbuie Sep 7, 2023
d2a56f2
feat(input_dark_mode): Make `id` optional
gadenbuie Sep 7, 2023
824f2e8
feat(darkModeSwitch): Observe document element for mode changes
gadenbuie Sep 7, 2023
5a32c5b
chore(darkModeSwitch): Extend LitElement directly
gadenbuie Sep 7, 2023
4fe55f4
chore: Make tag name consistent with R function
gadenbuie Sep 7, 2023
2214281
core(darkModeSwitch): Simplify property names
gadenbuie Sep 7, 2023
8ee16b9
chore: yarn build
gadenbuie Sep 7, 2023
b935225
Resave data (GitHub Action)
gadenbuie Sep 7, 2023
4a27e8d
docs(pkgdown): Add `input_dark_mode` to reference index
gadenbuie Sep 7, 2023
9e6845e
chore: Drop "toggle" as explicit value of `ToggleMessage`
gadenbuie Sep 7, 2023
18a1cbf
feat: Emit window resize event on color mode change
gadenbuie Sep 7, 2023
8dda683
chore(darkModeSwitch): Adjust aria label
gadenbuie Sep 7, 2023
c181ea5
feat(toggle_dark_mode): `id` is not required, use custom message inst…
gadenbuie Sep 7, 2023
492c032
Resave data (GitHub Action)
gadenbuie Sep 7, 2023
ff5fe08
chore(toggle_dark_mode): Warn if dots aren't empty
gadenbuie Sep 7, 2023
97d28a5
docs(input_dark_mode): Reword `id` param
gadenbuie Sep 7, 2023
1b6d36d
docs(toggle_dark_mode): Move `session` param docs into function
gadenbuie Sep 7, 2023
715b4c3
chore(darkModeSwitch): Make document observer method private
gadenbuie Sep 7, 2023
b4f0e9c
chore(darkModeSwitch): Store shiny custom message handlers as static …
gadenbuie Sep 7, 2023
455b612
Merge 'origin/main' into branch feat/dark-mode-switch
gadenbuie Sep 7, 2023
8db469f
`yarn build` (GitHub Actions)
gadenbuie Sep 7, 2023
de2824d
Resave data (GitHub Action)
gadenbuie Sep 7, 2023
c433453
docs: Add NEWS item
gadenbuie Sep 7, 2023
1c1af63
chore(input_dark_mode): Remove unneeded `bslibShiny` dep
gadenbuie Sep 8, 2023
dc08ca4
chore(BslibInputDarkMode): Align class name and file name with tag name
gadenbuie Sep 8, 2023
cf44138
chore: Simplify private attribute setting
gadenbuie Sep 8, 2023
8682eb8
fix: Add missing `--ease-out-[1,3,4]` defaults
gadenbuie Sep 8, 2023
7898c68
chore: Disconnect mutation observer on disconnect
gadenbuie Sep 8, 2023
fea680f
chore: yarn build
gadenbuie Sep 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Collate:
'files.R'
'fill.R'
'imports.R'
'input-dark-mode.R'
'input-switch.R'
'layout.R'
'nav-items.R'
Expand Down
2 changes: 2 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ export(font_collection)
export(font_face)
export(font_google)
export(font_link)
export(input_dark_mode)
export(input_switch)
export(is.card_item)
export(is_bs_theme)
Expand Down Expand Up @@ -128,6 +129,7 @@ export(sidebar)
export(sidebar_toggle)
export(theme_bootswatch)
export(theme_version)
export(toggle_dark_mode)
export(toggle_popover)
export(toggle_sidebar)
export(toggle_switch)
Expand Down
84 changes: 84 additions & 0 deletions R/input-dark-mode.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#' Dark mode input control
#'
#' Creates a button that toggles between dark and light modes, specifically for
#' toggling between light and dark [Bootstrap color
#' modes](https://getbootstrap.com/docs/5.3/customize/color-modes/) -- a new
#' feature added in [Bootstrap
#' 5.3](https://getbootstrap.com/docs/5.3/migration/#color-modes).
#'
#' @param ... Additional attributes to be passed to the input control UI, such
#' as `class`, `style`, etc.
#'
#' In `toggle_dark_mode()`, the `...` are included for future extensibility
#' and are currently ignored.
#' @param id An optional input id, required if you'd like to be able to
#' reactively read programmatically toggle the current color mode.
gadenbuie marked this conversation as resolved.
Show resolved Hide resolved
#' @param mode The initial mode of the dark mode switch. By default or when set
#' to `NULL`, the user's system settings for preferred color scheme will be
#' used. Otherwise, set to `"light"` or `"dark"` to force a particular initial
#' mode.
#' @inheritParams tooltip
gadenbuie marked this conversation as resolved.
Show resolved Hide resolved
#'
#' @return Returns a UI element for a dark mode switch input control. The server
#' value received for the input corresponding to `id` will be a string value
#' with the current color mode (`"light"` or `"dark"`).
#'
#' @describeIn input_dark_mode Create a dark mode switch input control
#' @family input controls
#' @export
input_dark_mode <- function(..., id = NULL, mode = NULL) {
if (!is.null(mode)) {
mode <- rlang::arg_match(mode, c("light", "dark"))
}

if (any(!nzchar(rlang::names2(rlang::list2(...))))) {
abort("All arguments in `...` must be named.")
}

res <- web_component(
"bslib-input-dark-mode",
id = id,
attribute = "data-bs-theme",
mode = mode,
style = css(
"--text-1" = "var(--bs-emphasis-color)",
"--text-2" = "var(--bs-tertiary-color)",
# The vertical correction used in the dark mode component isn't quite
# right on Bootstrap pages. This next line overrides it and removes the
# vertical correction. But users can still set the CSS property manually
# in their a `style` argument passed in via `...` if they want.
"--vertical-correction" = " "
),
...,
component_dependency_js("bslibShiny")
gadenbuie marked this conversation as resolved.
Show resolved Hide resolved
)

res <- tag_require(res, version = 5, caller = "input_dark_mode()")
as_fragment(res)
}

#' @describeIn input_dark_mode Programmatically toggle or set the current light
#' or dark color mode.
#' @export
toggle_dark_mode <- function(mode = NULL, ..., session = get_current_session()) {
gadenbuie marked this conversation as resolved.
Show resolved Hide resolved
if (!is.null(mode)) {
mode <- tryCatch(
rlang::arg_match(mode, c("light", "dark")),
error = function(err) {
rlang::warn(rlang::cnd_message(err))
mode
}
)
}

data <- dropNulls(list(method = "toggle", value = mode))

# We're using sendCustomMessage() here because dark mode is set globally and
# `id` is not required for `toggle_dark_mode()`. `$sendInputMessage()` would
# require us to know the `id` of at least one input control.
callback <- function() {
session$sendCustomMessage("bslib.toggle-dark-mode", data)
}

session$onFlush(callback, once = TRUE)
}
11 changes: 0 additions & 11 deletions R/input-switch.R
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,6 @@ toggle_switch <- function(id, value = NULL, session = get_current_session()) {
session$onFlush(callback, once = TRUE)
}

# Keep this internal for now until we agree on the UX
input_dark_mode_switch <- function(id, label, ..., width = "auto") {
res <- input_switch(id, label, ..., width = width)
# TODO: .navbar should probably do this for .shiny-input-container
res <- tagAppendAttributes(res, style = "margin-bottom: 0;")
tagAppendAttributes(
res, .cssSelector = "input",
onclick = "document.documentElement.setAttribute('data-bs-theme', this.checked ? 'dark' : 'light'); $(window).resize();"
)
}

input_checkbox <- function(id, label, class = "bslib-input-checkbox", value = FALSE, width = NULL, inline = FALSE) {
div(
class = "form-group shiny-input-container",
Expand Down
Binary file modified R/sysdata.rda
Binary file not shown.
1 change: 1 addition & 0 deletions _pkgdown.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ reference:
UI controls for capturing user input
contents:
- input_switch
- input_dark_mode
- title: Accordions
description: |
Create collapsible sections of content
Expand Down
46 changes: 32 additions & 14 deletions inst/components/dist/bslibShiny/bslibShiny.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions inst/components/dist/bslibShiny/bslibShiny.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion inst/components/dist/bslibShiny/bslibShiny.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading