openui / open-ui

Maintain an open standard for UI and promote its adherence and adoption.
https://open-ui.org
Other
3.5k stars 186 forks source link

[select] `<selectedoption for=id>` as an alternative to split buttons and `<button type=popover>` #1063

Open josepharhar opened 2 months ago

josepharhar commented 2 months ago

Our latest idea is that in order to support "split buttons" where one button has the <selectedoption> and does something author defined and another button actually opens the popover, we support slotting multiple <button>s inside a <select> into the in-page portion and signify which button opens the popover with <button type=popover>.

Instead of doing this, we could make <selectedoption> capable of living outside of the <select> and link them together by supporting the existing for attribute on <selectedoption>. This has some benefits:

  1. Removes the restriction of only using <selectedoption> inside a <button>.
  2. Removes the <button type=popover> attribute and complicated algorithms to figure out which button(s) open the popover, which I am still trying to figure out how to implement.
  3. Might make accessibility mapping and other things easier since only one button is allowed inside the select @scottaohara
  4. Might make select changes easier to standardize since I don't have to add a type=popover attribute.

Current way of making a split button:

<select>
  <button>i submit a form or something <selectedoption></selectedoption></button>
  <button type=popover>open dropdown</button>
  ...
</select>

What I am proposing:

<button>i submit a form or something <selectedoption for=myselect></selectedoption></button>
<select id=myselect>
  <button>open dropdown</button>
</select>

In cases where the authors want the layout boxes of the two buttons to be siblings, they can put display:contents on the <select>. I think this also might be worth doing by default in the UA stylesheet.

scottaohara commented 2 months ago

thanks for raising this joey as this is exactly the direction i was hoping for when i proposed the idea in the discussions we've been having about select.

if selectedoption can be associated with a select declaratively, then authors can get that value pulled into their own button that they can script to do whatever it needs to do - without having to put it inside the select itself.

it also makes it a lot easier for browsers to implement, as the select's mappings don't need to potentially be variable to account for extra content presented in the page along with the select's button part for invoking the popup - it also then means that a browser is off the hook for having to determine "is this a split button, and if so, do keyboard behavior as a single tab stop - or is this not a split button and just happens to be two buttons in this select container, and thus two separate tab stops would be expected... etc."

this direction simplifies a lot, and is not an unreasonable expectation to put on developers - particularly since developers that were making well supported accessible split buttons (and other composite custom controls) would likely be already following this sort of practice of having the controls be siblings, rather than nested, anyway.

josepharhar commented 2 months ago

One more thing I forgot to clarify - if you put a <selectedoption> inside a <select>, then the association will be set up automatically without the need for the for attribute, so this will still work:

<select>
  <button>
    <selectedoption></selectedoption>
  </button>
  ...
</select>
css-meeting-bot commented 2 months ago

The Open UI Community Group just discussed [select] `<selectedoption for=id>` as an alternative to split buttons and `<button type=popover>`, and agreed to the following:

The full IRC log of that discussion <gregwhitworth> jarhar: I mentioned this idea that I wrote about some a11y stuff
<gregwhitworth> jarhar: the idea is that we have support for split button and it will slot in numerous items and if it has type=popover is that it will denote which one toggles the popover
<masonf> q+
<gregwhitworth> jarhar: the idea that I see is where you have a button that opens the select within another button
<gregwhitworth> jarhar: the selectedoption element just looks up its ancestor tree to find out where to get its selected option from
<gregwhitworth> jarhar: if we have a for attribute we can have the selectedoption element get its content from somewhere else
<gregwhitworth> jarhar: you can then have the two buttons and it provides the improvements in the implementation and we don't have a new button type attribute and when you want to put the selectedoption elsewhere
<gregwhitworth> masonf: I love the idea
<gregwhitworth> masonf: split buttons are a real thing that we need to support
<gregwhitworth> masonf: I like not having two buttons that are magical
<bkardell_> yeah that was my immediate thought too
<gregwhitworth> masonf: one comment I would make, actually from Anne, one tweak is rather than having an attribute that is on select that gets the selectedoption element
<scotto6> q+
<gregwhitworth> masonf: it avoids having numerous elements around the document
<gregwhitworth> ack masonf
<jarhar> q?
<gregwhitworth> masonf: it gets it so that implementation is easier to look it up due to referring in the other direction
<gregwhitworth> scotto: I was going to thank jarhar for writing this up and the reversal makes a lot of sense so thank you for the idea Anne
<gregwhitworth> ack scotto
<masonf> q+
<gregwhitworth> jarhar: I still kind of like it being on selectedoption having for
<scotto6> q+
<gregwhitworth> jarhar: I think that updating multiple other selectedoption elements wouldn't be too complicated versus one
<gregwhitworth> jarhar: I like the idea being able to quickly looking it up on the select but in general I'm happy with either of these verses our current approach
<gregwhitworth> jarhar: do you have any idea of what the attribute on the select would be called?
<gregwhitworth> ack masonf
<gregwhitworth> masonf: naming wise, I think we should pick a bad name and people will change it to something good :)
<gregwhitworth> masonf: one question I was on the queue to ask is about usecases
<gregwhitworth> masonf: in the inverted case you only have one selectedoption you can refer to but do you only allow just those two?
<jarhar> q?
<gregwhitworth> jarhar: if we do an inverted style where you can only specify one then you shouldn't support any selectedoption that are inside of the select or else we'll end up with a list of them that we'll have to clone stuff into
<gregwhitworth> masonf: to make it easier to comment on, my proposal would be to support both but it would just be two
<gregwhitworth> scotto: the only thing I was going to say, for the labele element on a form control... could it not be that there are multiple selected options in the DOM that the browser can be "no more after that"
<gregwhitworth> scotto: the browser could treat it that way but it won't render it all over the place and stops cloning after that except for inside of the select element
<gregwhitworth> q+
<gregwhitworth> ack scotto
<gregwhitworth> scotto: for the label for it can only have one id it won't label every single one that has that ID it will only label the first one
<gregwhitworth> mfreed: if you have two labels with one control does that still work?
<gregwhitworth> scotto: you have to concat them together to make the acc name
<gregwhitworth> scotto: it wouldn't be cloning them into separate options.
<masonf> q+
<gregwhitworth> ack gregwhitworth
<gregwhitworth> masonf: my only comment was to scotto thing. We're moving towards agreement of at max two, one outside and one inside
<jarhar> q+
<gregwhitworth> masonf: it seems a bit funny to support <n> selectedoptions but the first one works where the other way around there is only one and I think it feels cleaner
<gregwhitworth> ack masonf
<gregwhitworth> jarhar:
<gregwhitworth> jarhar: I thought of another reason that the inversion thing is good is that we can incrementally introduce this on other elements
<jarhar> proposed resolution: add the selectedoption attribute to the select element which is an idref to a selectedoption element which lives outside of the select element as a replacement for multiple buttons in select and type=popover
<gregwhitworth> jarhar: if we want to have an input with a selected option and could be feature detected on IDL
<masonf> Proposed resolution: add an attribute called `myselectedoptionelementis=foo` to select, which can point to a single <selectedoption> element to update. The first contained <selectedoption> would also be updated.
<gregwhitworth> masonf: it differs only in that it has a named attribute and outlines that the first child of the selectedoption will be updated
<masonf> Proposed resolution: add an attribute called `selectedoptionelement=foo` to select, which can point to a single <selectedoption> element to update. The first contained <selectedoption> would also be updated.
<jarhar> +1
<bkardell_> lgtm
<dandclark> +1
<keithamus> +1
<scotto6> +1
<dbaron> (I was the code reviewer who told Joey that it was important to explicitly add a test that we *don't* ever ship 'appearance: bikeshed'.)
<masonf> RESOLVED: add an attribute called `selectedoptionelement=foo` to select, which can point to a single <selectedoption> element to update. The first <selectedoption> contained within the <select> would also be updated.
josepharhar commented 1 month ago

I created an explainer PR for this here: https://github.com/openui/open-ui/pull/1071

yisibl commented 1 month ago

Maybe the name would be better changed to selectedoptionfor?