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!: Introduce navbar_options() #1141

Merged
merged 34 commits into from
Dec 2, 2024
Merged

feat!: Introduce navbar_options() #1141

merged 34 commits into from
Dec 2, 2024

Conversation

gadenbuie
Copy link
Member

@gadenbuie gadenbuie commented Nov 26, 2024

This PR consolidates the position, bg, collapse, inverse and underline arguments of navset_bar() and page_navbar() into a navbar_options() helper and replaces their use in the parent functions with a single navbar_options argument.

Before

page_navbar(
  title = "My App",
  bg = "#0062cc",
  underline = TRUE,
  nav_panel() # ...
)

After

page_navbar(
  title = "My App",
  navbar_options = navbar_options(
    bg = "#0062cc",
    underline = TRUE
  ),
  nav_panel() # ...
)

Using the direct arguments results in a lifecycle deprecation warning

page_navbar(
  title = "My App",
  bg = "#0062cc"
)
#> Warning message:
#> The `bg` argument of `page_navbar()` is deprecated as of bslib 0.9.0.
#> ℹ Navbar options have been consolidated into a single `options` argument. Use the `bg`
#>   argument of `navbar_options()` instead.
#> ℹ The deprecated feature was likely used in the bslib package.
#>   Please report the issue at <https://github.com/rstudio/bslib/issues>.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated. 

and another warning is emitted if the same argument is used in both places

page_navbar(
  title = "My App",
  bg = "#0062cc",
  navbar_options = navbar_options(bg = "#cc0099")
)
#> Warning message:
#> In page_navbar(title = "My App", bg = "#0062cc", navbar_options = navbar_options(bg = "#cc0099")) :
#>   `bg` was provided twice: once directly and once in `navbar_options`.
#> • The deprecated direct option(s) will be ignored and the values from `navbar_options` will be used.

Background

The reason for this PR is two-fold:

  1. The arguments of page_navbar() and navset_bar() are applied in several different contexts, but there are clear groupings. This change makes it clearer which arguments apply to the navbar appearance and style by separating them from the remaining arguments.

  2. This change makes it easier to introduce new navbar options to page_navbar() and navset_bar(). Bootstrap 5 has moved away from the default/inverse terminology and has improved the terminology around the navbar colors. (Is inverse = TRUE for light on dark background or dark text on light background? I can never remember.)

    Bootstrap 5 now uses data-bs-theme="dark" and the color mode terminology, where "light" is like a light color mode, i.e. dark text on a light background. It'd be nice to make the navbar functions consistent with this new language in a backwards-compatible way.

    However, if we were to introduce mode or type as a top-level argument, it'd be far too confusing with the other arguments. If we introduce navbar_mode or navbar_type, it's equally confusing -- why is only mode or type prefixed with navbar_? Introducing a navbar_options() helper gives us the space to have better named arguments. It also creates space to have Bootstrap version-aware options and defaults.

@gadenbuie gadenbuie marked this pull request as ready for review November 26, 2024 19:33
@gadenbuie gadenbuie requested a review from cpsievert November 26, 2024 19:33
collapsible = collapsible,
underline = underline,
.fn_caller = "page_navbar",
.warn_deprecated = !was_called_by_shiny
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really really like to decouple shiny::navbarPage() from bslib::page_navbar(). I'm thinking it'd be an update to add page_navbar_legacy() that we'd export but mark as internal so it doesn't show up in docs and indices.

What I want out of that change is to have a clear line around what parts of the navbar API we shouldn't touch without thinking carefully about backwards compatibility or API changes and which parts are owned by bslib. Currently it feels too entangled and over time entropy wins leading to more entanglement.

R/navs-legacy.R Outdated Show resolved Hide resolved
R/navs-legacy.R Outdated Show resolved Hide resolved
@cpsievert
Copy link
Collaborator

cpsievert commented Nov 26, 2024

This change makes it easier to introduce new navbar options to page_navbar() and navset_bar().

Do you have any immediate/near-term plans to do this?

@gadenbuie
Copy link
Member Author

This change makes it easier to introduce new navbar options to page_navbar() and navset_bar().

Do you have any immediate/near-term plans to do this?

Yeah, I'm planning to immediately use this to introduce navbar_options(type = "dark") as a replacement for inverse. See posit-dev/brand-yml#52 for (long and detailed) background.

@cpsievert
Copy link
Collaborator

Yeah, I'm planning to immediately use this to introduce navbar_options(type = "dark")

Sounds good, thanks. FWIW, I do want to be conservative about adding more to the bslib:: namespace, so I wasn't sure about this at first, but I can see now why this is worth it.

R/navs-legacy.R Outdated Show resolved Hide resolved
R/navs-legacy.R Outdated Show resolved Hide resolved
DESCRIPTION Outdated Show resolved Hide resolved
@cpsievert
Copy link
Collaborator

Here is the idea I had earlier, but had a hard time articulating. It does drop the extra warning about navbar_options() taking precedence, but I feel like that's overkill anyway given you'll also get a deprecation warning in that case:

simplify.patch

@gadenbuie
Copy link
Member Author

Here is the idea I had earlier, but had a hard time articulating. It does drop the extra warning about navbar_options() taking precedence, but I feel like that's overkill anyway given you'll also get a deprecation warning in that case:

Thanks for the suggestion. I also tried something similar this morning, but I think it's important that navbar_options() is equivalent to a standard list. With the current implementation, navbar_options(bg = "red") and list(bg = "red") are equivalent. That feels like an important constraint to me.

I also think it's important to consider that the code is currently a little complicated to give the best transition experience. In a year or so we could delete most of it and hard-deprecate the direct arguments (once we deal with shiny::navbarPage()).

R/navs-legacy.R Outdated Show resolved Hide resolved
R/navs-legacy.R Outdated Show resolved Hide resolved
R/navs-legacy.R Outdated Show resolved Hide resolved
@cpsievert
Copy link
Collaborator

That feels like an important constraint to me.

Another way to go to fulfill this constraint would be attach the "present" arguments as a character vector attribute on the list.

....currently a little complicated...

...In a year or so we could delete most of it...

I won't insist on following my suggestion, but part of why I'm pushing back is that, in my experience, complicated code tends to not get touched/deleted because it's painful to load up all the context.

@gadenbuie
Copy link
Member Author

Another way to go to fulfill this constraint would be attach the "present" arguments as a character vector attribute on the list.

Good idea, done in ee683e7

R/navs-legacy.R Outdated Show resolved Hide resolved
R/navs-legacy.R Outdated Show resolved Hide resolved
R/navs-legacy.R Outdated
is_default <- attr(options_user, "is_default") %||% list()
for (opt in names(options_old)) {
can_use_direct <-
!opt %in% names(options_user) ||
Copy link
Collaborator

@cpsievert cpsievert Dec 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is here to account for the fact that we might in the future have deprecated options that aren't available in navbar_options()? It's not clear to me why we need to account for that situation here, but then silently drop them later in rlang::exec(navbar_options, !!!options_user)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring specifically to the !opt %in% names(options_user) line?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, it says that NULL values in navbar_options() can be overridden by non-null direct values, but I've changed this in the latest commit.

I've reworked this so that navbar_options(bg = NULL) wins in the presence of a direct use of bg, since the signal is that the user put bg in navbar_options(). The implicit bg = NULL in navbar_options() is (still) overridden by a direct bg = "red" or similar.

The end result is that navbar_options_resolve_deprecated() returns an object that is completely equivalent to one that would be created by directly calling navbar_options(). This means that when we elevate to deprecation errors instead of warnings, the only code we need to delete is the unreachable branch inside navbar_options_resolve_deprecated() and some easy-to-identify test code.

R/navs-legacy.R Outdated Show resolved Hide resolved
@gadenbuie gadenbuie requested a review from cpsievert December 2, 2024 21:10
@gadenbuie gadenbuie merged commit 74a138c into main Dec 2, 2024
13 checks passed
@gadenbuie gadenbuie deleted the navbar-options branch December 2, 2024 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants