JSFiddle - React, Tailwind, and code Playground
HTML
<a href="#test" onclick="alert('Oh no!');">I should not receive any focus</a>
<input type="text" value="No focus please" />
<div class="overlay">
<div class="dialog">
Here is my dialog<br />
TAB out with Shift+Tab after focusing "focus #1"<br />
<input type="text" value="focus #1" /><br />
<input type="text" value="focus #1" /><br />
</div>
</div>
CSS
.overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
text-align: center;
}
.dialog {
display: inline-block;
margin-top: 30%;
padding: 10px;
outline: 1px solid black;
background-color: #cccccc;
text-align: left;
}
JavaScript
console.clear();
var tabbingForward = true;
//The body should have at least 2 input fields outside of the dialog to trap focusing, otherwise focusing may be outside of the document and we will loss control in such a case.
//So we create 2 dummy text fields with width = 0 and opacity = 0
var dummy = "<input style='width:0; opacity:0'/>";
var clickedOutside = false;
$('body').append(dummy).prepend(dummy);
$('.dialog').focusout(function(e){
if(clickedOutside) {
e.target.focus();
clickedOutside = false;
}
else if(!e.relatedTarget||!$('.dialog').has(e.relatedTarget).length) {
var inputs = $('.dialog :input');
var input = tabbingForward ? inputs.first() : inputs.last();
input.focus();
}
});
$('.dialog').keydown(function(e){
if(e.which == 9) {
tabbingForward = !e.shiftKey;
}
});
$('body').mousedown(function(e){
if(!$('.dialog').has(e.target).length) {
clickedOutside = true;
}
});
//focus the first input initially
$('.dialog :input:first').focus();