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: Improve navbar compatiblity for Bootstrap 5 and light/dark modes #1145

Merged
merged 16 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
9 changes: 7 additions & 2 deletions R/bs-theme-preset-bootswatch.R
Original file line number Diff line number Diff line change
Expand Up @@ -96,9 +96,14 @@ bootswatch_bundle <- function(bootswatch, version) {
# Use local fonts (this path is relative to the bootstrap HTML dependency dir)
'$web-font-path: "font.css" !default;',
bootswatch_sass_file(bootswatch, "variables", version),
# Unless we change navbarPage()'s markup, BS4+ will likely want BS3 compatibility
# BS4 navbars are matched with BS3 for compatibility
switch_version(
version, three = "", default = bs3compat_navbar_defaults(bootswatch)
version,
three = "",
four = bs3compat_navbar_defaults(bootswatch),
# BS5 uses more neutral defaults (navbar that flips in light/dark mode)
# or requires a bit more user input
default = list()
)
),
rules = list(
Expand Down
62 changes: 39 additions & 23 deletions inst/bs3compat/_navbar_compat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -72,42 +72,58 @@ ul.nav.navbar-nav {
}
}

:root {
--bslib-navbar-light-bg: var(--bslib-navbar-default-bg, var(--#{$prefix}light));
--bslib-navbar-dark-bg: var(--bslib-navbar-inverse-bg, var(--#{$prefix}black));
}

@mixin navbar-background-dark($important: false) {
background-color: var(--bslib-navbar-dark-bg) if($important, !important, null);
}

@mixin navbar-background-light($important: false) {
background-color: var(--bslib-navbar-light-bg) if($important, !important, null);
}

.navbar {

// Defaults to null (and in that case, we don't want to define the CSS var)
@if $navbar-light-bg {
--bslib-navbar-default-bg: #{$navbar-light-bg};
--bslib-navbar-light-bg: #{$navbar-light-bg};
}
@if $navbar-dark-bg {
--bslib-navbar-inverse-bg: #{$navbar-dark-bg};
}

// BS3 .navbar-default -> BS4 .navbar-light
&.navbar-default {
// Sets a variety of fg colors which are configurable via $navbar-light-* options
@extend .navbar-light;
background-color: var(--bslib-navbar-default-bg, var(--#{$prefix}light)) !important;
--bslib-navbar-dark-bg: #{$navbar-dark-bg};
}

// BS3 .navbar-inverse -> BS4 .navbar-dark
&.navbar-inverse {
// Sets a variety of fg colors which are configurable via $navbar-dark-* options
@extend .navbar-dark;
background-color: var(--bslib-navbar-inverse-bg, var(--#{$prefix}dark)) !important;
// For BS5+ lean on emphasis-color
--bs-emphasis-color: white;
--bs-emphasis-color-rgb: 255, 255, 255;
@if $bootstrap-version < 5 {
// BS3 .navbar-default -> BS4 .navbar-light
&.navbar-default {
// Sets a variety of fg colors which are configurable via $navbar-light-* options
@extend .navbar-light;
@include navbar-background-light($important: true);
}

// BS3 .navbar-inverse -> BS4 .navbar-dark
&.navbar-inverse {
// Sets a variety of fg colors which are configurable via $navbar-dark-* options
@extend .navbar-dark;
@include navbar-background-dark($important: true);
}
}
}

$enable-dark-mode: false !default;
@if $enable-dark-mode {
@include color-mode(dark) {
.navbar.navbar-default {
background-color: var(--bslib-navbar-default-bg, var(--#{$prefix}dark)) !important;
}
@if $bootstrap-version >= 5 {
.navbar {
background-color: $navbar-bg;
}

[data-bs-theme="dark"] :where(.navbar) { @include navbar-background-dark(); }
[data-bs-theme="light"] :where(.navbar), :where(.navbar) { @include navbar-background-light(); }

// These are defined *after* the above rules because we want the local version
// to win without having to resort to specificity tricks.
:where(.navbar)[data-bs-theme="dark"] { @include navbar-background-dark(); }
:where(.navbar)[data-bs-theme="light"] { @include navbar-background-light(); }
}

// Implement bs3 navbar toggler; used in Rmd websites, i.e.
Expand Down
15 changes: 8 additions & 7 deletions inst/builtin/bs5/shiny/_rules.scss
Original file line number Diff line number Diff line change
Expand Up @@ -173,14 +173,15 @@ $bslib-checkbox-radio-margin-right: 0.35em !default;
background-color: var(--bslib-dashboard-main-bg);
}

.navbar {
// Add border-bottom for general navbars (primarily in non-bslib contexts)
border-bottom: $card-border-width solid $card-border-color;
}

.bslib-page-navbar, .bslib-page-dashboard {
> .navbar {
@if not $navbar-light-bg and not $navbar-bg {
--bslib-navbar-default-bg: var(--#{$prefix}body-bg);
}
@if not $navbar-dark-bg and not $navbar-bg {
--bslib-navbar-inverse-bg: var(--#{$prefix}body-color);
}
// Inside bslib we only add the border on the top-level navbar
.navbar {
border-bottom: none;
}

> .navbar + div {
Expand Down
15 changes: 15 additions & 0 deletions inst/builtin/bs5/shiny/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,21 @@ $bslib-sidebar-fg: null !default;
$bslib-sidebar-fg: color-contrast($bslib-sidebar-bg);
}

// From inst/lib/bs5/scss/_variables.scss
// Repeated here so that we can set navbar light/dark to `--bs-body-bg`
$navbar-bg: null !default; // Background color for any navbarPage()
$navbar-light-bg: $navbar-bg !default; // Background color for navbarPage(inverse = FALSE)
$navbar-dark-bg: $navbar-bg !default; // Background color for navbarPage(inverse = TRUE)

@if $bslib-dashboard-design and $navbar-bg == null {
@if $navbar-light-bg == null {
$navbar-light-bg: var(--#{$prefix}body-bg);
}
@if $navbar-dark-bg == null {
$navbar-dark-bg: var(--#{$prefix}body-bg);
}
}

$border-color-translucent: if($bslib-dashboard-design, rgba(40, 70, 94, 0.1), null) !default;
$border-color-translucent-dark: if($bslib-dashboard-design, rgba(255, 255, 255, 0.1), null) !default;

Expand Down
30 changes: 28 additions & 2 deletions inst/lib/bs5/scss/_navbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
// Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations.

.navbar {
.navbar,
:where([data-bs-theme="light"]) .navbar { // bslib-patched: explicitly set navbar props in light mode regions
// scss-docs-start navbar-css-vars
--#{$prefix}navbar-padding-x: #{if($navbar-padding-x == null, 0, $navbar-padding-x)};
--#{$prefix}navbar-padding-y: #{$navbar-padding-y};
Expand All @@ -26,7 +27,9 @@
--#{$prefix}navbar-toggler-focus-width: #{$navbar-toggler-focus-width};
--#{$prefix}navbar-toggler-transition: #{$navbar-toggler-transition};
// scss-docs-end navbar-css-vars
}

.navbar {
position: relative;
display: flex;
display: -webkit-flex;
Expand Down Expand Up @@ -296,6 +299,7 @@
}

.navbar-dark,
:where([data-bs-theme="dark"]) .navbar, // bslib-patched: dark mode inside dark regions
.navbar[data-bs-theme="dark"] {
// scss-docs-start navbar-dark-css-vars
--#{$prefix}navbar-color: #{$navbar-dark-color};
Expand All @@ -309,10 +313,32 @@
// scss-docs-end navbar-dark-css-vars
}

:where(.navbar[data-bs-theme="dark"] .navbar-toggler-icon) {
// bslib-patched: toggler icon should follow closest navbar color mode over global mode
--#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
}

@if $enable-dark-mode {
@include color-mode(dark) {
.navbar-toggler-icon {
// bslib-patched: toggler follows global theme unless in a light region
:where(.navbar:not([data-bs-theme="light"]) .navbar-toggler-icon) {
--#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
}
}
}

.navbar[data-bs-theme="light"] {
// bslib-patched: Make sure local light navbar overrides page global
--#{$prefix}navbar-color: #{$navbar-light-color};
--#{$prefix}navbar-hover-color: #{$navbar-light-hover-color};
--#{$prefix}navbar-disabled-color: #{$navbar-light-disabled-color};
--#{$prefix}navbar-active-color: #{$navbar-light-active-color};
--#{$prefix}navbar-brand-color: #{$navbar-light-brand-color};
--#{$prefix}navbar-brand-hover-color: #{$navbar-light-brand-hover-color};
--#{$prefix}navbar-toggler-border-color: #{$navbar-light-toggler-border-color};

.navbar-toggler-icon {
// bslib-patched: Make sure toggler icon follows local light mode, too
--#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-light-toggler-icon-bg)};
}
}
66 changes: 66 additions & 0 deletions tools/patches/034-bs5-navbar-bg.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
diff --git a/inst/lib/bs5/scss/_navbar.scss b/inst/lib/bs5/scss/_navbar.scss
index 988bbe09..ec497278 100644
--- a/inst/lib/bs5/scss/_navbar.scss
+++ b/inst/lib/bs5/scss/_navbar.scss
@@ -3,7 +3,8 @@
// Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations.

-.navbar {
+.navbar,
+:where([data-bs-theme="light"]) .navbar { // bslib-patched: explicitly set navbar props in light mode regions
// scss-docs-start navbar-css-vars
--#{$prefix}navbar-padding-x: #{if($navbar-padding-x == null, 0, $navbar-padding-x)};
--#{$prefix}navbar-padding-y: #{$navbar-padding-y};
@@ -26,7 +27,9 @@
--#{$prefix}navbar-toggler-focus-width: #{$navbar-toggler-focus-width};
--#{$prefix}navbar-toggler-transition: #{$navbar-toggler-transition};
// scss-docs-end navbar-css-vars
+}

+.navbar {
position: relative;
display: flex;
display: -webkit-flex;
@@ -296,6 +299,7 @@
}

.navbar-dark,
+:where([data-bs-theme="dark"]) .navbar, // bslib-patched: dark mode inside dark regions
.navbar[data-bs-theme="dark"] {
// scss-docs-start navbar-dark-css-vars
--#{$prefix}navbar-color: #{$navbar-dark-color};
@@ -309,10 +313,32 @@
// scss-docs-end navbar-dark-css-vars
}

+:where(.navbar[data-bs-theme="dark"] .navbar-toggler-icon) {
+ // bslib-patched: toggler icon should follow closest navbar color mode over global mode
+ --#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
+}
+
@if $enable-dark-mode {
@include color-mode(dark) {
- .navbar-toggler-icon {
+ // bslib-patched: toggler follows global theme unless in a light region
+ :where(.navbar:not([data-bs-theme="light"]) .navbar-toggler-icon) {
--#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-dark-toggler-icon-bg)};
}
}
}
+
+.navbar[data-bs-theme="light"] {
+ // bslib-patched: Make sure local light navbar overrides page global
+ --#{$prefix}navbar-color: #{$navbar-light-color};
+ --#{$prefix}navbar-hover-color: #{$navbar-light-hover-color};
+ --#{$prefix}navbar-disabled-color: #{$navbar-light-disabled-color};
+ --#{$prefix}navbar-active-color: #{$navbar-light-active-color};
+ --#{$prefix}navbar-brand-color: #{$navbar-light-brand-color};
+ --#{$prefix}navbar-brand-hover-color: #{$navbar-light-brand-hover-color};
+ --#{$prefix}navbar-toggler-border-color: #{$navbar-light-toggler-border-color};
+
+ .navbar-toggler-icon {
+ // bslib-patched: Make sure toggler icon follows local light mode, too
+ --#{$prefix}navbar-toggler-icon-bg: #{escape-svg($navbar-light-toggler-icon-bg)};
+ }
+}