Skip to content
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

Consider "toggle" (expand/collapse) attribute #700

Open
scottaohara opened this issue Mar 29, 2023 · 47 comments
Open

Consider "toggle" (expand/collapse) attribute #700

scottaohara opened this issue Mar 29, 2023 · 47 comments
Labels
needs edits This is ready for edits to be made

Comments

@scottaohara
Copy link
Collaborator

With the evolution of popover, developers got the ability to use a button to toggle the displaying of a popover element in the top layer without the need for JavaScript.

What HTML is still lacking though is a way to use a button to toggle the display of elements that don't get rendered in the top layer. The best way to do that now is to use a standard button element with an aria-expanded set to true/false. In the grand scheme of things, the JS needed for this is rather trivial... but the fact that any JS and ARIA are needed means that people will try to work around those requirements, or have the potential to implement them incorrectly.

Now yes, we have the details and summary elements to make native disclosure widgets - but these have some oddities, to put it politely, and there is no room for leniency with their placement in the DOM. The triggering summary element MUST be a child of the details, which awkwardness of the current elements aside, this required parent/child relationship can be a deal breaker for consideration. E.g., a button to toggle a hidden navigation appears as the first element in a header, but the revealed navigation is positioned after the header in the DOM. Even if details/summary had no other issues with it, the mentioned layout would make their use a no-go.

And just because I don't think I could make this issue without mentioning it, yes, there's also the CSS toggles proposal. I would expect some learning / ideas from that to be relevant here. Though I would submit what I'm proposing here is much smaller in scope, with far less "let the browser figure out what sort of toggle this is and provide the correct keyboard behaviors and hope to god that developers didn't muck something up that we didn't consider". And more just "let's make a button show/hide a specified target element, and expose an expanded/collapsed state for the button while we're doing it" which is exactly what we have with buttons that toggle popovers... just again, minus the top layer part, please.

@hidde
Copy link
Contributor

hidde commented Apr 3, 2023

I support this idea!

The comparison with details/summary is helpful, and it makes sense to want something without its oddities (like DOM placement).

In terms of accessibility API, is the only thing it would do manage expanded/collapsed state? Would it also convey some kind of aria-controls relationship (even if zero AT seem to expose that relationship in any way?)?

@NeilWix
Copy link

NeilWix commented Apr 4, 2023 via email

@scottaohara
Copy link
Collaborator Author

@hidde likely not aria-controls, but similar to how popovertarget is shaping up to work, which has an aria-details relationship.

@NeilWix I think you misunderstood the proposal, as there was no mention of adding a semantically neutral component, and as the proposal was actually for either extending button element behaviors, or adding a new type of button, your mention of the intuitiveness of keyboard behavior is puzzling.

@bkardell
Copy link
Collaborator

bkardell commented Apr 4, 2023

Is this also related to #333 ? Just linking it up so we can keep track of them and hopefully close things as they get irrelevant, or look back and see what we said in the past.

@scottaohara
Copy link
Collaborator Author

@bkardell anything that is proposed for showing/hiding content will always be related to each other :)

but outside of that, no. this is not a tabs or menu or treeview proposal. this is just for adding expand/collapse capabilities and programmatic state to buttons - e.g., what has already been done with popovertarget, but without promoting the target to the toplayer.

@brechtDR
Copy link
Collaborator

Could really be beneficial to have something like this.

A side question i have about this, is that if would beneficial to have this state exposed to CSS as well? Reason for this is that; for example, when I style collapsed items with aria-expanded I tend to use this attribute in CSS as well

button[aria-expanded="true"] {
/* rotate the icon or something like that */
}

Why I do this, is to prevent people forgetting it... "forgot aria, you don't get the styling".

In the popover case, it could also be used to give the button a certain visual state based on that. Although less important because (If I'm interpreting your suggestion correctly) it would be automated "behind the scenes, without JS". Still, I thought I might mention this side question.

+1 for the idea in general

@jimmyfrasche
Copy link

I don't know how often I'd need this in a future world where more stuff from this group has shipped but I can say I have probably implemented various toggle buttons more than anything else, as they are very often a necessary piece of anything larger I need. It would certainly be nice to have one that just works and handles all the appropriate aria natively. Even if it becomes useful over time as more powerful things get built into the platform I imagine it would still come up.

@scottaohara
Copy link
Collaborator Author

scottaohara commented Apr 26, 2023

well, all the appropriate aria (accessibility mappings) in this case would be purposefully limited to more straight forward disclosure widgets (largely just exposing an expanded/collapsed state for the button. providing other meaningful semantics - details relationship - when the invoked content is not next to its invoking button in the DOM).

other potential components that could come from this group, e.g., making a standardized proposal for tabs, menus, treeitems, etc. those would - at their core - still show/hide content, but they'd communicate very different semantics and have different keyboard functionalities.

so, hence this proposal. start with the most basic / common component needed to show/hide content. and then create other components that are suited for their task thereafter.

@una
Copy link
Collaborator

una commented Apr 27, 2023

I would love for the feature to exist, with aria-expanded under the hood, and I think it would solve a lot of the use cases we want toggles for without added scripting.

Could we leverage something like CSS container queries (state queries) for this, i.e. is-toggled to style it?

@scottaohara
Copy link
Collaborator Author

@una i think that's an implementation detail i'd really like to hear more about from what has been investigated with CSS toggles, as I personally don't see any reason why not, so long as whatever the current visible state of the associated content (hidden or not) could be communicated back to the button element, so that it could correctly expose the expanded/collapsed state.

maybe we can discuss this more in next week's call, especially if david ends up being able to provide an update on the state/fate of css toggles.

@dbaron
Copy link
Collaborator

dbaron commented Apr 28, 2023

One thing that's not clear to me (and might differ depending on the details of this proposal, what hooks into CSS and JS it eventually has, etc.) is how easy it would be to mis-use what this is proposing to build components (for example, tabs) for which it would have the wrong accessibility semantics. In other words, depending on details, this might end up being a primitive that developers would want to use for a big portion of the things that toggle could be used for -- and if that's the case, that might run into cases where the accessibility roles and keyboard handling are wrong.

Or, to put it another way, it seems in some ways like a much lighter weight version of CSS toggles (again, perhaps depending on what the CSS and JS integration looks like)... and might end up sharing both some of the advantages and some of the disadvantages.

@jimmyfrasche
Copy link

What if the natural way to think about this is backwards and there needs to be an attribute like popover but for the sections that expands/collapses and a button with an expandstarget gets aria-expanded based on the target's state?

So something like

<button expandstarget=it>toggle</button>
<div id=it expands open>
  this is open until the button gets clicked
</div>

A closed [expands] element should open when the button is pressed, search in page finds a match (with a way to opt out), and the location.hash matches the id (with a way to opt out). When closed it should be inert and the default styles would be like [hidden] so you could easily override them to do something fancier.

@jimmyfrasche
Copy link

The downside of that specific outline is there's no way to force it open in a container size query unless you can set inert in CSS (which I was 👍 on anyway). It would work for @media (print) though since it doesn't matter if that's inert, I suppose

@lukewarlow
Copy link
Collaborator

If we go on the basis that this would utiltise the invokerbutton proposals. I guess the question is what would the action be and would we need any additional attributes to define the expandability?

Or does the ability to invoke the details externally effectively solve this?

@scottaohara
Copy link
Collaborator Author

to be honest, when i logged this issue/idea, the intent wasn't really that people would use this with details - that already exists and i struggle to see the value in having a control to toggle a details separate from a details - since there's already a summary element either manually added or automatically generated as the first child of the details to do that.

a details element by itself has no meaningful semantics exposed to AT that isn't reliant on the summary element, or extra effort to expose such semantics by a developer (nor should it, lest that be considered a bug). And i mention this (at a high level, i'm leaving out some details - ha) simply to the point that if someone were going to create a button that could toggle a div/article/fieldset/list/whatever, then there's no reason to even need to get details involved and wrangle with changing its current behavior/potential legacy browser issues with any sort of polyfill.

This comment has been minimized.

@github-actions github-actions bot added the stale label Mar 20, 2024
@bkardell
Copy link
Collaborator

We still dig this idea, it's not stale <3

@github-actions github-actions bot removed the stale label Mar 22, 2024
@mayank99
Copy link

Echoing some of the earlier comments but with the added foresight of invokers, I think this could be handled with a new attribute like disclosure. Example:

<button invoketarget="more">Show more</button>
<div disclosure id="more">… (more stuff here) …</div>

Similar to popover, this would toggle the visibility, and implicitly set aria-expanded and whatever else is necessary.

I specifically like how low-level it is and how little "API" there is, which makes it easy to use for simple cases while still being flexible enough to support more complex ones. Big improvement over <details> and/or JS-driven disclosures imo.

@scottaohara scottaohara changed the title Consider toggle (expand/collapse) button or attribute Consider "toggle" (e.g., show/hide - expand/collapse) button or attribute May 30, 2024
@lukewarlow
Copy link
Collaborator

I agree that using the content-visibility: hidden and hidden until-found mechanism (probably implicitly like details does) is probably better than toggling display.

I guess it does beg the question is there a use case where you don't want the contents to be searchable (aka the old details behaviour)? If so we could make the new attribute be an enum so it can be configured.

I know tabs are one case where you sometimes don't want it to be searchable. But I would rather we address that specific case separately with dedicated tab elements.

@mayank99
Copy link

mayank99 commented Jan 5, 2025

If this is meant to be a low-level disclosure primitive, then it shouldn't mess with the searchability.

Today, the contents of <details> being exposed to find-in-page (in certain browsers) greatly limits the usefulness of the element. It's handy for a certain type of use-case (e.g. an FAQ page), but is largely undesirable when building complex dynamic applications, where disclosures are used throughout the interface to reduce visual clutter. When the end user searches for something on the page, I don't want them to unintentionally open random disclosures all over the place.

That's not to say it should not be possible; it should just be explicit (rather than implicit like in <details>). Maybe the new disclosure attribute could be combined with hidden=until-found? This would allow for both behaviors, while avoiding any surprises.

<button commandfor="more">Show more</button>
<div id="more" disclosure hidden="until-found">… (more stuff here) …</div>

Side note: content-visibility: hidden does not preserve searchability (The web.dev article might be misleading on this topic). Afaict, the hidden=until-found behavior is unique to the attribute and does not have a proper CSS equivalent.

@scottaohara
Copy link
Collaborator Author

IMO, i'd much rather someone opt into hidden until found than have that be the default.

sub-navigations, custom menus, sidebars / toggle tips that are meant to only be toggled via a button - there's a lot of content in many websites / complex web apps beyond just tab widgets that would be silly to find their content if doing a find in page. i'd submit there's probably more of these in a page than one realizes, which would make it rather annoying to have to undo a default hidden until found for so many items.

that said, i can see the use case for wanting to pair this with hidden=until-found, so that sounds reasonable to allow that attribute/state to take precedent over, what i'd prefer, a default display none

and regarding content-visibility: hidden - definitely don't want that. i've had to deal with devs using that lately and making their apps incredibly difficult for people to navigate with a screen reader.

@EllyLoel
Copy link

EllyLoel commented Jan 6, 2025

I think I mostly agree, though if I were to play devil's advocate for a moment.

Today, the contents of <details> being exposed to find-in-page (in certain browsers) greatly limits the usefulness of the element.

There are other more problematic issues limiting <details> usage/adoption, @scottaohara touched on them when he initially opened this issue and detailed them further in his great blog post.

It's handy for a certain type of use-case (e.g. an FAQ page), but is largely undesirable when building complex dynamic applications, where disclosures are used throughout the interface to reduce visual clutter.

When the end user searches for something on the page, I don't want them to unintentionally open random disclosures all over the place.

sub-navigations, custom menus, sidebars / toggle tips that are meant to only be toggled via a button - there's a lot of content in many websites / complex web apps beyond just tab widgets that would be silly to find their content if doing a find in page.

I don't think these are the best examples to base our reasoning/decision making on. As someone with AuDHD and Dyslexia1 find-in-page is very important for me to be able to navigate web pages2, without it I have to read everything which leaves me overloaded, overwhelmed, and running low on spoons.

Sub-navigations, custom menus, sidebars / toggle tips, random disclosures, and other parts of dynamic applications are actually perfect examples of why I struggle so much when relying on find-in-page currently. These are situations where I really want find-in-page to work so I don't have to manually open every little disclosure.

That's not to say it should not be possible; it should just be explicit (rather than implicit like in <details>).

IMO, i'd much rather someone opt into hidden until found than have that be the default.

I think making it an option to enable or disable find-in-page and fragment navigation is a great idea. I think the more accessible/usable option should be the default. In my mind than means it should be enabled by default but I'd like to hear other arguments.


Side note: content-visibility: hidden does not preserve searchability (The web.dev article might be misleading on this topic). Afaict, the hidden=until-found behavior is unique to the attribute and does not have a proper CSS equivalent.

and regarding content-visibility: hidden - definitely don't want that. i've had to deal with devs using that lately and making their apps incredibly difficult for people to navigate with a screen reader.

Yikes! I think I got confused because a lot of the documentation3 about hidden=until-found4 it mentions the fact that content-visibility: hidden is used instead of display: none right along side talking about find-in-page and fragment navigation working, which makes it seem like that is what provides/enables the functionality. Thanks for catching my mistake!

Footnotes

  1. I mention these three as I feel they're the most pertinent, though there are others that are pertinent I don't want to over complicate things.

  2. I'd recommend checking out 4.3.6 Provide Search (Pattern) from Making Content Usable for People with Cognitive and Learning Disabilities to learn more.

  3. "The hidden until found state" section in the MDN article, the "The hidden attribute" section in the HTML spec, and—as was already mentioned—the "Caveats" section in the web.dev article

  4. and probably <details> too.

@lukewarlow
Copy link
Collaborator

Yikes! I think I got confused because a lot of the documentation3 about hidden=until-found4 it mentions the fact that content-visibility: hidden is used instead of display: none right along side talking about find-in-page and fragment navigation working, which makes it seem like that is what provides/enables the functionality. Thanks for catching my mistake!

Fwiw you weren't wrong content-visibility is the CSS property that enables hidden until-found. I think Scott is basically just saying we need to be careful and only use that where it makes sense (such as how details does now).

I'm happy to defer to others on whether we want contents to be searchable by default. I like you generally prefer things to expand when searched, but I can absolutely see that there's use cases where it's not desirable. On that basis provided there's a way to cater to both cases I'm happy.

@lukewarlow lukewarlow added the agenda+ Use this label if you'd like the topic to be added to the meeting agenda label Jan 6, 2025
@lukewarlow
Copy link
Collaborator

Adding to agenda to discuss in more detail and try and get the ball rolling because this feels like a useful addition and something we should be able to gain consensus on. Especially because there's clearly use cases that aren't overlapped with details.

Some questions to think about:

  1. (Discussion above) should find in page work when closed.

  2. Would this new attribute enforce / require a specific set of aria roles. Popover for example enforces a minimum of group. I'm guessing this new 'bruce' attribute probably shouldn't prescribe a specific role (beyond perhaps a minimum) because of the wide variety of use cases.

  3. Obviously this can (and will) be bikesheded to oblivion, but what name for the attribute? I'd like something such as expand or expandable. Disclosure feels too specific about a single use case to me.

  4. What should the commands for this be? (Again bikeshedding I know) expand, collapse and toggle-expansion?

4a. What should the equivalent JS APIs be called?

  1. Should this match the :open pseudo class or should it be something else?

  2. Are there any elements where this attribute shouldn't be valid? (E.g. details seems a candidate and maybe dialog?)

  3. Do we need to handle an initially open state? If so how?

@scottaohara
Copy link
Collaborator Author

i'm going to walk back a couple of my concerns with the find in page, since the things i'd be most concerned being exposed by find in page are UI elements which should be built using popover, and likely not this feature. so popup menus, tooltips / other popups that would clutter the UI / potentially block what people were searching for, and which wouldn't make sense to find for those who purposefully didn't want to find out more information about something they weren't searching for wouldn't be impacted.

so i'm less concerned about it being a potential default - though i think it really should be a user setting in the end. it absolutely can be helpful for some, and incredibly annoying if it just clutters the find in page functionality for others.

using this page as an example, the context menus that go along with each comment have an item for "report content" in each. There are about 27 comments in this thread now. Also, we've been talking about "content", and that word has been used 24 times in comments. So, in the hypothetical situation where github revised their menu popups to use this proposed feature, rather than popover - and the feature defaulted to hidden until-found, searching for the word "content" would get about 61 hits, and about half those hits would be repeat "report content" menu items.

anyway...

to some of luke's questions (no opinions on naming at this time because i hate that game)

(Discussion above) should find in page work when closed.

maybe! some people will want it, others won't. it'd be best to support both somehow.

Would this new attribute enforce / require a specific set of aria roles.

IMO, probably similar.

Should this match the :open pseudo class or should it be something else?

i'd hate to not be consistent, so i'd tentatively say :open instead of ":open-but-named-something-else"

Are there any elements where this attribute shouldn't be valid? (E.g. details seems a candidate and maybe dialog?)

we don't want yet another way to open non-modal dialogs? ;)
no but seriously - popover is a global attribute, imo, not because it actually makes sense to use on all elements, most global attributes don't make sense to use on all elements... i could see this falling into a similar space. does this proposed attribute belong on a dialog, meta, html, b or style element? no more so than tabindex or title or draggable...

Do we need to handle an initially open state? If so how?

yeah, i'd think so, since people can use open now with details - and can setup their custom disclosure widgets to have a class, or use an aria-expanded=false + .my-whatever { display: none } ruleset and thus anything set to aria-expanded=true would have a default open state.

@jimmyfrasche
Copy link

I don't know whether find in page should be opt in or opt out but it should be an option, like bikeshed vs. bikeshed=whichever-is-not-the-default.

👍 for supporting open, matching :open, supporting the toggle event, and anything else that makes sense to copy. Don't see a reason to not default to being consistent here. There should not be a lot of new things to learn here. There's good precedent to lean on.

@mayank99
Copy link

mayank99 commented Jan 6, 2025

[…] the things i'd be most concerned being exposed by find in page are UI elements which should be built using popover, and likely not this feature. so popup menus, tooltips / other popups that would clutter the UI / potentially block what people were searching for, and which wouldn't make sense to find for those who purposefully didn't want to find out more information about something they weren't searching for wouldn't be impacted.

[…] So, in the hypothetical situation where github revised their menu popups to use this proposed feature, rather than popover - and the feature defaulted to hidden until-found, searching for the word "content" would get about 61 hits, and about half those hits would be repeat "report content" menu items.

I mentioned earlier that I consider this new attribute to be a low-level disclosure primitive. So popover can be thought of as a subset of this feature and therefore I think that hypothetical situation should be supported properly (even if it would be more appropriate to use popover to build out those patterns).

Conversely, it would be nice to also allow the popover content to be exposed to find-in-page. Many toggletips and tooltips built using popover today likely contain additional and unique information that would be useful to be searchable.

With these considerations in mind, I would say both the new disclosure attribute and the existing popover attribute should allow opting in (rather than opting out) of find-in-page functionality. As for the actual opt-in mechanism, I think reusing hidden="until-found" makes sense, avoiding the addition of another new API.

@jimmyfrasche
Copy link

if you set hidden=until-found and the do a search that reveals the element the browser removes [hidden] and if you press the button again it gets closed but doesn't add [hidden] back unless it's supposed to remember that that was there. I think it would have to be a keyword on the attribute that makes it expandable so it can continue to operate correctly regardless of the sequence of operations in a way that's easy to reason about.

@lukewarlow
Copy link
Collaborator

lukewarlow commented Jan 6, 2025

👍 for supporting open

Fwiw I wouldn't be supportive of involving the existing open attribute with this new thing. It's a design mistake in HTML that dialog and details mutate their own attributes for state. But an initiallyopen attribute that isn't reactive would make sense.

if you set hidden=until-found and the do a search that reveals the element the browser removes [hidden] and if you press the button again it gets closed but doesn't add [hidden] back unless it's supposed to remember that that was there. I think it would have to be a keyword on the attribute that makes it expandable so it can continue to operate correctly regardless of the sequence of operations in a way that's easy to reason about.

While this is true I imagine we can special case the behaviour with this new attribute such that it doesn't get removed and just gets overriden when open. (Not saying that's good or bad but it's probably possible)

@jimmyfrasche
Copy link

It's a design mistake in HTML that dialog and details mutate their own attributes for state. But an initiallyopen attribute that isn't reactive would make sense.

I've thought about this and, while I agree that open was a mistake, this seems like a bigger one. I'd rather have three similar things that all work the same way than two things that work one way and one that works differently. If there's some way to change them all to use initiallyopen and deprecate open then, fine, handle them all at once. Until then it's worth making the same minor mistake again to avoid introducing differences that make things harder to learn and remember.

@lukewarlow
Copy link
Collaborator

I personally still lean towards not reflecting the state via an attribute though. While dialog and details are examples of state reflection (in fact they're the only cases afaik). Popover and select elements are examples of things that open, that don't do that. Popover being newer than details and dialog, and being a similar mixin attribute design.

It's one thing an element mutating its attributes. But it being another attribute doing it feels extra weird.

But yes you raise a valid argument.
I'm sure there's going to be people on both sides, so it's good to get them down here and discussed in the meetings.

@jimmyfrasche
Copy link

that seems fine since popover and select can't be opened by default but dialog, details and this can so they need an attribute to allow that and then it gets reflected to keep everything in sync. I'll also note that adding hidden=until-found back would be the same sort of thing.

@mfreed7
Copy link
Collaborator

mfreed7 commented Jan 9, 2025

I personally still lean towards not reflecting the state via an attribute though

I need to review this issue in more detail, and I'm looking forward to the discussion today, but I want to +100 this statement. We cannot add new things that mutate their own attributes to reflect state. CSS is the right place to reflect current state, as pseudo classes. I'm in favor of deprecating things that have an open attribute, especially now that we have :open.

@mayank99
Copy link

mayank99 commented Jan 9, 2025

Just adding a note that the attribute name, unlike property name, does not need to be indicative of whether the state is reflected.

As an example, <input> has a value attribute which does not reflect the current value. In JavaScript, the value property does reflect but there is also a defaultValue property, which is more similar to the value attribute in HTML. (Similar deal with checked/defaultChecked in <input type="checkbox">)

@mfreed7
Copy link
Collaborator

mfreed7 commented Jan 9, 2025

Just adding a note that the attribute name, unlike property name, does not need to be indicative of whether the state is reflected.

As an example, <input> has a value attribute which does not reflect the current value. In JavaScript, the value property does reflect but there is also a defaultValue property, which is more similar to the value attribute in HTML. (Similar deal with checked/defaultChecked in <input type="checkbox">)

I think these particular two examples are precisely the reason the name should indicate whether it's state-reflecting. Both of these are quite confusing. If we want an attribute to indicate initial state only, the name should include the prefix "initial" or "default". E.g. we proposed adding initiallyopen for popover, though that discussion is still open. See #500 for a bit of that discussion.

@lukewarlow
Copy link
Collaborator

As for initially vs defaut I was initially concerned about a different prefix but I think in this case there is an actual difference in behaviour. value / defaultValue isn't just its initial value it's also the value that it gets reset to when a form reset happens, same with checked / defaultChecked and selected / defaultSelected.

Where as initiallyopen really is just its initial state, there's no "reset" for a details/dialog/bruce-mcbikeshed.

I would personally love it if we could fix all these legacy ones so that the attribute matched the property (and that they matched the pseudo class too because currrently a selected option matches :checked but that's a whole other can of worms).

Having said that I don't know if it's plausible for us to change even details and dialog at this point.

@mayank99
Copy link

mayank99 commented Jan 9, 2025

I think these particular two examples are precisely the reason the name should indicate whether it's state-reflecting. Both of these are quite confusing. If we want an attribute to indicate initial state only, the name should include the prefix "initial" or "default". E.g. we proposed adding initiallyopen for popover, though that discussion is still open. See #500 for a bit of that discussion.

Ah, thanks for linking to that discussion. I wasn't aware that <input value> is, lets say, frowned upon 😅. I generally try to align with existing conventions.

As for initially vs defaut I was initially concerned about a different prefix but I think in this case there is an actual difference in behaviour. value / defaultValue isn't just its initial value it's also the value that it gets reset to when a form reset happens, same with checked / defaultChecked and selected / defaultSelected.

Where as initiallyopen really is just its initial state, there's no "reset" for a details/dialog/bruce-mcbikeshed.

I don't see why the form reset behavior of form controls would affect the naming for unrelated popover/disclosure attributes. It looks like the resolution from #500 is to use defaultopen. But this is very much getting into bikeshed territory, which I'm not sure is the best use of our time here.

I was mainly trying to point out that based on precedent the name does not need to be indicative of whether it reflects the state. With the added information, I'm in favor of using defaultOpen/initiallyOpen as the attribute name and I agree that it is less confusing and more intuitive.

@flackr
Copy link

flackr commented Jan 9, 2025

My personal feeling is that no HTML attributes should be live. The HTML is what the author provided, and any state updates happen as internal state reflected in IDL. I think adding "initially" to everything is additional characters that developers have to write for something that is not providing value since in general the HTML attribute value should only be changed by explicit mutation to the HTML. I know there are a couple properties where we haven't done this but perhaps we could consider those to be the exception rather than the rule requiring adding initially to new property names?

@jimmyfrasche
Copy link

I'm all for deprecating open. If open was deprecated before this was brought up, that's one thing.

Until it is deprecated, this should support it and it can be deprecated with the other uses so that everything acts uniformly at all points in time. This isn't about what's best locally but about what's best globally.

@css-meeting-bot
Copy link

The Open UI Community Group just discussed Consider "toggle" (e.g., show/hide - expand/collapse) button or attribute , and agreed to the following:

  • RESOLVED: Add a global attribute called `openable` that opts an element into matching `:open`, adds JS methods like .open(), .close(), and .toggle(), and connects to command/commandfor. All names subject to bikeshedding.
The full IRC log of that discussion <jarhar> lwarlow: there are many things on the web that show and hide the content in them. currently theres not necessarily a great way of implementing that without javascript but also like to implement it nicely, can be difficult
<jarhar> lwarlow: the details element, which is perfect in some situations, but its got some rough edges to it, and it also just isnt the correct solution in all cases
<jarhar> lwarlow: even with the new styling stuff, which is great, its still problematic for certain things
<masonf> q+
<jarhar> lwarlow: it would be nice if we had some sort of thing that could do that in a more generic way
<jarhar> lwarlow: comand invokers could be the summary equivalent thing which is a button that triggers this
<jarhar> lwarlow: i put a comment with some questions
<jarhar> lwarlow: i dont have answers to all of these, but thats the gist of it
<jarhar> lwarlow: the latest proposal is to have an attriubute called bruce. that would turn the elemnt into a showy hidy thing
<jarhar> lwarlow: some questions: would this add js apis? yes, like popover does
<jarhar> lwarlow: what theyre called, we can decide, but expand collapse and toggle sort of thing
<jarhar> lwarlow: theres questions about which pseudo classes it should match. i think :open is correct, maybe not
<jarhar> lwarlow: aria roles and states and stuff
<gregwhitworth> ack masonf
<jarhar> masonf: the question i wanted to ask - i see the point, the shape seems ok, but i think where we should start or make sure we've discussed first: why isn't summary details the answer? i know theres issues with it, but like fundamentally summary details is a button that opens and closes regions of content, it meets everything you just said i think.
<jarhar> is it possible that we fix whatevers missing? or are there fundamental things it cant do?
<scott> q+
<gregwhitworth> q+
<gregwhitworth> ack scott
<jarhar> scott: i look at details summary and i dont think its really the solution for imagine a static navigation. im thinking like small viewport, you have a list of links, but some of those links have a button next to them to expand and collapse some navigation. not a popup, but some navigation within that.
<jarhar> scott: i wouldnt think of that as a details summary semantically where theres a legend or label for contents, those are often just a down chevron, a single button that should be able to open and close things
<jarhar> scott: thats one of the use cases. theres others, but another one that i would point to: weve been talking about accessibility issues with details. in some browsers its mapped to a button and in gecko its a summary role, but thats not an aria thing
<jarhar> scott: if more browsers mimicked that, then that role doesn't have the presentational children of buttons
<jarhar> scott: it kind of mitigates the whole you can't put interactive content inside of a button
<jarhar> scott: there are use cases for that, and then theres use cases for buttons that open and close things
<jarhar> scott: i think thats how id summarize it - its semantically a bit different
<lwarlow> q?
<jarhar> masonf: i get that point. maybe we should be adding more behaviors to other elements that can do this? i wonder if this disclosure thing is a global attribute or just goes on summary details?
<lwarlow> q+
<jarhar> scott: that was one of lukes questions, i could see if very well being similar to the popover attribute. theres just enough things it does belong on that it makes sense for it to be a global attribute, but why would you put this on the body element?
<jarhar> gregwhitworth: i posted lea's status where she gives us props for not doing the element. i envision us hitting similar things where one of the reasons we went that route is because use csaes cant be solved by them being elemnts
<jarhar> gregwhitworth: the irony is that her tweet before that is supporting scotts initial thing where he wanted a drawer element
<jarhar> gregwhitworth: so it would be popover plus toggling
<jarhar> gregwhitworth: the invoker thing is starting to become the thing in which we say that this thing is going to do something with that. that was raised on that thread as well
<jarhar> gregwhitworth: i see the value, details summary is there, tabs we would be doing something similar. details summaries coudl be laid out to be tabs
<gregwhitworth> ack gregwhitworth
<gregwhitworth> ack lwarlow
<jarhar> lwarlow: i think on the cant do details summary, i dont know if these are not fixable problems, react aria has a details thing partially because of the styling thing. stuff like their design have it so you can have stuff adjacent to - inside the summary but not actually inside it. another button that does something else. in theory you can't put in
<jarhar> a summary but then youd have nested interactives
<gregwhitworth> q+ naman
<jarhar> lwarlow: i think the other thing is the fact that the spec doesn't match impls, but details summary you cant necessarily change the roles
<jarhar> lwarlow: i think a details is just a group at the moment, and then summary is slightly weird. if you had other roles you needed to use you cant do that in the current model
<jarhar> scott: in the aria and html spec the reason that we have that rule in there is because if there have been cases where changing the roles of those elements it stops working in the accessibility tree. its more of an author rule, but visually it would look fine
<jarhar> lwarlow: the one other thing is you dont necessarily want the trigger to be adjacent to the thing thats expanding. now in chrome you can go ham with css and mess things about, but a hamburger menu if you want that to do an expanding thing - having a summary inside the details limits that
<scott> q+ to say that's another use case. an expand all button or collapse all button.
<jarhar> lwarlow: i did at some point make a tab component that is using details summary, and the exclusive stuff to make a tab like thing, and i used the prototype invokers and hiding the summary
<jarhar> lwarlow: you can do that, it requires js, but none of thats necessarily correct because of certain impl problems
<masonf> q+
<jarhar> lwarlow: this was brought up by someone on mastodon, my first thought was details summary already does this. to me theres enough distinction if we can come up with concrete use cases where details summary doesnt work
<gregwhitworth> ack naman
<jarhar> nmn: is there a use case for a toggle thats not to show or hide something?
<jarhar> nmn: you use css to hide the details, or extend details summary. would it make sense to allow details to be used without a summary, and you use an invoker to open or close it?
<jarhar> scott: i would think that would have backwards compat issues because if you don't put a summary in a details then it would automatically get added
<jarhar> lwarlow: command invokers dont currently touch details
<jarhar> lwarlow: there is a prototype to do it with details, but i dont necessarily know if thats what we want
<jarhar> lwarlow: maybe instead we would just have a new thing and say use invokers with that
<gregwhitworth> ack scott
<Zakim> scott, you wanted to say that's another use case. an expand all button or collapse all button.
<jarhar> scott: an expand all button and collapse all button is another instance where this would be useful because you wouldn't use a details summary to collapse other details
<jarhar> scott: my original thought was that in some cases i have a button that invokes - my content is actually a popover for larger screen views, but i could write a script and swap that out and have another feature where another button invokes the same thing but its displayed inline. or i could have two buttons and display one, but its the same content
<jarhar> that shows up as a popup or a disclosure
<jarhar> scott: one of them i can do with html and the other i have to do with javascript
<gregwhitworth> ack masonf
<jarhar> masonf: some of the arguments are semantic, so whatwg would be ok with that
<lwarlow> q+
<jarhar> masonf: one thing that naman said is that a lot of the discussion about the magical hiding thing. what if the attribute was called openable, and that opts it in to matching or not matching the :open pseudo class, maybe adds toggle if you want, and its up to the developer to add a rule to display:none. all this attribute adds is one bit of state
<jarhar> which matches the pseudo-class, and then you dont have to worry about hiding
<jarhar> masonf: avoiding having to decide whether its display:none or visibility:hidden, and these questions it sidesteps
<gregwhitworth> ack lwarlow
<jarhar> lwarlow: i like that, but theres no way in css to do the find in page stuff
<jarhar> lwarlow: content-visibility:hidden might match, but hidden=until-found is special html stuff
<jarhar> lwarlow i could see a div that has hidden=until-found, and you can kind of make it display when its opened. the only bit there is that once its opened...
<jarhar> lwarlow: you could special case it where you don't have to remove the attribute. it does get removed, but this element has this other thing, so we're going to leave it and let it do stuff
<jarhar> masonf: when it has openable and hidden=until-found they play well together
<scott> q+
<jarhar> lwarlow: that does quite neatly avoid all the questions around does this work or does this not
<jarhar> lwarlow: maybe we do need default styles? but maybe not?
<gregwhitworth> ack scott
<jarhar> scott: since im not hearing anyone say i hate this, i was going to ask luke, do you want to help me write a proposal for this?
<gregwhitworth> q+
<jarhar> scott: since you already did work on the proposal for the pressed button which could the other question be for about, like other toggleable things, and this one is for show and hide and stuff
<jarhar> gregwhitworth: i would like clarity on the amount of things ive seen listed - invoker or commandfor? where does that line start and stop? i think that would be useful to understand
<jarhar> gregwhitworth: ive seen in the explainer video play start and stop so that its declarative. it feels like its becoming like state commands, and thats why im like at what point are those command this type of things?
<jarhar> gregwhitworth: what if devs think to try this
<jarhar> masonf: the proposal here is theres two parts: you put the openable attribute on something, and the other half is to use the command attribute to toggle it
<gregwhitworth> ack gregwhitworth
<jarhar> scott: when i wrote this command/commandfor didn't exist yet, but now we can just use command
<jarhar> lwarlow: as for where the line is drawn, currently the thing going into html is custom command which is nice to have on its own, popover commands, and modal dialog
<jarhar> lwarlow: followups to that would be this thing if this happens may be details if this doesn't happen. input and seelct have showpicker methods so we could see if we have a declarative way to do that. input especially it could be useful, that would be a fast followup
<jarhar> lwarlow: media controls and whatnot, i think its cool if we could do them. differnet class of things. all of them are currently aria expand and stuff, except for the custom ones
<jarhar> lwarlow: not really a clear line of where to stop
<masonf> Proposed resolution: Add a global attribute called `openable` that opts an element into matching `:open`, adds JS methods like .open(), .close(), and .toggle(), and connects to command/commandfor.
<jarhar> gregwhitworth: thanks, and thats a separate issue, just a quick clarifier, and it sounds like were using it so cool
<jarhar> q+
<keithamus> +1
<gregwhitworth> ack jarhar
<gregwhitworth> q+ nmn
<masonf> jarhar: for popover, we could have used :open, but we chose not to, because it conflicts with :open when on something like <dialog>
<masonf> jarhar: maybe we need a different pseudo class, other than :open.
<lwarlow> +1 (minus bikeshedding)
<gregwhitworth> ack dbaron
<masonf> jProposed resolution: Add a global attribute called `openable` that opts an element into matching `:open`, adds JS methods like .open(), .close(), and .toggle(), and connects to command/commandfor. All names subject to bikeshedding.
<jarhar> dbaron: the proposed resolution adds js methods. i dont think we should have a mechanism for adding or removing js methods based on an attribute
<jarhar> masonf: yeah it would have to throw if we dont have the attribute
<dbaron> s/should have/have/
<jarhar> masonf: whatever we did for popover we should do
<jarhar> scott: this could be the same as popover, it just doesn't go into the top layer
<gregwhitworth> ack nmn
<lwarlow> q+
<gregwhitworth> ack lwarlow
<dbaron> (One other issue is whether there are existing elements with open/close/toggle methods.)
<masonf> Proposed resolution: Add a global attribute called `mason` that opts an element into matching `:open`, adds JS methods like .open(), .close(), and .toggle(), and connects to command/commandfor. All names subject to bikeshedding.
<jarhar> masonf: we dont need closewatcher, it doesn't block navigation
<jarhar> keithamus: this isn't necessarily floating ui
<lwarlow> +1
<scott> +1
<masonf> +100, given the name
<keithamus> +1
<jarhar> +1
<nmn> +1
<masonf> RESOLVED: Add a global attribute called `openable` that opts an element into matching `:open`, adds JS methods like .open(), .close(), and .toggle(), and connects to command/commandfor. All names subject to bikeshedding.
<gregwhitworth> Zakim, end meeting

@lukewarlow lukewarlow changed the title Consider "toggle" (e.g., show/hide - expand/collapse) button or attribute Consider "toggle" (expand/collapse) attribute Jan 9, 2025
@lukewarlow lukewarlow added needs edits This is ready for edits to be made and removed agenda+ Use this label if you'd like the topic to be added to the meeting agenda labels Jan 9, 2025
@jimmyfrasche
Copy link

so (using the current spellings) openable defaultopen hidden=until-found is how you write one of these which is opened by default but still opens on ctil-f when closed? Does that mean that browsers must support until-found before this? (otherwise it would be hidden instead of :open)

It seems like there would be annoyances with [hidden] styles colliding with [openable]:open and so on.

@lukewarlow
Copy link
Collaborator

Me and Scott are going to put together a proposal next week which should hopefully clarify certain aspects of this. I think we can make it so that the styling story is nice but also configurable to different needs.

Fwiw a browser won't need hidden until found for this attribute to work but it would probably need it for the find in page use case to work.

@jimmyfrasche
Copy link

If it supports this but not hidden=until-found then it reads that as hidden and when it's open by default it's open but hidden. If it was openable=allow-fip (or something like that) it could work in browsers without hidden until found by ignoring the request to allow that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs edits This is ready for edits to be made
Projects
None yet
Development

No branches or pull requests