Offcanvas: Improve offcanvas drawer support for same-page navigation #38514
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.
Add an option to not return focus to the offcanvas toggle button after an offcanvas nav drawer is closed.
Description
A navbar can be configured with an offcanvas drawer where the menu slides in (when a navbar button is clicked or tapped). Currently, the offcanvas drawer acts like a modal in that closing the drawer causes focus to be reapplied to the navbar button.
Reapplying focus is the expected behavior for a modal used for actions such as adjusting settings (e.g. font size), but is unexpected when the user clicks a same-page link. The expectation is focus will be on the destination element.
There is an additional complication with Chromium browsers if clicking the same-page link is used to close the drawer (in addition to starting a smooth scroll to an HTML element). On Chromium browsers, setting focus stops any in-process scrolls. Bootstrap sets the offcanvas transition time to 0.3s. Chrome takes around 0.4s and Edge takes around 0.7s to scroll to a new position, so the scroll does not have time to complete. Firefox will complete the scroll. (Don’t have info on Safari.)
Change details
Make the following changes to the offcanvase.js source file
true
.boolean
.EventHandler.on
function, move theEventHandler.one
function call to after the data const value is set, and wrap theEventHandler.one
function in anif statement
that only calls theEventHandler.one
function ifdata._config.focus
is set totrue
.EventHandler.one
setsthis.focus()
to take place after the offcanvas drawer has been hidden. Making theEventHandler.one
conditional makes it possible to use links on the offcanvas drawer to move around a page and have the tab-order in the right sequence, rather than restarting from the navbar.Setting the focus option
The focus setting can be set by either a
data-bs-focus="false"
or adata-bs-config= '{"focus": false}'
data attribute on the offcanvas div.Maintaining current functionality
If the new focus variable is left at the default value (true), then offcanvas sidebars will operate the same way they do now.
Changes to the documentation
offcanvas.md
Add a line to the Options table in offcanvas.md to provide information about the new variable.
focus boolean true Return focus to the data-bs-toggle element.
Example
Add a functional example of using offcanvas for a single-page website to the Examples section.
Motivation & Context
For a single-page website with a navigation menu (the menu links point to elements on the same page) and the need to use a hamburger style menu button (the menu items will not fit across the top of the page on a mobile device), there are the following issues with the current offcanvas drawer slide-in menu:
fixed-top
, causing the navbar to always be showing, the hamburger button will have the focus.fixed-top
, the page will scroll to the button and the button will have the focus.It would be nice (the motivation for the change) for users, when clicking a same-page link, for the page to scroll to that position and focus be associated with the element the page scrolled to.
Type of changes
Checklist
npm run lint
)Codepen examples
Standard (unmodified) offcanvas.js for single pages w/ autoclose menu
Demonstrates how focus is returned to the menu button and Chromium based browsers stop scrolling.
https://codepen.io/richdebourke/pen/zYmomJz
Modified offcanvas.js for single pages w/ autoclose menu
Demonstrates how the modified offcanvas.js skips returning focus to the menu button, leaving it at the destination element.
https://codepen.io/richdebourke/pen/ExdNKWm
Chromium browsers stop scrolling when focus is set
Demonstrate how Chromium based browsers stop scrolling when focus is set to another element.
https://codepen.io/richdebourke/pen/NWObWdd
Additional information
Automatically closing the offcanvas drawer
For same-page links, an offcanvas element can be automatically closed by either including a
data-bs-dismiss="offcanvas"
attribute on the link (in a span tag) or by using an event listener to get the offcanvas instance and callinghide()
. For links on the offcanvas drawer to a different page, the drawer wouldn’t need to be closed.React Bootstrap focus option
React Bootstrap has a restoreFocus function that controls whether to restore focus to a button or not
Related issues
Pull request #38079 by @ChellyAhmed: Posted on February 17, 2023 – Prevent Scrolling back when focus on close. Adds
preventScroll: true
object to thethis.focus()
method, which results in the page not scrolling to the menu button if page has scrolled to a new point. The menu still needs to be closed manually and focus is point to the menu button rather than to the active point on the page. The pull request is still pending as of this writing.Issue #34447: Posted on July 7, 2021 – offcanvas: causes re-focus of trigger element after hidden. It was closed by @GeoSot with a note that, “I am pretty sure that it is not a bug, as modal and collapse have the same behavior, to indicate in purpose the trigger element.”
While Bootstrap’s modal and collapse functions do return focus to the trigger element when a navbar is collapsed, most websites, for same-page menus, let the focus follow the link.