64 points by jaffathecake 5 days ago | 48 comments
gabesullice 1 day ago
If the developer wants a <selectedoption>, they should fill it with <option> elements that correspond to the <option> elements that appear in the dropdown. Each option could reuse the <label for=""> pattern to associate them with their counterpart.
Then, when an option is selected by the end user, the corresponding option inside the <selectedoption> would get a `selected` attribute.
The default CSS would be:
selectedoption > option { display: none; } selectedoption > option[selected] { display: block; }
This gives complete control to the developer, works fine without JS, and wouldn't have shocking side effects.
As they say, "duplication is cheaper than the wrong abstraction".
2freedi 1 day ago
<select name="commenters">
<option value="annevk">Anne van Kesteren</option>
<option value="jakearchibald">
<label>Jake Archibald</label>
<selectedcontent>
<div>
<img src="profile.avif" alt="Jake's photo">
<div>Jake Archibald<br><small>@jakearchibald</small></div>
</div>
</selectedcontent>
</option>
<option value="sorvell">Steve Orvell</option>
</select>
The value attribute would be required when using these new sub elements. This structure feels familiar and progressive to me.Naively, I would imagine that the following JavaScript would cause 1 DOM update, 1 redraw of the option if the dropdown is open, and 1 redraw of the selected option:
document.querySelector('option:selected selectedcontent').innerHTML = 'Jake Archibald';
Obviously, things are different when using multiple. Maybe a `select > selectedcontent` element containing a copy of each `option > selectedcontent` element that is updated on change events.jaffathecake 1 day ago
There are a few different cases worth considering:
# I want to display the option content in the <selectedoption> as is
Great! Use <selectedoption>
# I want to display the option content in the <selectedoption> a little differently (eg, hide the associated <img> or a different font-weight)
In this case, you're probably best off using a little CSS to style the content of <selectedoption> different, eg hide particular elements.
# I want to display something completely different in the <selectedoption>
<selectedoption> is optional, so one thing you can do here is just… not use it, and instead change the content of your <button> in response to state changes. This requires JavaScript.
If you really want to use <selectedoption> for this, then you could do this:
<option>
<div class="option-content">…</div>
<div class="selectedoption-content">…</div>
</option>
Along with the CSS: option .selectedoption-content { display: none }
selectedoption .option-content { display: none }
mminer237 23 hours ago
This shouldn't be a literal new element. It should be a psuedo-element like other component parts like `::-[engine]-slider-thumb` are. You can then style `select::selected-option` and not have to mangle your HTML or worry about mirroring HTML.
jaffathecake 22 hours ago
If you have a psuedo-element, it still needs to get its content from somewhere, and needs to be placed somewhere in the tree. With <selectedoption> you can put it wherever you want in the <button>, but you'd lose that functionality with a pseudo. The same questions remain about when the content of the pseudo gets updated. And now you need to figure out how events work.
mminer237 22 hours ago
You don't need to rearrange the HTML of the "button". You can use ::before, ::after, and general styling to do anything you need to. I'm struggling to see any advantage even if you were okay with using HTML to style pages.
jaffathecake 22 hours ago
That maintains one of the problems I'm worried about. If you have a mouseenter listener on something in an <option> that triggers a fancy animation, you (surely most of the time) don't want that action repeated in the <selectedoption>, because it's the thing in the <option> that was hovered, not the thing in the <selectedoption>.
> You can use ::before, ::after, and general styling to do anything you need to.
You don't need to look at too many web sites to see examples where folks have added divs for styling, because pseudo-elements didn't provide enough style hooks.
mminer237 21 hours ago
lifthrasiir 1 day ago
1. Declarative camp, where people expect two differently stylable copies of `<option>` somewhere in `<select>`. I don't think the exact copying mechanism and timing is very important here, as long as it can be safely done and works without JS.
2. Programmable camp, where people want the full control over appearance and behavior. We can reasonably assume that JS is required for this camp, and they generally have better understanding of what gets rendered or not in the first place.
Given both requirements, it seems wise to couple the clone timing with the event processing, which most cases in the second camp would have to do anyway. In the other words, the `input` event would have the default behavior of full cloning, and that default behavior should be prevented via `e.preventDefault()`. The second camp will almost always use this option and can use their own `MutationObserver` or similar to implement edge cases described in the OP. The timing and extent for the default behavior can be then optimized without affecting the second camp. It is even possible to distinguish two camps via different values of the `appearance` CSS property.
Sidetrack: It seems that `<selectedoption>` indeed exists mainly to distinguish two camps? But that leaves many edge cases like multiple `<selectedoption>` elements I believe. Maybe something like `<select reflect="foo"><button><option id="foo">...</option></button>...</select>` might be more appropriate. (`<output>` was my initial thought, but `<option>` would be more regular since it can't nest.)
jaffathecake 1 day ago
Hm, it feels like, when the selected option is changed via user interaction, the <selectedoption> should be populated before the event fires.
But this is really besides the point, because not all selected-option-changes come with an input event, eg programatic change, including to the content of the currently selected option, which the post focuses on.
> that leaves many edge cases like multiple `<selectedoption>` elements I believe
That isn't really a big problem. It's something the platform already deals with all over the place, like multiple <title> elements, multiple elements with the same ID etc etc.