open-ui icon indicating copy to clipboard operation
open-ui copied to clipboard

[focusgroup] Why not include memory of last focused item in group?

Open travisleithead opened this issue 2 years ago • 20 comments

Transferred from https://github.com/MicrosoftEdge/MSEdgeExplainers/issues/579

Opened by @aleventhal

Focusgroup is really neat. I'm super happy to see it being worked on, and the number of scenarios handled is amazing.

Regarding this part, I admit I'm very disappointed that focusgroup doesn't handle this for us:

The focusgroup doesn't "remember" the last element that was focused when focus leaves the group and returns later. Instead, the "leaving" and "returning" logic (for keyboard scenarios) depends on the preexisting tabindex sequential focus navigation only (those with tabindex=0 for example). The CSS Toggles proposal could be used in this same scenario to track the "toggle state" among this group of toggle-able elements, allowing focus changes to be decoupled from "selection/toggle" state.

Is this not being handled because of the reliance on tabindex, which already hard codes whether something is tabbable or just focusable?

Maybe all we need is another property, like focus-group-memory: on|off|value. The default would be on. When used, all focusable descendants would get a computed tabindex of 0 or -1, overriding the attribute value.

User impact: the impact would be the highest in containers with many controls. Imagine tabbing into a grid and being at column 50, row 50. When you tab to the toolbar and come back, it would sure be helpful to be in the right place.

CC @travisleithead @benbeaudry

@jcsteh wdyt?


@benbeaudry wrote:

@travisleithead This would require a few changes in our implementation, but I do agree that the users would benefit from it. Was there any specific reason why we decided not to keep track of the last focused element when leaving a focusgroup in the first place?


@jcsteh responded:

I agree this would often be a massive efficiency benefit for users. I think it's also what users have come to expect in most cases.

travisleithead avatar May 26 '22 18:05 travisleithead

@travisleithead If I recall (and this convo was awhile ago), I think the issue here was that not every instance where someone may want to use focusgroup should automatically return someone to the previously focused instance. If someone wanted focusgroup behavior for a menu with menu-items I would not expect focusgroup to return me to the last item I invoked, I would expect it to drop me to the first focusable menu-item.

I agree this would be a benefit to users but IMO it would likely need to be opt-in and not prescribed for all because it isn't applicable for all instances.

chrisdholt avatar May 26 '22 19:05 chrisdholt

@chrisdholt are we talking about a menu that is a dropdown, expanding when you click something? I would say if the menu closes in between, that would reset it. Otherwise, I don't see an issue with returning to the last focused item.

aleventhal avatar May 26 '22 20:05 aleventhal

I wrote this in an earlier iteration of the explainer (e.g., https://github.com/MicrosoftEdge/MSEdgeExplainers/commit/6fd4e17e36df119d59e4968ca11c365b9096e3fe) which captures my thinking at the time. I still feel hesitant about starting to mess around with the sequential tab focus algorithm.

The "memory" part of a focusgroup could be added as an additional attribute value, such as "sticky" which would then cause the focusgroup to remember the last focused item and return to it. However, supporting such a feature would require potentially interfering with sequential focus navigation. For example, it becomes very challenging to predict where focus might go when entering a focusgroup. The "memory element" (saved element that is a tab stop) could be at the end of a list of tab-focusable elements. When entering the focusgroup, does the platform ignore and skip the set of tab-focusable elements that should come before the memory element, to jump directly to the "memory element"? Does it only jump to the memory element if it happens to be before (in tabindex navigation order) any of the other tab-able elements? Rather than tackle these concerns initially, this is left as a possible future extension.

But, let's brainstorm a bit. The use of tabindex>=0 is fully under author control. We have to assume that if an author marks an element with tabindex>=0 that they want that element to participate in sequential focus navigation. I think we have two options for adding "memory": one that respects the author's use of tabindex>=0 and one that dismisses their intent (within the scope of a focusgroup).

(focusgroup values below are for discussion purposes only ;-)

focusgroup=memory-reset

I think not having a memory is a good default given the relative potential surprises of the other approaches. We can view this as having a "reset-able" memory: e.g., as soon as focus is moved by the tab key (entering, exiting, or within a focusgroup's scope), the last focused item is forgotten, and the focusgroup "resets" back to its state as declared in the DOM by virtual of tabindex values. (This is the current stateless design.)

focusgroup=memory-roving

This first approach attempts to integrate with the sequential focus navigation order within a focusgroup. The idea is that the element that currently has focus acts as if it has a tabindex=0 value (even if it does not). Entering the focusgroup for the first time still respects the sequential focus navigation order, as does pressing the tab key (for elements marked with tabindex>=0 within the focusgroup). However, when the arrow keys move the focus to an element that was focusable with tabindex=-1, that element is treated as tabindex=0 until focus is moved to another element within the focusgroup, in which case it goes back to its tabindex=-1 state. So, given this:

<element tabindex=0> before </element>
<parent focusgroup>
  <element tabindex=0> A </element>
  <element tabindex=-1> B </element>
  <element tabindex=0> C </element>
  <element tabindex=-1> D </element>
</parent>
<element tabindex=0> after </element>

The natural sequential focus navigation order (for Tab) is [ before | A | C | after ].

If arrow keys move the focus to B, B is added to the order: [ before | A | B | C | after ].

When focus is moved to C (either by Tab or arrow keys), B is dropped from the order (because focus memory is still within the scope of the focusgroup): [ before | A | C | after ]

When focus goes to D: [ before | A | C | D | after ], and then the user Tabs out of the focusgroup to after, D stays in the sequential navigation order [ before | A | C | D | after ]. In this way, re-entering the focusgroup from the end (Shift+Tab) takes the user to the last focused element that is proximally closest to their entry-point in sequential navigation order.

It's not a perfect solution, but tries to respect the rest of the tabindex=0 values set by the author.

focusgroup=memory-override

This approach is to completely ignore the differentiation of tabindex=-1 and tabindex=0 for the purposes of sequential navigation order. Instead, the platform would wholly manage the sequential focus navigation order by implementing the roving tabindex pattern across everything focusable in the focusgroup's scope. In the previous example above, the tabindex=0 values would be ignored. The platform would pick an initial entry point (likely the first focusable item in DOM order if forward-tabbing into the focusgroup, or the last item if reverse-tabbing into the focusgroup) as the singleton tab stop for the focusgroup. No other tab stops would be possible. As the arrow keys move the focus around, the platform "remembers" that current element so that when tab moves focus out of the focusgroup (in either direction), that same element will be the designated return element when focus re-enters (either from a forward or reverse direction).

If there are other variations or approaches, I'm curious to hear what you think.

My POR was to defer this feature until CSS Toggles is farther along. It seems to me that rather than have a "last focused" memory, what authors really want is to have focus return to a current "selected" element (e.g., an active tab in a tab row). That selected item (or N selected items), introduces a third variable for consideration that might be more explicitly controllable by authors than the memory-roving approach above.

travisleithead avatar May 26 '22 20:05 travisleithead

@jcsteh @scottaohara @benbeaudry

aleventhal avatar May 26 '22 20:05 aleventhal

@chrisdholt are we talking about a menu that is a dropdown, expanding when you click something? I would say if the menu closes in between, that would reset it. Otherwise, I don't see an issue with returning to the last focused item.

Sure - both could use focusgroup though (a menu which expands from a menu button or a static menu) and so you'd need to be able to choose the correct behavior for each. I agree on the value here. My point was primarily why it wasn't default behavior and why I think it would need to be opt-in. Again, we discussed this on one of our calls w/r/t behavior, just trying to recall examples we discussed specifically where it wasn't universal.

chrisdholt avatar May 26 '22 20:05 chrisdholt

My opinions, so take with a grain of salt:

  • tabindex > 0 is evil, and it should be strongly discouraged, and even not supported in a focusgroup.
  • The only useful tabindex values are 0 (tabbable) and -1 (focusable).
  • When focusgroup is used everything that is focusable in any way should just be normalized to be focusable. Any value of tabindex is treated the same.
  • memory of the last focus should be the default. The memory can clear when the focusgroup element is hidden, which takes care of the dropdown case.
  • The "non-memory" might not be useful enough for the first version. We could ship and see when people really need it.

aleventhal avatar May 26 '22 20:05 aleventhal

  • tabindex > 0 is evil, and it should be strongly discouraged, and even not supported in a focusgroup.

Agreed here, I don't think we should encourage or support this (@travisleithead I think I'm on record on this in notes somewhere 😄 )

chrisdholt avatar May 26 '22 20:05 chrisdholt

  • When focusgroup is used everything that is focusable in any way should just be normalized to be focusable. Any value of tabindex is treated the same.
  • memory of the last focus should be the default. The memory can clear when the focusgroup element is hidden, which takes care of the dropdown case.

So that's a +1 from @aleventhal for the focusgroup=memory-override behavior that I desribed above, with the extra feature of "forgetting" when content is hidden.

It does result in the erasure of use cases where authors want to have multiple tab stops within a focusgroup. E.g., this is a use case employed by Microsoft Edge's tab row today. Not sure we can just drop that use case.

travisleithead avatar May 26 '22 20:05 travisleithead

@travisleithead thanks, is there a demo of that use case I can peek at?

aleventhal avatar May 26 '22 21:05 aleventhal

@travisleithead thanks, is there a demo of that use case I can peek at?

not a demo, but I think I show the use case in more detail in this recorded OpenUI meeting - around time index 04:44. Two permanent tab stops and a "roving" tab stop.

travisleithead avatar May 26 '22 21:05 travisleithead

Travis summed up pretty well the three approaches we have: reset, roving or override.

Reset is trivial and doesn't solve this issue. It's also our current approach.

memory-roving

I think that the memory-roving approach is interesting and is our best shot at dealing with fixed tab stops within a focusgroup and keeping track of the last visited focusgroup-item (by setting its tabindex value to 0). However, I see a couple of potential issues with it:

  1. All the focusgroup items above (when moving forward) a sibling focusgroup item that has a tab stop won't be "memorized" as last visited when navigating away by pressing the tab key, since that fixed tab stop focusgroup-item will become the last visited focusgroup item. I think this could fall under the bad authoring category, though.
  2. Having moving tab stops in-between fixed tab stops might become confusing to the end user.

memory-override

This approach is one that would just "make sense" for the end user, so I like a lot. Making sure that there is always only one tab stop per focusgroup and leaving it be managed by the platform is a simple and great solution.

However, I think this would render the "natively tabbable" elements (buttons, links, etc.) not tabbable anymore and would potentially be very confusing for the end user.

Example:

<div focusgroup=horizontal>
    <a href=#>Link 1</a>
    <a href=#>Link 2</a>
    <a href=#>Link 3</a>
    <a href=#>Link 4</a>
</div>

The user might expect to be able to tab to each link, but because these links are now within a focusgroup, they aren't tabbable. This would feel weird in my opinion.

Note that for this to be a problem, the links and buttons would need to be the focusgroup items directly - not descendants of focusgroup items.

For example, this wouldn't be an issue:

<ul focusgroup=vertical>
    <li tabindex=-1><a href=#>Link 1</a></li>
    <li tabindex=-1><a href=#>Link 2</a></li>
    <li tabindex=-1><a href=#>Link 3</a></li>
    <li tabindex=-1><a href=#>Link 4</a></li>
</ul>

I think the memory-override approach is the most user-friendly, but the least developer-friendly because it breaks the tabbable behavior developers have come to expect - links, buttons, and any other element with tabindex>=0 won't be tabbable within a focusgroup. For this reason alone, I don't think this should be the default behavior - I'd like the developer to really opt-in that mode, knowing full well that it will break your usual tabindex values. This is just my opinion and should be taken with a grain of salt.

TLDR

  • memory-roving is developer friendly as it doesn't break anything and stores the last visited focusgroup item for you automagically.
  • memory-roving might be confusing to users, but I might be wrong.
  • memory-override is so simple it the users probably won't notice that its being used.
  • memory-override can be "dangerous" if the developer uses it without reading the docs (but that never happens, right?) since it would break the tabbable behavior

Extra question

  • If a focusgroup doesn't have any tabbable focusgroup-item, should the focusgroup automatically make the first/last element tabbable (depending on the tab navigation direction)? Someone mentioned that in a comment above and I really liked the idea... should this be a default behavior regardless of "memory" mode, or would this lead to more issues?

benbeaudry avatar May 26 '22 22:05 benbeaudry

There are some good points here.

Is anyone up for having a video meeting on this topic? Just +1 this message if you want want to join.

aleventhal avatar May 27 '22 15:05 aleventhal

There hasn't been any discussion on this issue for a while, so we're marking it as stale. If you choose to kick off the discussion again, we'll remove the 'stale' label.

github-actions[bot] avatar Nov 24 '22 00:11 github-actions[bot]

Looking again at adding a memory (and making it the default behavior):

I do like the simplicity of the "memory-override" approach outlined above where the platform hijacks all the focusable elements, however, I think I found a problem use case that would need to be handled somehow. The scenario is:

<div focusgroup>
   <a href="somewhere">hyperlink</a>
   <label for=text>What's your name?</label>
   <input id=text type=text>
   <button>do something</button>
</div>
  1. You Tab into the focusgroup (first time), and land on the hyperlink. focusgroup's memory is updated to the hyperlink.
  2. Then you use arrow keys to move to the input element. (Note: it would be weird for users if 'Tab' stopped working at this point.) Again, memory is updated to the input element.
  3. You enter your name. Arrow keys don't work to escape the input element because it currently captures those keystrokes. (We could change input behavior to not trap the arrow keys when in a focusgroup to fix this.) You 'Tab' away. (Note, it would be weird for users if the focus didn't go to the button.)
  4. Focus jumps out of the focusgroup (because the entire thing is treated like a single Tab stop).
  5. Later, the user returns to the focusgroup by Shift-Tab. Focus is moved to the last-remembered item (the input element). Unless we make changes to the input element's behavior (and potentially other input trapping-element's behavior, though content-editable/EditContext might be hard to change and have compat issues), focus is now stuck in the input and the user can't get back to the hyperlink (or the button) while in the focusgroup.

travisleithead avatar Feb 08 '24 18:02 travisleithead

I'd like to propose a 4th approach, not mentioned above, that is similar to the current approach of not having a memory (and respecting all tabindex values), but which does add-in a "memory" and the memory is only used when re-entering the scope of the focusgroup (it's less complicated than "memory-roving"), and I hope it could make a good default behavior. If we need to add a way to opt-out, we could do that too.

"entrance-memory"

In this approach, tabindex=0 and tabindex=-1 values are completely ignored but only when focus enters or re-enters a focusgroup. After that (once inside), it's business-as-usual for the Tab key with respect to the document's tab order given wherever focus redirected to. So, in the prior example, focus would still get trapped in the input type=text element in step 3, but step 4 would jump to the button element (next in tab order). If the user then leaves the focusgroup and returns (step 5) they would go to the last element they had focused, but could then use Tab to move around again (if they got stuck).

This approach allows webdevs to easily create roving tabindex behavior where there is only ever one tab stop, by setting everything tab-able to tabindex=-1 within a focusgroup, for example:

<div focusgroup>
   <a href="somewhere" tabindex=-1>hyperlink</a>
   <label for=text>What's your name?</label>
   <input id=text type=text tabindex=-1>
   <button tabindex=-1>do something</button>
</div>

which, of course, re-introduces the issue outlined above where the user can get stuck in the input, but at least in that case, they introduced the problem themselves, and can fix it by making some other element in the focusgroup tab-able.

And if we consider a case that doesn't involve an element like <input> that captures keystrokes, then the combination of setting everything focusable to tabindex=-1 and adding a focusgroup acts just like the "memory-override" case.

Regarding @benbeaudry's extra question:

If a focusgroup doesn't have any tabbable focusgroup-item, should the focusgroup automatically make the first/last element tabbable (depending on the tab navigation direction)? Someone mentioned that in a comment above and I really liked the idea... should this be a default behavior regardless of "memory" mode, or would this lead to more issues?

I think this is nicely solved with the "entrance-memory" proposal. The first entrance to the focusgroup disregards what the tabindex values are and selects the focusable element that the focusgroup's memory is tracking, or if there is nothing in the memory, I think it should select the first focusable item in DOM order in the focusgroup (including if the first entrance is from Shift-Tab, reverse direction entrance).

travisleithead avatar Feb 08 '24 21:02 travisleithead

Note: @gfellerph proposed an alternative approach that sticks with "memory-override", but addresses the problem of getting trapped in the input element by allowing the platform to temporarily make the next/previous focusable elements around the input element have tabindex=0 behavior to allow for a Tab-escape, and then reverting back to the normal behavior after focus moves. This would have to be pretty smart in case the next/previous elements were also focus-input traps too.

travisleithead avatar Feb 08 '24 21:02 travisleithead

Need to also figure out under what conditions the memory of the focusgroup will be forgotten.

  • @aleventhal mentions that one case is when the focusgroup element is hidden.
  • Perhaps another should be when any changes to the DOM are made to the subtree of the focusgroup element? In any case, if the element that is being remembered gets removed from the DOM for some reason, that's at least one case to forget it. :)
  • when it is disabled, inert, or excluded from a focusgroup
  • if its "focusability" is ever toggled.

travisleithead avatar Feb 08 '24 21:02 travisleithead

It could also get disabled, inert or excluded from the focusgroup by CSS or attribute, basically if it becomes not focusable (I wish there was a browser API like node.focusable).

@travisleithead, is the difference between "memory-override" and "entrance-memory" that tabindex settings by the author are respected the first time a focusgroup candidate gets focus but then thrown away for "memory-override" mode while "memory-override" will not initially respect the authors tabindex?

Not initialised (no element received focus yet), the author made the first button not focusable:

<div focusgroup>
  <button tabindex="-1">First</button> <!-- set by the author, is skipped when user tabs into the focusgroup -->
  <input type="text">
  <input type="text">
  <input type="text">
  <button>Last</button>
</div>

User tabs into the focusgroup, first input receives focus as the button is being skipped:

<div focusgroup>
  <button tabindex="0">First</button> <!-- gets activated for backwards tab exit -->
  <input type="text" tabindex="0"> <!-- arrow keys are now handled by the input field, roving focus is trapped -->
  <input type="text" tabindex="0"> <!-- gets activated for forwards tab exit -->
  <input type="text" tabindex="-1">
  <button tabindex="-1">Last</button>
</div>

In this state, it could also be possible to use selectionStart to determine if the cursor is at the beginning or the end of the input field and handle arrow keypresses from there on to move back to the focusgroup. This would get a little harder with <audio>, <video> and friends if they have visible controls.

After pressing tab:

<div focusgroup>
  <button tabindex="-1">First</button> 
  <input type="text" tabindex="0"> <!-- gets activated for backwards tab exit -->
  <input type="text" tabindex="0"> <!-- has focus -->
  <input type="text" tabindex="0"> <!-- gets activated for forwards tab exit -->
  <button tabindex="-1">Last</button>
</div>

The whole focusgroup looses focus because the user clicked somewhere else:

<div focusgroup>
  <button tabindex="-1">First</button> 
  <input type="text" tabindex="-1"> <!-- resets when the sibling input lost focus -->
  <input type="text" tabindex="0"> <!-- memorised -->
  <input type="text" tabindex="-1"> <!-- resets when the sibling input lost focus -->
  <button tabindex="-1">Last</button>
</div>

All this tabindex setting is of course just necessary if there is no other way to take an element out of focus order while keeping it interactive otherwise.

gfellerph avatar Feb 09 '24 23:02 gfellerph

@gfellerph thanks for illustrating your idea with examples.

@travisleithead, is the difference between "memory-override" and "entrance-memory" that tabindex settings by the author are respected the first time a focusgroup candidate gets focus but then thrown away for "memory-override" mode while "memory-override" will not initially respect the authors tabindex?

Did you mean 'but then thrown away for "entrance memory" mode while "memory-override" will not initially respect the authors tabindex?'? I'm not sure that quite captures it. Let me clarify using your example setup. (And remember that focusgroup will not actually change tabindex values in the DOM--I assume your examples are illustrative of what is happening internally).

From the not-initialized state (no memory yet), a tab into the focusgroup would put the focus on the <button> in your example in both "entrance-memory" and "memory-override".

  • In "entrance-memory" this is because the "entrance" to the focusgroup just picks the memory element OR the first focusable thing (ignoring tabindex=-1) in DOM order when nothing is in the memory. A tab key press would then go to the first <input> and so on like normal.
  • in "memory-override" the <button> is selected for the same reason, and then it works like a typical roving tabindex set. A tab key press would then jump out of the focusgroup.

Hope that helps.

travisleithead avatar Feb 13 '24 23:02 travisleithead

Current plan:

  • change the explainer to add a "memory" to the focusgroup with the least disruption/magic to existing Tab behavior as possible. A roving-tab-index "memory" is a nearly universal feature of all existing roving tab-index patterns. The MVP of this feature would not be complete without it. The "entrance-memory" proposal adds a memory that has minimum impact on other Tab behavior allowing developers to workaround potential issues noted above with focus-trapping elements without needing to add other magic behaviors.

travisleithead avatar Feb 21 '24 19:02 travisleithead

From a recent telecon (see issue #990), it was noted:

Make the entire focusgroup focusable (by default) so that it's always a tab stop (another alternative to tricky memory/tabindex behavior changes) (@keithamus)

This could be another alternative to needing to introduce special-case handling for tabindex...?

travisleithead avatar Feb 27 '24 19:02 travisleithead

Note from @kbrilla copied here from #990

Roving tabindex with focusgroup (take 2) (from this doc) Needs ability to opt out from memory mechanism as for example common pattern is using tabindex=0 on selected option and when you tab into/tab back into you always want that selected item to be first focused not the last item where you were (for example using arrows). From what I understand this will not be possible as memory mechanism takes priority before tabindex=0

I think this makes sense and is a good use case for having an opt-out.

travisleithead avatar Feb 27 '24 19:02 travisleithead

The discussion in the meeting just been swayed me against the idea of making the whole group focusable so I withdraw my position on that.

keithamus avatar Feb 29 '24 20:02 keithamus

The Open UI Community Group just discussed [focusgroup] Why not include memory of last focused item in group?.

The full IRC log of that discussion <bkardell_> Travis: There was some discussion in the recent thread, thank you... as well as some commentary in the doc I wrote about what focusgroup is solving for and the roving tabindex pattern.. hopefully that was helpful
<bkardell_> Travis: we don't have any kind of memory - it doesn't remember where you had focus before... So, several solutions were proposed in 537
<bkardell_> Travis: first was a proposal I'll call roving, which tries not to interfere with what the tabstop would be, so it ... well, it's complicated, and hard to implement and maybe not predictable
<bkardell_> Travis: the second I'll call override - it just kind of works like most web developres write today... memory just clobbers whatever was there before. In the issue we found an issue that a naieve implementation would cause -- if you had a textbox that traps arrow key movement in your focus group, you'd get stuck.. As you exited, the textbox is remembered and then you can't get out
<bkardell_> Travis: I'm sure there are some workarounds - I think luke or keith suggested some in the issue
<keithamus> q+
<bkardell_> Travis: a third one, I am calling "the latest proposal" the one I hope sticks... we do as little messing with tab stop as possible and just jump you write to the memory element, and if that is missing we just move you into the first focusable element
<bkardell_> Travis: so it just preempts the focus order and jumps you to the memory - that's the one case, and outside of that it's just normal order
<gregwhitworth> ack keithamus
<gregwhitworth> q?
<bkardell_> keithamus: I would like to refloat the idea of focusgroup itself being tabindex 0.. it kind of helps solve. If the group is the first thing that is focused, your arrow keys move you around the in the focusable items and once you make a focus choice, exiting and entering will put you back on it or store it.. that way the default is just to put you on the group and otherwise you wind up in the right place
<Travis> https://codepen.io/hexagoncircle/pen/QWMZBve
<gregwhitworth> q+
<bkardell_> keithamus: stopping on the focus group should only happen once, I think
<gregwhitworth> ack gregwhitworth
<bkardell_> keithamus: once you've made a choice it should just remove itself from the tabindex flow, but I don't know if that's weirtd
<bkardell_> s/weirdtd/weird
<scotto_> q+
<bkardell_> keithamus: if they're all tabindex=-1 then if there is a memory location you move to that. Once you've made a choice, it will immediately move focus.
<gregwhitworth> ack scotto_
<bkardell_> scotto_: the thing I'm struggling with is: depending on what you are bulding, either case might be the right thing... with a grid you never expect to focus on the grid itself, you just go to the first cell
<bkardell_> scotto_: but then the other use case - like a series of cards that then someone is supposed to arrow around to whatever the heck those things are. There's no one way to do this, so how do you account for both use cases? Otherwise , I think you're right.
<bkardell_> scotto_: but for those other use cases, maybe focus never should go to the focus group container at all - or maybe it should go into it
<gregwhitworth> q?
<bkardell_> keithamus: if you set tabindex -1 on the focusgroup, you would explicitly opt out of the group getting focus... You could get into weird states - if it was all tabindex (parent and children) that would be weird, you could get into there if you clicked something and then you can move focus around
<gregwhitworth> q+
<bkardell_> scotto_: even if you put tabindex-1 on the container, it sounds silly but it's common that then an errant click someone in proximity has suddenly set the focus in there. (some ancedote about cats that I missed)
<bkardell_> gregwhitworth: do we have user research in any meaningful sense about what users want?
<bkardell_> keithamus: The markdown toolbar in github does this - we did some user studies.
<bkardell_> gregwhitworth: did they want it on the outer layer or did they not? I'm not sure I've seen one that does that? Has everyone screwed up ?
<bkardell_> keithamus: there's no focus ring on the outer container - if we had a do-over I would propose that... WE can add visual queues or aria-described by on the container at least. We haven't done the user research on that specific thing
<bkardell_> gregwhitworth: I think this is where it needs to be a new element with a completely different semantic meaning. That's where my brain jumps to - Idk if that is a correct thought or not
<gregwhitworth> q?
<gregwhitworth> ack gregwhitworth
<bkardell_> keithamus: what's the motivation for that
<masonf> The suggestion is <focusgroup>
<bkardell_> gregwhitworth: looking across the industry, they don't seem to stop on the container that would be a focusgroup - since this is a proposal for an attribute, it can be applied anywhere. This would make it create an implied tab stop
<bkardell_> Travis: actually the proposal is a little more subtle - - only if there was no memory.
<masonf> q?
<masonf> q+
<bkardell_> keithamus: it's a solution to discoverability
<gregwhitworth> q+
<bkardell_> keithamus: there is no way right now that arrow keys are going to do anything - it would be nice to have a visual or an auditory queue so that AT could let you known
<scotto_> q+
<bkardell_> Travis: is there a way in the platform that you can still make that notification by being in a subtree of something - or do you have to actually be on the thing
<bkardell_> masonf: there are other things that where you are in the context of the tree matters
<gregwhitworth> ack masonf
<bkardell_> masonf: If the best approach from the users point of view is that the group gets focused but only the first time, it does sound like something that a new element would be great at. It is slightly semantically different and it comes with a bunch of behaviors that are different
<bkardell_> q+
<gregwhitworth> ack gregwhitworth
<bkardell_> masonf: I just played with the rich editor in gh, it has the behavior I naievely expect.. Are there examples of anyone anywhere that do this - are there
<gregwhitworth> ack scotto_
<bkardell_> keithamus: I'm not specifically aware
<dbaron> +1 to being nervous about doing things here that aren't paving cowpaths
<gregwhitworth> +1 to dbaron +1
<masonf> q+
<bkardell_> scotto_: as far as what would the aria role for this be - the problem is that some of this is expected by current roles.. Are we doing this to make toolbars? should we make a toolbar element? Navigable grid? It could be a new element? It's the what are we doing that doesn't already exist - that seems to be where the real challenge is. Maybe there is some kind of way we can figure out how that all fits within the accessibility api, etc
<bkardell_> scotto_: I don't know that we need 1 element for what most people want to do.
<gregwhitworth> ack bkardell_
<Travis> bkardell_: I think maybe scott said what I wanted to say...
<Travis> .. additionally, it gets tricky when we add a new element.
<Travis> .. semantics for the new element? Could be hard... a new level of complexity.
<gregwhitworth> ack masonf
<bkardell_> masonf: The examples of toolbar and grid are interesting
<bkardell_> masonf: they kind of point out that there are different roles
<keithamus> q+
<Travis> q+
<dbaron> Chair: gregwhitworth, masonf
<bkardell_> keithamus: I see this as part of these larger featuresets - as I understand it things like popover came out of things like selectmenu as a constituent part... I think that focus group is similar, and someday we will just have the vernacular to create those really high level things
<Travis> q-
<bkardell_> keithamus: In the meantime I think we are making these constituent parts that allow the community to rely on them and make cowpaths too...
<bkardell_> keithamus: we should definitely make stuff that is well trodden cow paths, but I think we also have opportunity to resolve whole classes of things that developers didn't even realize before -- like not having to worry about zindex in popover.
<luke> q+
<bkardell_> keithamus: if we can verify that it is worth having that additional element of discoverability, it is worth trying and prototyping. I wish that I had the scope/sway/bandwidth to explore that
<masonf> ack keith
<masonf> ack luke
<masonf> q+
<bkardell_> luke: the question is: Do we want it to be you have to add tabindex=-1 to opt out, vs having to add tabindex=0 to opt in? I think it would be interesting to see, like looking at existing patterns in design systems, like we do with others.Maybe the fact that no one is doing it suggests it should be opt in, but keith has a point that maybe no one is doing it for not great reasons too
<scotto_> q+
<bkardell_> luke: I think the memory feature as a whole might even warrant opt in vs opt out
<bkardell_> masonf: I think mechanically you can't make it opt out. It feels too funny to disregard tabindex=0.
<bkardell_> masonf: the entire point of focusing the group itself is just to provide a way to annouce that there is special keyhandling here?
<bkardell_> keithamus: If you wanated things to only be accessible via arrow keys, you'll have to do something like roving tabindex or something
<bkardell_> masonf: I can see where you have tabindex=-1 and the fact that they are in a focus group just handles all of that and so on
<bkardell_> Travis: that is actually the current proposal for memory
<bkardell_> masonf: so what is the real advantage of focusing the group
<bkardell_> q+
<bkardell_> masonf: for AT users I would think there are affordances where they can know that from the inside
<masonf> ack mason
<masonf> ack scott
<bkardell_> masonf: for AT users I would think there are affordances where they can know that from the inside...
<bkardell_> Travis: I think the memory thing would be that particular hook
<bkardell_> scotto_: you're absolutely right mason - this isn't something that has to be an element. By mere fact that the first grid cell is focused, each AT has provided their own hints that people can turn on or off
<bkardell_> q-
<Travis> q+
<masonf> q+
<bkardell_> scotto_: the thing that I am most concerned with are the patterns where there _are_ no known expectations. There's a lot more thought that would have to go into this to make ways to provide this information to ATs to communicate it effectively
<masonf> q-
<bkardell_> scotto_: it's very easy for the patterns that already exist - it's the unknown ones that you can totally create today where a focus group contains a button and a select and the select has it's own focus group and so on. What do you do with that?
<bkardell_> Travis: please comment on issue 995
<bkardell_> Travis: someone suggested a use case I forgot about for why turning off memory is necessary
<bkardell_> scotto_: yes I forgot - a menu of regular menu items, it typically doesn't remember. If you are in a big grid, you absolutely need to remember. There's definitely both use cases for and against memory
<masonf> q?
<masonf> ack travis
<bkardell_> Travis: yes, you made my point very well. Thank you
<bkardell_> Travis: An immediate change I would like to make to the feature: It's limited to immediate children. I think there is wide agreement that we can change that to all descendants. It makes it much easier to use - that's one change, and it has a cascade of other changes that need to be made to support it. An opt out seems even more important then. And we can get rid of features for extending, because you won't need that
<bkardell_> Travis: that simplifies the spec quite a bit. There's one exception - i would propose to allow continuing ...? something
<luke> +1
<bkardell_> Travis: any objections to me making those changes?
<bkardell_> Travis: if you want to comment on home/end keys that's issue 543

css-meeting-bot avatar Feb 29 '24 20:02 css-meeting-bot

PR #1021 has landed and includes the changes for an "entrance-memory" as described above. That PR is a major re-write, so might be worth reading the explainer again top-to-bottom. Note, it also includes definition of a memory opt-out via no-memory or focus-group-memory: none.

travisleithead avatar Mar 28 '24 23:03 travisleithead