Skip to content

Commit

Permalink
fix(utils): focusElementsWithin correctly focuses container element a…
Browse files Browse the repository at this point in the history
…s a fallback
  • Loading branch information
mlaursen committed Apr 18, 2021
1 parent 1d92472 commit cff46c4
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 4 deletions.
7 changes: 7 additions & 0 deletions packages/utils/src/wia-aria/__tests__/focusElementWithin.ts
Expand Up @@ -192,4 +192,11 @@ describe("focusElementWithin", () => {
);
expect(scrollIntoView).not.toBeCalled();
});

it("should fallback to focusing the container element if it is focusable", () => {
const div = document.createElement("div");
div.tabIndex = -1;

expect(() => focusElementWithin(div, "first", true)).not.toThrow();
});
});
17 changes: 13 additions & 4 deletions packages/utils/src/wia-aria/focusElementWithin.ts
@@ -1,5 +1,6 @@
import { scrollIntoView } from "../scrollIntoView";
import { getFocusableElements } from "./getFocusableElements";
import { isFocusable } from "./isFocusable";

export type Focus = "first" | "last" | string;

Expand All @@ -12,21 +13,24 @@ export type Focus = "first" | "last" | string;
* @param focus - Either the "first" or "last" string to focus the first or last
* focusable element within the container or a query selector string to find a
* focusable element within the container.
* @param programmatic - Boolean if programmatically focusable elements should be
* included as well.
* @param preventScroll - Boolean if the focus event should not scroll the
* element into view. This should normally remain `false`, but can be useful if
* the element gets focused while offscreen during a transition.
* @param progamatic - Boolean if programatically focusable elements should be
* included as well.
* @param elements - Optonal child elements to search
* @remarks \@since 2.8.0 Supports focusing the container element if it is
* focusable
*/
export function focusElementWithin(
container: HTMLElement | Document,
focus: Focus,
programatic = false,
programmatic = false,
preventScroll = false,
elements?: HTMLElement[]
): void {
if (!elements || !elements.length) {
elements = getFocusableElements(container, programatic);
elements = getFocusableElements(container, programmatic);
}

let el: HTMLElement | null;
Expand All @@ -41,6 +45,11 @@ export function focusElementWithin(
el = container.querySelector<HTMLElement>(focus);
}

// just allow any focusable-type element
if (!el && isFocusable(container, "programmatic")) {
el = container;
}

if (!el) {
throw new Error("Unable to find a focusable element");
}
Expand Down

0 comments on commit cff46c4

Please sign in to comment.