You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A bit finicky with rendering non-ref children, can cause issues when used in combination with ClickOutsideListener
containerElements requiring a list of elements and not immediately working with refs
Can create actual focus traps in some rare scenarios (does not handle web components correctly, does not handle nameless radio groups)
Having our own mechanism of trapping/managing focus that better adapts to the paradigms that we use would help to reduce this friction, as well as provide a mechanism for this to be used for future behaviors outside of Cauldron.
As an inspiration, Adobe Spectrum has a FocusScope and useFocusManager hook that would be much better aligned with how we write our components today. This would provide much greater flexibility than what react-focus-trap currently offers today.
Concepts
At a high level the necessary behaviors could be contained within individual hooks to encapsulate containing focus plus any necessary configuration options to initialize and configure focus traps:
typeuseFocusTrapProps<TargetElementextendsElement=Element,FocusElementextendsHTMLElement=HTMLElement>=(target: ElementOrRef<TargetElement>,options: {/** * When set to false, deactivates the focus trap. This can be necessary if * a component needs to conditionally manage focus traps. */disabled?: boolean;/** * When the trap is activated, an optional custom element or ref * can be provided to override the default initial focus element behavior. */initialFocusElement?: ElementOrRef<FocusElement>;/** * When set to true and the trap is deactivated, this will return focus * back to the original active element or the return focus element if * provided. */returnFocus?: boolean;/** * When the trap is deactivated, an optional custom element or ref * can be provided to override the default active element behavior. */returnFocusElement?: ElementOrRef<FocusElement>;})=>void
This could replace the focus trap in the following components:
Dialog
Drawer
Popover
TwoColumnPanel
The advantage of utilizing a hook vs a component is removing any complexities that from "focus scope management" having to figure out what the containing child should be and trying to align on a single responsibility of just focus management. This hook should not be concerned with clicking outside, whether or not things outside of the scope are aria-hidden, but purely focused on just containing focus within the element.
The text was updated successfully, but these errors were encountered:
Is there a more React-like way to find the first focusable element in a form than what I do here (using querySelectorAll)? I of course, could apply a ref to the first focusable element, but the first focusable element is nested in this form in children component and it changes dynamically, so I don't want to have to drill down into each component to set refs on the first select/input/button/etc. manually.
...
const formRef = useRef<HTMLFormElement>(null);
...
const focusFirstFocusableElement = () => {
const form = formRef.current;
if (form) {
const focusableElements = Array.from(
form.querySelectorAll(
'input:not([type="hidden"]):not([disabled]), select, textarea, button, a'
)
) as HTMLElement[];
if (focusableElements.length > 0) {
focusableElements[0].focus();
}
}
};
useEffect(() => {
if (!isLoading) {
focusFirstFocusableElement();
}
}, [isLoading, isStepDataLoading]);
We've been encountering a number of issues with
react-focus-trap
over the years. There's some limiting factors toreact-focus-trap
, such as:focus-trap-options
only being read upon initial renderschildren
, can cause issues when used in combination withClickOutsideListener
containerElements
requiring a list of elements and not immediately working with refsHaving our own mechanism of trapping/managing focus that better adapts to the paradigms that we use would help to reduce this friction, as well as provide a mechanism for this to be used for future behaviors outside of Cauldron.
As an inspiration, Adobe Spectrum has a
FocusScope
anduseFocusManager
hook that would be much better aligned with how we write our components today. This would provide much greater flexibility than whatreact-focus-trap
currently offers today.Concepts
At a high level the necessary behaviors could be contained within individual hooks to encapsulate containing focus plus any necessary configuration options to initialize and configure focus traps:
This could replace the focus trap in the following components:
Dialog
Drawer
Popover
TwoColumnPanel
The advantage of utilizing a hook vs a component is removing any complexities that from "focus scope management" having to figure out what the containing child should be and trying to align on a single responsibility of just focus management. This hook should not be concerned with clicking outside, whether or not things outside of the scope are
aria-hidden
, but purely focused on just containing focus within the element.The text was updated successfully, but these errors were encountered: