diff --git a/__tests__/spelling-ignore.yml b/__tests__/spelling-ignore.yml
index 106dbb404b..dc4b642afb 100644
--- a/__tests__/spelling-ignore.yml
+++ b/__tests__/spelling-ignore.yml
@@ -127,6 +127,7 @@
- TODO
- TBD
- CJK
+- TBC
# Tool and library names
- axe-core
diff --git a/_rules/focus-returns-trigger-9au0ou.md b/_rules/focus-returns-trigger-9au0ou.md
new file mode 100644
index 0000000000..203475ccdf
--- /dev/null
+++ b/_rules/focus-returns-trigger-9au0ou.md
@@ -0,0 +1,245 @@
+---
+id: 9au0ou
+name: Focus returns to trigger
+rule_type: atomic
+description: |
+ This rule checks that when a modal closes the focus returns to the trigger that opened the modal.
+accessibility_requirements:
+ wcag20:2.4.3: # Focus Order (A)
+ forConformance: true
+ failed: not satisfied
+ passed: further testing needed
+ inapplicable: further testing needed
+ wcag-technique:G59: # Placing the interactive elements in an order that follows sequences and relationships within the content
+ forConformance: false
+ failed: not satisfied
+ passed: further testing needed
+ inapplicable: further testing needed
+input_aspects:
+ - Accessibility Tree
+ - DOM Tree
+acknowledgments:
+ authors:
+ - Dan Tripp
+ - Helen Burge
+---
+
+## Applicability
+
+This rule applies when focus is trapped within a region activated by a trigger control that is dismissible.
+
+## Expectation
+
+The element that triggers the target element to become visible, is still present in the screen behind the triggered content and is the same element that receives focus when the target element stops being visible.
+
+## Background
+
+### Assumptions
+
+There are no assumptions.
+
+### Accessibility Support
+
+Some assistive technologies on known browsers still exhibit inconsistencies. Specifically, if an element is removed from the accessibility tree after being activated (e.g., a close button), and focus is moved via JavaScript to an element that is not inherently operable (e.g., a button works, but a div with tabindex="-1" may not), the assistive technology might automatically shift focus to the closest visible element, regardless of the intended JavaScript behavior.
+
+### Bibliography
+
+- [Understanding Success Criterion 2.4.3: Focus Order](https://www.w3.org/WAI/WCAG22/Understanding/focus-order.html)
+- [G59: Placing the interactive elements in an order that follows sequences and relationships within the content](https://www.w3.org/WAI/WCAG22/Techniques/general/G59)
+
+## Test Cases
+
+### Passed
+
+#### Passed Example 1
+
+The button that is activated to display the [modal][] gets the [focus][] returned to it when the [modal][] is dismissed using the escape key or activating close, OK or cancel button in the modal.
+
+```html
+
+
+
+ Passed Example 1
+
+
+
+
+
+
+
+
+
+
+
+
Dialog title
+
Dialog content.
+
+
+
+
+
+
+
+
+
+```
+
+#### Passed Example 2
+
+The link that is activated to display the [modal][] gets the [focus][] returned to it when the [modal][] is dismissed using the escape key or activating close, OK or cancel button in the modal.
+
+```html
+
+
+
+ Passed Example 2
+
+
+
+
+
+
+ Do nothing
+ Open modal dialog
+ Do nothing
+
+
+
Dialog title
+
Dialog content.
+
+
+
+
+
+
+
+
+
+```
+
+### Failed
+
+#### Failed Example 1
+The button that is activated to display the [modal][] gets the [focus][] returned to the item after it when the [modal][] is dismissed.
+
+```html
+
+
+
+ Failed Example 1
+
+
+
+
+
+
+
+
+
+
+
+
+
For this test: use any button, or the escape key, to close the dialog.
+
+
+
+
+
+
+
+
+
+```
+
+#### Failed Example 2
+The button that is activated to display the [modal][] gets the [focus][] returned to the start of the page when the modal is dismissed.
+
+```html
+
+
+
+ Failed Example 2
+
+
+
+
+
+
+
+
+
+
+
+
+
For this test: use any button, or the escape key, to close the dialog.
+
+
+
+
+
+
+
+
+
+```
+
+#### Failed Example 3
+The link that is activated to display the [modal][] gets the [focus][] returned to the item after it when the [modal][] is dismissed.
+
+```html
+Code needed!
+```
+
+#### Failed Example 4
+The link that is activated to display the [modal][] gets the [focus][] returned to the start of the page when the modal is dismissed.
+
+```html
+Code needed!
+```
+
+#### Failed Example 5
+The page has a list of buttons that is activated to display a [modal][], the [focus][] is returned to the incorrect button on dismissing the modal.
+
+```html
+Code needed!
+```
+
+### Inapplicable
+
+#### Inapplicable Example 1
+TBC
+
+```html
+Code needed!
+```
+
+[focus]: #focused 'Definition of focused'
+[modal]: https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/
diff --git a/package.json b/package.json
index ff4a1959cb..279f00b7f7 100644
--- a/package.json
+++ b/package.json
@@ -131,6 +131,10 @@
{
"name": "Helen Burge",
"url": "https://github.com/HelenBurge"
+ },
+ {
+ "name": "Dan Tripp",
+ "url": "https://github.com/dan-tripp-siteimprove"
}
],
"devDependencies": {
diff --git a/test-assets/9au0ou/9au0ou.css b/test-assets/9au0ou/9au0ou.css
new file mode 100755
index 0000000000..2e365c8d13
--- /dev/null
+++ b/test-assets/9au0ou/9au0ou.css
@@ -0,0 +1,21 @@
+.close-button {
+ padding: 0.3rem;
+ margin: 0.3rem;
+ /*
+ display: inline-block;
+ vertical-align: middle;
+ overflow: hidden;
+ text-decoration: none;
+ color: inherit;
+ background-color: inherit;
+ text-align: center;
+ cursor: pointer;
+ white-space: nowrap
+ */
+}
+
+.topright {
+ position: absolute;
+ right: 0;
+ top: 0;
+}
diff --git a/test-assets/9au0ou/aria-apg-dialog.css b/test-assets/9au0ou/aria-apg-dialog.css
new file mode 100755
index 0000000000..0bf4286f80
--- /dev/null
+++ b/test-assets/9au0ou/aria-apg-dialog.css
@@ -0,0 +1,135 @@
+.hidden {
+ display: none;
+}
+
+[role="dialog"] {
+ box-sizing: border-box;
+ padding: 15px;
+ border: 1px solid #000;
+ background-color: #fff;
+ min-height: 100vh;
+}
+
+@media screen and (min-width: 640px) {
+ [role="dialog"] {
+ position: absolute;
+ top: 2rem;
+ left: 50vw; /* move to the middle of the screen (assumes relative parent is the body/viewport) */
+ transform: translateX(
+ -50%
+ ); /* move backwards 50% of this element's width */
+
+ min-width: calc(640px - (15px * 2)); /* == breakpoint - left+right margin */
+ min-height: auto;
+ box-shadow: 0 19px 38px rgb(0 0 0 / 12%), 0 15px 12px rgb(0 0 0 / 22%);
+ }
+}
+
+.dialog_label {
+ text-align: center;
+}
+
+.dialog_form {
+ margin: 15px;
+}
+
+.dialog_form .label_text {
+ box-sizing: border-box;
+ padding-right: 0.5em;
+ display: inline-block;
+ font-size: 16px;
+ font-weight: bold;
+ width: 30%;
+ text-align: right;
+}
+
+.dialog_form .label_info {
+ box-sizing: border-box;
+ padding-right: 0.5em;
+ font-size: 12px;
+ width: 30%;
+ text-align: right;
+ display: inline-block;
+}
+
+.dialog_form_item {
+ margin: 10px 0;
+ font-size: 0;
+}
+
+.dialog_form_item .wide_input {
+ box-sizing: border-box;
+ max-width: 70%;
+ width: 27em;
+}
+
+.dialog_form_item .city_input {
+ box-sizing: border-box;
+ max-width: 70%;
+ width: 17em;
+}
+
+.dialog_form_item .state_input {
+ box-sizing: border-box;
+ max-width: 70%;
+ width: 15em;
+}
+
+.dialog_form_item .zip_input {
+ box-sizing: border-box;
+ max-width: 70%;
+ width: 9em;
+}
+
+.dialog_form_actions {
+ text-align: right;
+ padding: 0 20px 20px;
+}
+
+.dialog_close_button {
+ float: right;
+ position: absolute;
+ top: 10px;
+ left: 92%;
+ height: 25px;
+}
+
+.dialog_close_button img {
+ border: 0;
+}
+
+.dialog_desc {
+ padding: 10px 20px;
+}
+
+/* native