whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.03k stars 2.63k forks source link

[Proposal]: Enable `HTMLElement` attributes to be toggled without JavaScript #10357

Open ITenthusiasm opened 4 months ago

ITenthusiasm commented 4 months ago

What problem are you trying to solve?

It's common for applications to create content that can be accessibly expanded/collapsed with the aria-expanded attribute. Unfortunately, there is no native way to toggle this attribute without JavaScript today. Consequently, there are several rich user experiences that are currently unaccessible to people without JavaScript.

With the power of CSS selectors (especially now that we have :has() on the scene), we can pretty much "expand" any element with just CSS. Below is a simple example:

/* Assumes that `.my-target` is visible by default. */
button[aria-expanded="false"] + .my-target {
  display: none;
}

So all that we really need in order to make elements expandable without JS is a feature that would enable an attribute to be toggled without JS. It would be spectacular if that could be supported! 🙏🏾

What solutions exist today?

Bad: Navigation

One existing solution is to create a link that acts like an expandable button by navigating to a URL where the content is already expanded.

<!-- The value for `aria-expanded` would need to be dynamically determined during server rendering, based on the query parameter -->
<a href="?target-button-expanded=true" role="button" aria-expanded"false" aria-controls="target-content">
  See Content
</a>

However, this approach has a few significant problems:

Slightly Better but Limited: Hacking the <details> Element

Theoretically, now that we have :has(), it would be possible to hack the <details> element to accomplish the desired behavior with aria-owns in the event that the content does not visually live inside the <details> element.

<div class="card-component">
  <div style="display: flex; justify-content: space-between; align-items: center">
    <div>Heading for Card</div>
    <details aria-owns="card-content">
      <summary>
        <span class="screen-reader-only-text">Show Card Details</span>
        <svg viewBox="0 0 100 100" aria-hidden="true">
          <use href="#my-caret-icon" />
        </svg>
      </summary>
    </details>
  </div>

  <div id="card-content">
    Oh wow! Look at all of this cool styled content!
  </div>
</div>

Then the CSS would potentially look something like this:

.card-component:has(details:not([open])) > :last-child {
  display: none;
}

This is significantly more preferable than awkwardly chatting with the server, but this approach still has other significant caveats:

How would you solve it?

The Popover API seems like a potential source of inspiration. HTML attributes could be used to determine how an element's attributes should be changed when a button is clicked.

<button aria-controls="target" aria-expanded="false" switch-attribute="aria-expanded" switch-on="true" switch-off="false">
  See Content
</button>

This is just one potential solution. I'm certain there are other alternatives.

Anything else?

Multiple Buttons Expanding/Collapsing the Same Element

There might be situations where multiple elements on the same page would be able to control the same element's visibility. In that case, there would need to be a way to "link" all of them together. I'm not sure what a good solution would look like. But off the top of my head, one potential idea is to use another attribute that can group together a set of controls (just like radio buttons are grouped by name).

<button switch-group="my-group"></button>
<button switch-group="my-group"></button>

Doing More Than Attribute Toggling

It's possible that what's really surfacing from this feature proposal is a way to control attributes without JavaScript in a more broad sense. However, I'm not immediately certain what the use cases for that would be. It's just a thought.

annevk commented 4 months ago

Did you see #9625?

ITenthusiasm commented 4 months ago

I did not, though this isn't necessarily related to dialogs/popups. I can take a look at the OP and the comments.

ITenthusiasm commented 3 months ago

@annevk I tried to skim through that issue, and it seemed like it is restricted to dialogs and popups. I saw mention of "custom actions", but it looked like those are intended to work with JavaScript only. Is that correct? So perhaps my Issue here is still a distinct one?

In my skimming, I came across openui/open-ui#1058 and openui/open-ui#700. @scottaohara's OP in Issue 700 definitely shares my sentiment, as I would also like something that isn't restricted to the Top Layer or to <details>. Would it be appropriate to leave this issue open here? Or should I transfer these details to one of those other 2 OpenUI Issues? (Or perhaps somewhere else? I can try skimming the issue that you provided a little more to look for other linked issues.)

annevk commented 3 months ago

I think it's okay to leave this open. That other issue has the momentum currently though and I would not expect us to add several very similar mechanisms.

ITenthusiasm commented 3 months ago

Got it! I'll try to add a comment to that issue when I get a chance then -- hopefully today or tomorrow. (I'm assuming you're referring to the dialog/popover/custom actions Issue?)