Skip to content
Open
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
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

* Added an aria-controls attribute when using bslib::page_navbar() with bslib::nav_panel() to establish an explicit relationship between the tab and the controlled tab panel. (@shelbylevel, #1354)

* `page_navbar()` now wraps the top navigation bar in a `<header>` element, giving the page a banner landmark that screen readers can navigate to.

* `page_navbar()` now renders its content area as a `<main>` element, giving the page a main landmark. (Pages with a `sidebar` already had one, via `page_main_container()`.)

# bslib 0.12.0

## New features
Expand Down
15 changes: 15 additions & 0 deletions R/page.R
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,21 @@ page_navbar <- function(
theme = theme
)

# Wrap the navbar in a <header> to give the page a banner landmark.
# This happens here, rather than in navs_bar_(), because navset_bar()
# (which shares that code) can appear anywhere on a page, where a
# banner landmark would be inappropriate.
navbar[[1]] <- tags$header(navbar[[1]])

# Give the content area a <main> landmark. When a sidebar is present, the
# content area already contains a <main> (via page_main_container()), so
# only change the content container's tag in the sidebar-less case. Done
# in-place (rather than wrapping) so the container remains a direct child
# of the page's fill container.
if (is.null(sidebar)) {
navbar[[2]]$name <- "main"
}

page_func(
title = infer_window_title(title, window_title),
theme = theme,
Expand Down
Binary file modified R/sysdata.rda
Binary file not shown.
Binary file modified man/figures/page-navbar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions tests/testthat/test-page.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,61 @@ test_that("page_navbar()", {
)
})

test_that("page_navbar() wraps the navbar in a <header> banner landmark", {
skip_if_not_installed("shiny")
with_private_seed()

html <- renderTags(page_navbar(
title = "foo",
nav_panel("One", "content")
))$html
expect_match(
as.character(html),
"<header>\\s*<nav class=\"navbar",
perl = TRUE
)

# navset_bar() can appear anywhere on a page, so it must NOT be wrapped
with_private_seed()
html <- renderTags(navset_bar(
title = "foo",
nav_panel("One", "content")
))$html
expect_no_match(as.character(html), "<header", fixed = TRUE)
expect_no_match(as.character(html), "<main", fixed = TRUE)
})

test_that("page_navbar() gives the content area a <main> landmark", {
skip_if_not_installed("shiny")
with_private_seed()

html <- renderTags(page_navbar(
title = "foo",
nav_panel("One", "content")
))$html
expect_match(
as.character(html),
"<main class=\"container-fluid",
fixed = TRUE
)

# With a sidebar, the page-level <main> comes from page_main_container(),
# and there should be exactly one <main> on the page
with_private_seed()
html <- as.character(
renderTags(page_navbar(
title = "foo",
sidebar = sidebar("side"),
nav_panel("One", "content")
))$html
)
expect_match(html, "<main class=\"bslib-page-main", fixed = TRUE)
expect_equal(
lengths(regmatches(html, gregexpr("<main", html, fixed = TRUE))),
1
)
})

test_that("page_sidebar()", {
with_private_seed()

Expand Down