I was trying to make a div and all its descendants unfocusable. I used a tabIndex -1 on the root div. But that was making focus move to its first focusable child. (The default behavior) Is there a workaround for this issue?
Example code
const SomeFunctionComponent = () => {
// ... some logic ...
const someTrustedHtml = `<p>Hello <a href="stackoverflow.com">World!</a></p>`;
const content = React.createElement("div", {
className: "some class name",
dangerouslySetInnerHTML: {
__html: someTrustedHtml;
},
tabIndex: -1, /* "tabindex": -1 does not work */
// None of these options helped either
// "data-is-focusable": false,
// "aria-hidden": true,
// disabled: true,
// role: "presentation"
});
// ... more logic ...
return (
<div>
{content}
<button onClick={() => console.log("hello world")}></button>
{/* some tab focusable elements */}
</div>
);
}
expected behavior:
When SomeFunctionComponent gets focus, focus would move to the button
actual behavior: focus goes to the link in the dangerouslySetInnerHtml
tabindex is not inheritable. You have to set it on every element that is natively focusable.
Interestingly enough, the spec says that setting it to -1 does not cause an element to be non-focusable, but I use that all the time and it works on all browsers.
Note that the tabindex attribute cannot be used to make an element non-focusable. The only way a page author can do that is by disabling the element, or making it inert.
As others have said, tabindex is not inheritable. However, could a focus trap help you achieve similar, perhaps in a slightly different way? Focus traps do what they sound like - they cage the focus to stay within an element and its descendants. A bit opposite of what it sounds like you were trying to do but it may yield some help. https://github.com/focus-trap/focus-trap
There is no simple solution. As the other answer says, you have to iterate through all focusable inside the div.
In fact, rather than setting tabindex=-1 on all focusable elements inside the div, it would be better to hide the div altogether via display:none or hidden attribute, or using disabled attribute for form fields as a second choice. Hidden elements aren't focusable.
Having the disabled attribute set is important to let the user visually see that he/she can't currently use the field, as well as telling screen reader users of that fact. So, it's preferable. Setting the disabled attribute to true automatically implies that the field isn't focusable anymore.
As a reminder, setting tabindex=-1 doesn't make an element totally unfocusable. It doesn't allow the user to focus it anymore using tab or other normal ways, but it remains focusable programatically (using the focus() method). Note that it's perfectly possible to bypass direct unfocusability with user scripts.