-
Notifications
You must be signed in to change notification settings - Fork 559
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Focus Management API #109
base: main
Are you sure you want to change the base?
Conversation
|
||
## FocusManager | ||
|
||
In addition to defining the focus scopes in an application, components need an API to programmatically move focus around. The singleton `FocusManager` API exported by `react-dom` provides this interface. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would this work with multiple React roots on the page?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one root can have focus at a time. The FocusManager APIs would apply to the root (and scope) which currently has focus.
You are mixing 3 separated things
|
I think all of these are related, and should be considered together. Trapping focus can kind of be implemented in user space, but not fully. It's not possible to support portals correctly. Controlling focus works within the scope, not the component. In a compound component like a list or table, you might want to handle keyboard events at the top and move focus in response. That might be several levels deep rather than a direct child of the component (e.g. within a row and cell). I think it would be inconvenient and not much better than we have now to have to do that focus marshalling manually. The difference between Traversing is quite related to all of this as well. I suppose it could be separated but it would end up being implemented together so I thought it would be better to consider all of this holistically. |
Possible, but might require deeper integration into the browser (read - hook on
I mean - component and everything below. Not above. For example - "focusNext" on the last element should move focus to the first element of the current scope, not to the "next" in the document scope.
Probably we shall not rely on tab index here, and use some other abstraction. For example - in Safary Links and Buttons are
Travesing is needed for other tasks, and should be considered in a broader scope. |
Right, that's defined by rendering a |
Read through the RFC and great to read something that is so detailed and well thought out. There are some things I really think will help. As I read, the following questions came up. Some of this I have mentioned before but for clarity will mention it again here. Focus trappingFor me the idea of focus trapping is pulled broader in the RFC than it should. Stating the obvious, but focus trapping is the keyboard equivalent of not being able to click on anything else for a mouse user. If the keyboard gets trapped while mouse and touch users can still navigate other elements, it is no longer inclusive design. So it seems reasonable that when focus is trapped, there is one container trapping focus and it is modal, i.e. any user cannot interact with anything else on the screen aside from what is in the trapped container. Even if we Inception all the things and have modals inside modals, only the current active group of elements should be navigable. Setting This is still an imperative task. So I feel that the RFC is helping us halfway here while still leaving some imperative tasks to the user. This makes me wonder of it should not form part of the focus trap implementation. Auto focus on unmountI don't think that React should automatically set focus to the previous I do not think that outside of handling focus-setting events, React should ever do the actual focus setting. Leave that to the implementing developer. Positive tabIndexAlthough I understand why you propose using this, I would plead for another way. As you state: On top of this, developers taking a cue from React on how to implement their own things could start implementing positive I believe that React should either be impartial to how a11y features are implemented or, when it does become opinionated, follow the specifications and recommendations of the a11y community. I also share the concern of what it would do in mixed-mode applications. When it comes to implementation of the positive In a barebones
With Also, when opening the As a sighted user I am a mediocre screen reader tester at best, but I cannot see the benefits of autocalculating |
@AlmeroSteyn thanks for your insightful feedback! Some responses below.
Yeah if used incorrectly. However, everything can be used incorrectly. I'm basically proposing react set the equivalent of
You're right that I left out some details of this. What happens if the previously focused element doesn't exist anymore? Sometimes we cannot know where focus should go automatically. However, I think it's a reasonable default. Perhaps we could support For your menu case, I think what would actually happen is that when the menu closes, its focus scope would unmount and restore focus to the target that opened the menu (e.g. button). When the dialog unmounted, it would restore focus to the button. So it might still just work by default in that case. But you're right that there will always be cases where we cannot predict the correct item, and for those we'd need a hook to let the user override.
That's interesting information. I am very aware of the issues with positive tabIndex and hesitated strongly about suggesting it as an implementation strategy. I was worried that reimplementing browser behavior by overriding the Tab key would be worse. We could maybe handle the tab key correctly, but perhaps it works differently across platforms or browsers or something. Also, what about hardware that doesn't have a tab key, like touch screen devices, or game consoles? In those cases, tabIndex may be the only way to expose the information about tab order that we know to the platform. Positive tabIndex would only be needed in a very narrow case: when portals are used, and while focus in inside a React root. That should work around the issue with mixed-mode applications as you say. That said, if there is a better way of implementing this that I'm just unaware of, please let me know. |
Granted! As long as any changes React make to the elements give an inclusive result then all good.
I like the idea in the last sentence here. An event that gives the use the ability to do something with it. I would still not want React to decide for me when and where to go set focus, but rather have React give me the tools so I can easily do it. If I have an event indicating that focus should be set and something else (
Should we not look at it as the effect caused by moving focus. Whether you use Tab or arrows or swipe to move focus is inconsequential, rather that the result is correct. So I have some event that tells me focus is about to move and I have a destination I need that focus to go to which may be different from the next in the DOM order and then I act. So in a modal, activating the button that opens it would be the event trigger to move focus into the modal and the close action of the modal would the trigger to return focus to the controlling element. I don't see that it matters where this action comes from, the fix is to repair focus when it is disturbed. I would expect this to still work in portals?
For fairness I confirmed my suspicions with our own auditors at Tenon before answering. Out of that discussion a pretty real world use case came up: If you set positive Not to mention that React will need to keep track of all managed and unmanaged (parts that may not be coded in React) tabIndexes on the entire page to calculate an order that would work. Otherwise very unexpected results could arise. Based on these kind of unexpected behaviours sites that use positive So I am really excited about some of the features in this rfc but it really needs to be solved without tabIndex :-(
Just from my experience with As mentioned above I cannot yet see why this would not work for portals. Perhaps a first pass of the rfc should focus on tools making it easier for the developer while leaving the actual actionables to the developer. Once that is nailed down and working it would be easier to crystalize out the bits where React could potentially do a little more. What do you think? |
At Ubisoft we have developed a simple Focus Manager to handle gamepad navigation in our SPA used on X1 and PS4. Sadly I've not succeeded yet to open source our solution. I will look at your RFC and try to help as much as I can. You can have a look to a pres I've made with some code previews: https://github.com/sylvhama/bringing-the-www-to-the-aaa |
The point of this RFC is so we can stop manually managing focus imperatively, and just declare what we want to happen. I agree that we might need manual overrides for some edge cases, but I think we can come up with a good default that works automatically for most uses.
That's fine, and expected. We will be setting
Sure if you are just repairing focus, but that's not possible without some context about the user's intent. In the portals example in the RFC without the positive tab indexes, focus would go from input 1, input 3, input 2. If you wanted to repair that, when input 3 focused, you could instead move focus to input 2. However, you only want to do that if it came from the tab key or some other focus movement interaction. You don't want to repair it if the user directly clicked or tapped on input 3. So, we need some info on the user's intent. The tab key is just one of those, but I don't think it's the only one. From @sylvhama's presentation, it looks like game consoles move focus around using some non-standard key codes. I'm not sure if mobile browsers with previous/next buttons to move focus fire keyboard events or not. And there are probably more. The point is that we can't reproduce this reliably in JS. It has to be done by the browser. And the only way to expose information about the correct tab order to the browser as far as I know is via positive We can perhaps prototype this and test it out across platforms/browsers/screen readers, and see how bad it is. If it's just causing issues with audits, then those audits should probably be improved. Blanket banning a browser feature because it can be used incorrectly doesn't seem very productive. If it is causing actual issues with usability, and we determine that it isn't possible to implement the desired behavior, than perhaps we will need to drop that part of the RFC. |
It sounds like - forget about the
So - it has nothing with emulating focusing, playing with tabindexes and intercepting browser behavior - just observing the focus related events, and nothing more. |
Yeah that's possible, but I don't think it's a good idea for react to be inserting extra DOM nodes for you that you don't render. That could potentially mess up things like CSS selectors that depend on the structure you actually render. |
So - there are three options:
Why it would not lead to the issue you've pointed on - because any nested node would not exist - it's portaled! const forwardPortal = (children, targetNode) => (
<div data-portal={targetNode} styles={portalTrapStyles}>
{ReactDOM.createPortal(children, targetNode)}
</div>
) Done! In a user space! |
A locked focus scope should be the result of a user action. They should never just occur during normal navigation as this wil be a serious a11y violation in itself. So a user activates some trigger. This is modal behaviour and setting the rest as inert/aria-hidden="false" supports that. So if you want React to do this all it will need to be aware of the trigger anyways. Once the modal closes that is another event. In both cases focus can be repaired. There are also cases where the popup is not modal. A menu is a perfect example. One simply cannot make the rest of the application inert just because a menu is open. It would be as good as placing the menu on a new page and navigating there for screen reader users. So just like every other user, the screen reader user could and should be able to interact with the rest of the page. If they decide to jump to an ARIA landmark such as a A solution based on repairing focus may require more intervention from the developer, sure, but it is 100% guaranteed not to suffer from this. I like so much of what this RFC suggests that the support it would give me will already be such an enhancement even if I have to be the one to still do the focus setting.
If I came across as advocating a blanket ban of a normal feature or saying we need to avoid this simply to please audits, I am sorry. This was not the intention. Allow me to clarify. If I say things you already know, apologies, but I think it should be on record here. Browsers have functions that have proven to be harmful for accessibility, like the Far be it from me to say that things cannot be improved. The WCAG and a11y audits are changing. In fact we just saw that with version 2.1 of the WCAG. However this document and the audits that stems from it comes from many years of testing and encompasses a huge range of combinations of users, user agents and assistive tech. It help us so that we do not have to do this testing every time ourselves. Good audits from reputable experts dig into this knowledge to assist, not to dictate. If React becomes opinionated about something that every good accessibility source advises against, the testing base will need to be super huge. This means users with specific disabilities testing in every user agent known with every possible form of assistive tech. So it needs to cover screen readers, single switches, motion tracking, eye tracking, speech recognition... the list goes on. Once that is all tested and works for all cases that users can come up with using the new things this RFC aims to create it will be in a position to contradict the burden of evidence out there that positive tabIndex is a bad idea. Keep in mind that right now I can use React to create a website that conforms to all accessibility requirements out there. This is an incredible strength and is because React stays impartial to controversial accessibility issues and leaves that to user land. Some references on (positive) tabIndex: |
I'm not sure I understand the problems with Portals and focus flow for traps. In all focus traps I've implemented you listen at the root |
Yeah, and in that case you wouldn't use the In reply to the rest of your response, I understand the issues with positive tabIndex that you keep repeating, but no one has offered an alternative suggestion that would be able to implement what we need in a reliable way across platforms. This isn't about locking focus - that can be done without positive tab index - this is about correcting the tab order when a user tabs into a portal. If someone can come up with an alternative implementation suggestion to fix the example in the portals section of the RFC, I am all ears! But as far as I can tell, positive tabIndex is the only way. Again, this is only necessary when a portal is present, and the user is focused within the react root. This way it shouldn't cause usability issues with the rest of the page. However, if we determine through prototyping that it does still cause problems, and there is no other way to implement proper tab ordering through portals, then we may just have to drop that part of the RFC, leave the behavior as it is today, and work with browsers to make it possible to implement reliably.
Focus flow in portals doesn't have to do with traps at all, just in how focus flows around portals in general. For traps specifically, you need a way to query whether an element is "inside" a FocusScope, which is why it needs to be done in react itself. Checking for blurs without a focus doesn't seem reliable - what if the user is actually blurring and not moving focus? Then you'd get a blur event without a focus, and cause focus to move even though it wasn't the user's intent. |
not to sideline the conversation on a specific thing, but it is reliable, if you are trapping focus in a particular In any case my point was more about RFC scope, it's not obvious to me that focus traps are something React can implement better than i can already, even with portals. THat's fine too, i'm happy to not have to implement stuff, but do want to get clearish on the line between "what is possible to implement in a browser", "what is possible for React to implement", and finally "what is possible for a user of React to implement in the context of React". It helps understand which aspects are worth bike shedding vs others is all. Awesome work tho, really happy to see this have such lively discussion! |
Imagine a dialog. It contains some inputs. function Dialog() {
return (
<div>
<input placeholder="input 1" />
<input placeholder="input 2" />
</div>
);
} If input 1 is focused, and a user then clicks outside either of the inputs, whether that's still somewhere within the dialog or completely outside, the input will blur and there will be no corresponding focus event. Then you'll end up moving focus back to one of the inputs, which would be wrong. Also, based on that information, how would you know which input to focus? You don't know if the user is moving forward or backward in the tab order. Do you have an example of an implementation of this working somewhere I could see? |
I think we have different expectations of behavior for a focus trap. If you blur off an input the focus should drop to "body", in this case the outer div, not the first or last focusable item. If you tab out of the trap (forward or backwards) focus should move to the browser chrome. It should be noted that with a native dialog, blurring to nothing moves focus to the actual In any case I did confuse my various implementations :P the most common one i've employed is in react-overlay's Modal: https://react-bootstrap.github.io/react-overlays/#modals which definitely isn't perfect, and does suffer from not supporting portals b/c it listens to the |
You are right, I have said my peace here. As for an alternative implementation, no I don't have one and am personally not phased that as a developer I have to still do something here. Because focus is only a part of the story. In the case of the menu I have to know to add If I am coding a modal my ARIA states and properties are different again so that rules out having them set by default. So if the Stab in the dark: You mentioned the need for more declarative focus setting. What if In cases of tabbing into an open portal, this could also possibly be solved with such a |
@jquense - the problem with portals is not about catching |
Ah I see. The aria practices spec for modals says that focus should cycle within the modal, not go back to the browser chrome. Typically there are other keyboard shortcuts for that. |
Focus trapping is consider bad behavior. When focus becomes trapped, it implies that the user is trapped. Focus isolation better describes the practice of intentionally limiting focus to a container.
Not sure I follow. I didn't notice any issues with this approach.
In this case, you have to manage
What about splitting Focus Management and Tab Management? One part emulates focus change, and could be reimplemented in user space(to support Gamepads?), while another one just controls it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This RFC makes me so, so happy. We really need something like this in React -- doing robust, correct focus management is currently SUCH A PAIN, requires a lot of un-reacty code, and is way less performant than direct DOM manipulation in a non-React component. It breaks everything that's nice about React, but it's also an absolute requirement.
Thank you for putting the work into thinking about this, for writing it up, and for publishing it for public comment. You're making the web a better place. My commentary below is a bit...volumous. Please consider that to a reflection of my excitement for the future success of this proposal and not anything negative 🎉
|
||
The following terms will be used throughout this RFC. | ||
|
||
- A **focusable** element is any DOM element which has a `tabIndex` property, along with a set of default elements such as `input`, `button`, etc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this definition essentially https://www.w3.org/TR/html52/dom.html#interactive-content-2 ?
focusNextTabStop(): void; | ||
|
||
/* Focus the previous tabbable element after the currently focused one. */ | ||
focusPreviousTabStop(): void; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious what usages you imagine the focus*TabStop
methods -- doesn't the browser-default behavior of Tab do this for us?
I have pushed an update to this RFC based on the feedback on the PR, and the POC in react-events. Thanks everyone for your thoughtful feedback! 🙏 Here is a summary of the changes:
|
I made a pass at implementing the FocusManager API in addition to the already implemented FocusScope. facebook/react#15849 The API I ended up implementing is a little different than the one I proposed here (with a few more features), and I plan to update the RFC based on it. Feel free to leave feedback! |
We have a complete focus management implementation in React in https://github.com/enactjs/enact/tree/master/packages/spotlight that is already used on millions of devices. Was this implementation considered at all? I haven't had a chance to dig deeply into this proposal but it would be very interesting to at least share ideas and problems we've encountered in delivering this. There is also work being done on a W3C spatial navigation proposal that is relevant: https://www.w3.org/TR/css-nav-1/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are my first-pass comments on the RFC. Thank you for attempting to tackle this important issue. Focus management and spatial navigation are very important to accessible design and it would be great to have an API that would simplify its implementation within React.
|
||
# Motivation | ||
|
||
Focus management is the programmatic movement of keyboard focus in an application in response to user input, such as mouse, touch, or keyboard interactions. Implementing keyboard support for components and applications is imperative for accessibility, and not enough web applications implement this properly today. See the [ARIA Practices](https://www.w3.org/TR/wai-aria-practices-1.1/#keyboard) document for more information about focus management and keyboard interfaces. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be called 'spatial navigation' instead? Focus management, to me, is a broader concept that can also refer to things such as pointer/touch interaction.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we have a different idea of what focus management is. This RFC is dealing with focus in the traditional browser sense, just utilizing the React tree order rather than the DOM order, and providing more declarative primitives for moving focus around in React rather than relying on imperative DOM APIs.
I think you're thinking of an even higher level concept (spacial navigation), which could be implemented on top of this to move focus around in response to actual events (e.g. arrow keys or gamepad). React won't be doing any of that out of the box, just providing the primitives so that other libraries can be built on top.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The discussion of keyboard interactions led me to question that. Also, the inclusion of tab-focus methods. It was not solely restricted to tracking focus with the blur/focus methods and did delve into controlling the focus within a FocusScope
|
||
### Restoring focus | ||
|
||
When you close a dialog or popover, focus should be restored to whatever had focus before the modal opened. This requires us to remember what was focused last, and when the component unmounts, focus that element again. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should it always re-focus the last selected item? This should be configurable to allow for scenarios where the most logical item to be refocused could differ (e.g. the selected item in a dropdown). Given this is configurable below, perhaps it's better to say 'could be restored' or to otherwise change this section to indicate this is optional/configurable behavior.
} | ||
``` | ||
|
||
The tab order in this example will be input 1, input 3, and then input 2, assuming the portal is placed after the app in the DOM. Users may expect the order to be input 1, input 2, input 3, as declared in the React tree. The current behavior is non-deterministic — it depends on the specific implementation of the Portal component (i.e. where it is placed in the DOM), which could change over time and cause the tab order to differ from what was intended. It also depends on the order portals are appended to the DOM rather than the order they are declared. These issues would be solved if the tab order in portals were based on the order in the React tree rather than the DOM tree. This would also match other existing portal behavior such as event bubbling where portals behave as if they are inline. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't take into account DOM ordering based on RTL/LTR, flexbox ordering or other CSS techniques for element relocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RTL/LTR is a layout order, not structural order. This follows the existing DOM behavior or following structural order, but of the React tree instead of the DOM tree. RTL/LTR still follow structural order but in the opposite visual direction. There isn't anything React needs to do to support that - it will happen by default in the browser when using a flipped layout (e.g. flexbox).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're absolutely correct. I hardly ever deal with tab focus since we completely override that behavior hardly ever use that behavior. 👍
|
||
If the `contain` prop is not passed to the `FocusScope`, or the scope is the implicit root `FocusScope`, then the user can tab in and out of the scope at will. Once focus is inside the scope, components can use the `FocusManager` API to programmatically move focus within the scope, for example in response to arrow keys or other interactions. This exact behavior is not provided by React, but APIs to perform these actions are available for component libraries to use. See below for details. | ||
|
||
The `autoFocus` prop can also be passed to a `FocusScope`, which automatically focuses the first focusable element within that scope on mount. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How could I configure a default focus item instead of the first focusable? The first focusable element (in the DOM tree) may not be the logical item to focus.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you'd do that by putting an autoFocus
prop directly on the element you wanted to focus, rather than on the scope.
<FocusScope>
<input />
<input autoFocus />
</FocusScope>
This is already supported by React, so nothing new would need to be implemented.
|
||
While handling the Tab key may not cover all possible cases across all browsers and platforms, it is the only reliable way to implement this behavior without relying on features like positive `tabIndex` (which can cause other accessibility problems) or additional "sentinel" DOM nodes (which can affect e.g. CSS selectors). If a platform implements focusing behavior that does not fire Tab key events, then the behavior would be exactly as it is today - following DOM order rather than React tree order. Additional support for these platforms could be added to React in the future as well if they are deemed important enough to support. | ||
|
||
When the `restoreFocus` prop is enabled, the last focused element is stored by React when the `FocusScope` mounts. When the `FocusScope` unmounts, focus is restored to that element. If the element is no longer in the DOM, then focus is restored to the body (the default browser behavior). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would you be able to deal with items that are not initially rendered on mount (e.g. VirtualList items). Is there some method that could be made available either through placeholders or callbacks that would allow the developer to cache and restore focus compatible with this system?
|
||
## FocusManager | ||
|
||
In addition to defining the focus scopes in an application, components need an API to programmatically move focus around. The singleton `FocusManager` API exported by `react-dom` provides this interface. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a singleton disallows library authors from having access to custom management within components/sections. It also disallows custom components from specifying their own, local focus management. How could these situations be handled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be moving to a context-based API. We've done some POC work here and implemented a useFocusManager
hook to access the focus manager, instead of using a singleton. I'll update the RFC to reflect that.
One other comment that occurred to me is that there does not appear to be anything in the spec to deal with focus set through pointer interaction or programmatic focus ( |
Yes, this will all be built on top of the standard focus implementation in browsers utilizing native focus and blur events, |
Thanks for the responses. I'll look over the implementation you linked some more and see how it interacts with the implementation of focus management we use. |
Is it possible to know if the current |
@devongovett thank you first of all on starting this! 👍 That's fantastic work! This topic of focus management is very close to me as I am a contributor to open-source react library called Stardust and my main responsibility is to make sure that each component is delivered accessible. I went through your RFC and here some thoughts which are on top of my mind I want to share:
Would love to hear your thoughts on that. |
I really like this idea and I think it could be implemented as some library that React will use rather then make it React-specific. |
@krotovic I feel mixed. I partially agree with this proposal. I definitely agree in regards to things like the amount of refs needed to do something that is a standard pattern outside of React. I think the proposal hits the mark in regards to the ability to declaratively say "I want everything outside this component to have But I do think the proposal goes a bit far when it tries to do stuff outside the standard toolkit, namely things that are difficult/impossible to get right even when you aren't using react. |
@dantman I may not express myself very clearly. I thought to extract the part that isn't necessarily React specific e.g. FocusManager to simple library that can be implemented by other UI libraries like React, Vue, Angular, etc. I'm not sure if it could help some of those libs but it may be considered. |
In this case, it should rely on DOM as a source of truth, and such libraries already exist. |
I would really like to see this in React. The majority of react component libraries have an extremely difficult time with focus management. This means there are 0 accessible dataGrids in React, and the debates in the React Router world has meant that almost every website with react does nothing around alerting screen reader users something happened. |
Per #182, I'll comment that this is an area we're very interested in (in the longer term) but it's not currently on our near-term roadmap. We've had a few internal experiments in this area (here's a test file for the low-level APIs we've used). But we're unsatisfied with how overly generic the API we tried is, and that experiment probably doesn't have a future. When we get to this problem space, we'll be sure to explore this thread for inspiration. If you've implemented something related in userland and it gave you some ideas, please don't hesitate to share it here too. I'll keep this open because we're not ready to review this. |
Thank you for the interest still in this @gaearon! It will be a huge help. For posterity, my latest attempt at solving this was in a custom hook that helps to keep track of ids called use-item-list. I also wrote a small post on hacking useMutableSource to make this work with concurrent mode, although, I haven't looked at it in a while so it may be a broken approach now. This library use-ref-list has an example using that technique with a codesandbox here. |
This is also interesting: https://twitter.com/pirelenito/status/1459892048308408327 |
This RFC proposes adding a builtin
FocusScope
component andFocusManager
API toreact-dom
, along with internal logic to properly manage focus in React applications. Along with focus scopes declared in the application, it will take into consideration portals and other React concepts which may cause the React tree and the DOM tree to differ in relation to focus management.Related discussion: #104.
View Rendered Text