Skip to content

fix(sidebar): neutral sidebar markup with opt-in landmark roles - #1359

Merged
gadenbuie merged 10 commits into
mainfrom
fix/1358-sidebar-role
Sep 22, 2026
Merged

gadenbuie merged 10 commits into
mainfrom
fix/1358-sidebar-role

Conversation

@gadenbuie

@gadenbuie gadenbuie commented Sep 21, 2026 •

Copy link
Copy Markdown
Member

Fixes #1358
Fixes #1334

Summary

Sidebars previously used <aside> markup, so every sidebar became a complementary landmark. Screen reader users heard each dashboard sidebar announced as separate complementary content, even when the sidebar held the controls that drive the page's main output.

This PR changes the default sidebar markup to a neutral <div>. The new role argument of sidebar() adds a landmark when the sidebar's content warrants one. sidebar() accepts "form", "search", "complementary", or "region". "complementary" renders an <aside>; the other roles render a <div> with a role attribute.

Landmark roles need an accessible name. sidebar() labels the landmark from its title when one exists, and otherwise requires aria-label or aria-labelledby. An unnamed landmark role is a rendering error.

page_sidebar() now wraps its sidebar and main content in a single <main> element, so a sidebar with role = "form" sits inside the page's main landmark. That layout matches the guidance in the issue: dashboard filters are part of the main content, not complementary to it.

Also fixes the always-false guard in as.tags.bslib_sidebar() reported in #1334 (if (is.null(open)) resolved to base::open; now checks x$open).

gadenbuie and others added 6 commits September 21, 2026 11:46
Sidebars now render as a plain div by default instead of an aside,
since a sidebar's visual placement doesn't imply its content is
complementary to the main content. The new role argument of sidebar()
opts into a landmark: "complementary" renders a native aside, while
"form", "search", and "region" render a div with the matching ARIA
role. Landmark roles require an accessible name, provided by the
sidebar title (which is wired up via aria-labelledby) or by an
explicit aria-label/aria-labelledby, which always takes precedence.

Part of #1358
page_sidebar() now wraps the entire layout_sidebar() in its single
<main> element, so sidebar controls and content together form the
page's main landmark, instead of only the content area. The page
main container helper gains a gap argument shared with the navbar
variant, and the page-sidebar min-height/min-width rules are
retargeted for the extra <main> wrapper while remaining conditioned
on fillable layouts.

Part of #1358
@gadenbuie
gadenbuie marked this pull request as ready for review September 21, 2026 15:57
@gadenbuie
gadenbuie requested a review from cpsievert September 21, 2026 16:11
Comment thread R/sidebar.R
@gadenbuie
gadenbuie merged commit ac1e25f into main Sep 22, 2026
@gadenbuie
gadenbuie deleted the fix/1358-sidebar-role branch September 22, 2026 17:09
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.

Sidebar marked up as aside as.tags.bslib_sidebar guard is always FALSE

2 participants