blob: bb8d679a35b3f1b04e7d0e5648548137b1ff5403 [file] [log] [blame]
<!DOCTYPE html>
<meta charset="utf-8" />
<title>Popup focus behaviors</title>
<link rel="author" href="mailto:masonf@chromium.org">
<link rel=help href="https://open-ui.org/components/popup.research.explainer">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<popup data-test='default behavior - popup is not focused' data-no-focus>
<p>This is a popup</p>
<button>first button</button>
</popup>
<popup data-test='autofocus popup' autofocus class=should-be-focused>
<p>This is a popup</p>
</popup>
<popup data-test='autofocus empty popup' autofocus class=should-be-focused></popup>
<popup data-test='autofocus popup with button' autofocus class=should-be-focused>
<p>This is a popup</p>
<button>button</button>
</popup>
<popup data-test='autofocus child'>
<p>This is a popup</p>
<button autofocus class=should-be-focused>autofocus button</button>
</popup>
<popup data-test='autofocus on tabindex=0 element'>
<p autofocus tabindex=0 class=should-be-focused>This is a popup with autofocus on a tabindex=0 element</p>
<button>button</button>
</popup>
<popup data-test='autofocus multiple children'>
<p>This is a popup</p>
<button autofocus class=should-be-focused>autofocus button</button>
<button autofocus>second autofocus button</button>
</popup>
<popup autofocus data-test='autofocus popup and multiple autofocus children' class=should-be-focused>
<p>This is a popup</p>
<button autofocus>autofocus button</button>
<button autofocus>second autofocus button</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus popup'>
<p>This is a popup</p>
<button class=should-be-focused>first button should be focused</button>
<button>second button</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus takes precedence over autofocus'>
<p>This is a popup</p>
<button class=should-be-focused>first button</button>
<button autofocus>autofocus button should NOT be focused</button>
</popup>
<popup delegatesfocus autofocus data-test='delegatesfocus takes precedence over autofocus 2'>
<p>This is a popup</p>
<button class=should-be-focused>first button</button>
<button>autofocus button should NOT be focused</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus on empty popup has no effect' data-no-focus></popup>
<popup data-test='delegatesfocus on child has no effect' data-no-focus>
<p>This is a popup</p>
<button delegatesfocus>first button</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus skips contained popups'>
<p>This is a popup</p>
<popup>
<button>Contained popup button</button>
</popup>
<button class=should-be-focused>first button</button>
<button>autofocus button should NOT be focused</button>
</popup>
<popup delegatesfocus data-test='delegatesfocus skips contained dialogs'>
<p>This is a popup</p>
<dialog>
<button>Contained dialog button</button>
</dialog>
<button class=should-be-focused>first button</button>
<button>autofocus button should NOT be focused</button>
</popup>
<style>
popup {
border: 2px solid black;
top:150px;
left:150px;
}
:focus-within { border: 5px dashed red; }
:focus { border: 5px solid lime; }
</style>
<script>
function activateAndVerify(popup) {
const testName = popup.getAttribute('data-test');
const priorFocus = document.createElement('button');
priorFocus.id = 'prior-focus';
document.body.appendChild(priorFocus);
let expectedFocusedElement = popup.matches('.should-be-focused') ? popup : popup.querySelector('.should-be-focused');
if (popup.hasAttribute('data-no-focus')) {
expectedFocusedElement = priorFocus;
}
test(t => {
t.add_cleanup(() => priorFocus.remove());
assert_true(!!expectedFocusedElement);
assert_false(popup.open);
priorFocus.focus();
assert_equals(document.activeElement,priorFocus);
// Directly show the popup:
popup.show();
assert_equals(document.activeElement, expectedFocusedElement, `${testName} activated by popup.show()`);
popup.hide();
// Use an activating element:
const button = document.createElement('button');
const popupId = 'popup-id';
assert_equals(document.querySelectorAll('#' + popupId).length,0);
document.body.appendChild(button);
t.add_cleanup(function() {
popup.removeAttribute('id');
button.remove();
});
popup.id = popupId;
button.setAttribute('popup', popupId);
priorFocus.focus();
button.click();
assert_equals(document.activeElement, expectedFocusedElement, `${testName} activated by button.click()`);
// Make sure we can directly focus the (already open) popup:
popup.focus();
assert_equals(document.activeElement, popup.hasAttribute('delegatesfocus') ? expectedFocusedElement : popup, `${testName} directly focus with popup.focus()`);
popup.hide();
}, "Popup focus test: " + testName);
}
document.querySelectorAll('body > popup').forEach(popup => activateAndVerify(popup));
</script>