Repository navigation
feat(sidebar): opt-in ARIA landmark roles; aria-controls on nav links - #2526
Merged
Merged
Conversation
Ran `make upgrade-html-deps`. Pulls rstudio/shiny@main (bbc43849, the #4434 merge commit) and rstudio/bslib@main (97aa1abc -> ac1e25f8).
Emit data-dates-disabled instead of data-date-dates-disabled so the dates are parsed as yyyy-mm-dd by the client binding rather than by bootstrap-datepicker with the display format. Omit the attribute when datesdisabled is None. Update InputDate.expect_datesdisabled() to match. Needs the shiny.js from rstudio/shiny#4434.
Port of rstudio/bslib#1359 to ui.sidebar() and ui.page_sidebar(). ui.sidebar() gains a role parameter ("form", "search", "complementary", "region"). The default (None) now renders a neutral <div> instead of an <aside>; "complementary" renders an <aside>, and other roles render a <div> with the corresponding role attribute. Landmark roles require an accessible name: an explicit aria_label/aria_labelledby wins, otherwise the landmark is labelled by the sidebar's title (non-tag titles are wrapped in a display:contents div so they can hold an id). ui.page_sidebar() now places the whole sidebar layout inside the page's <main> landmark (previously only the main content children), and the <main> no longer gets bslib-gap-spacing (page_main_container gains a gap parameter). The Sidebar playwright controller locates the sidebar by class instead of the aside element.
Port of rstudio/bslib#1355: nav links that target a tab panel now carry aria-controls pointing at the panel's id, alongside the existing href.
cpsievert
changed the base branch from
main
to
fix-input-date-datesdisabled-format
October 5, 2026 15:21
The 'str' annotation tripped both pyright and pyrefly in CI (the pyright-ignore comment had also been detached from the call by black).
cpsievert
changed the base branch from
fix-input-date-datesdisabled-format
to
main
October 7, 2026 16:38
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #2523
This PR ports the R-side bslib changes that became necessary after #2523 bumped the vendored bslib assets from 97aa1abc to ac1e25f8. Its base is
fix-input-date-datesdisabled-format(a copy of #2523's branch pushed to this repo), so the diff shows only this PR's commits. Once #2523 merges tomain, delete the copy branch and GitHub will retarget this PR tomain.An audit of the bslib range found 6 commits; the other 4 needed no Python changes: rstudio/bslib#1349 and rstudio/bslib#1352 are TS/SCSS-only (carried by the vendored assets), rstudio/bslib#1353 is a DESCRIPTION change, and rstudio/bslib#1351 fixes a duplicate-id bug py-shiny never had (its
toolbar_input_select()already gives the<select>its own{id}-selectid).Port of rstudio/bslib#1359: sidebar landmark roles
ui.sidebar()gains aroleparameter ("form","search","complementary","region"). The default,None, now renders a neutral<div>instead of an<aside>;"complementary"renders an<aside>, and other roles render a<div>with the correspondingroleattribute (e.g.<div role="form">).aria_label=/aria_labelledby=(passed via**kwargs) always wins and is hoisted from the content div onto the landmark element; otherwise the landmark is labelled by the sidebar'stitle(viaaria-labelledby, generating a title id when needed). Non-tag titles (e.g.HTML()) are wrapped in adisplay:contentsdiv so they can hold an id. A landmark sidebar with no name raisesValueError.ui.page_sidebar()now places the wholelayout_sidebar()inside the page's<main class="bslib-page-main">landmark (previously only the main-content children were), and the<main>no longer getsbslib-gap-spacing(page_main_container()gains agapparameter).playwright.controller.Sidebarnow locates the sidebar by class (> .sidebar#{id}) instead of theasideelement, since the element is no longer always an<aside>.ui.sidebar()gains the sameroleparameter.Note the vendored
page_sidebar.scss(updated in #2523) already expects this new markup.Port of rstudio/bslib#1355: aria-controls on nav links
Nav links that target a tab panel now carry
aria-controlspointing at the panel's id, alongside the existinghref.Testing
page_sidebar()main-landmark structure, andaria-controlson nav links. Existing nav markup expectations updated.tests/pytest: 1226 passed, 6 skipped (the 14test_app_ui_page_html.pyerrors are a pre-existing local starlette/httpx environment issue, also present on the base branch).make check-lint/make check-typesfail locally on pre-existing sandbox files/missing pyrefly, unrelated to this change).