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

Interaction between ElementInternals (e.g. default ARIA) and declarative shadow DOM #972

Open
rniwa opened this issue Sep 28, 2022 · 10 comments
Labels
a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. custom-elements needs concrete proposal shadow-dom

Comments

@rniwa
Copy link
Collaborator

rniwa commented Sep 28, 2022

We need a way of serializing default ARIA role and other ARIA attributes usually specified on ElementInternals when using declarative shadow DOM.

@rniwa rniwa added shadow-dom custom-elements a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. labels Sep 28, 2022
@rniwa
Copy link
Collaborator Author

rniwa commented Sep 28, 2022

There are a few solutions to consider here.

  1. Put ARIA on template element and automatically transfer them to ElementInternals. This is a bit strange since we'd be special-casing ARIA on template elements then.
  2. Introduce new shadowaria* or defaultaria* content attributes on template element. e.g. shadowarialabel="blah" or defaultarialabel="blah" would translate to setting ariaLabel to "blah" in ElementInternals.
  3. "elementinternals" content attribute with its own micro-syntax for serializing ElementInternals on template element. e.g. elementinternals="role='checkbox' ariaLabel='blah'" or elementinternals='{"role": "checkbox", "ariaLabel": "blah"}'.
  4. Specify (2) or (3) on the shadow host. This will mirror ElementInternals being independent of shadow DOM.

@mfreed7
Copy link

mfreed7 commented Oct 4, 2022

There are a few solutions to consider here.

  1. Put ARIA on template element and automatically transfer them to ElementInternals. This is a bit strange since we'd be special-casing ARIA on template elements then.
  2. Introduce new shadowaria* or defaultaria* content attributes. e.g. shadowarialabel="blah" or defaultarialabel="blah" would translate to setting ariaLabel to "blah" in ElementInternals.
  3. "elementinternals" content attribute with its own micro-syntax for serializing ElementInternals. e.g. elementinternals="role='checkbox' ariaLabel='blah'" or elementinternals='{"role": "checkbox", "ariaLabel": "blah"}'.
  4. Specify (2) or (3) on the shadow host. This will mirror ElementInternals being independent of shadow DOM.

I agree that this is something we should work on. In terms of a solution, #1 sounds the most straightforward, and the least confusing from a developer point of view. Since a <template> doesn't render anything anyway, I would hope extra aria-* attributes on something that doesn't render a box shouldn't matter. Needs confirmation. Adding tons of shadowaria* sounds kind of ugly, as does a new elementinternals attribute. Though, elementinternals could be helpful for other things so perhaps that's worth exploring.

@justinfagnani
Copy link
Contributor

justinfagnani commented Oct 4, 2022

Since a <template> doesn't render anything anyway

This isn't always true. you can .append() into a <template> and that'll render. I wonder if the shadowroot attribute should change that?

@rniwa
Copy link
Collaborator Author

rniwa commented Oct 5, 2022

Accessibility folks probably wouldn't like (1) because ARIA doesn't have a special semantics like that on all other elements. In particular, it's odd to ignore the ARIA role of an element.

@nolanlawson
Copy link

#2 and #3 seem to be the only solution for components that don't use shadow DOM. Today a component can set its default role / ARIA attributes in ElementInternals without using shadow DOM.

If #2 is the solution, then would it make sense to align with cross-root ARIA delegation, since the syntax is similar?

@rniwa
Copy link
Collaborator Author

rniwa commented Oct 8, 2022

#2 and #3 seem to be the only solution for components that don't use shadow DOM. Today a component can set its default role / ARIA attributes in ElementInternals without using shadow DOM.

You mean (4)? (2) and (3) introduce attributes on template element defining declarative shadow DOM.

@nolanlawson
Copy link

You mean (4)?

Yes sorry, I meant (4).

@nolanlawson
Copy link

nolanlawson commented Oct 20, 2022

Today in the AOM meeting we discussed (4) – i.e., should the ElementInternals attribute (whether microsyntax or not) be defined on A) the custom element or B) its <template shadowroot>?

Arguments against A:

  • There aren't many great use cases for using ElementInternals in a shadowless component.
  • ElementInternals exposes the element's shadowRoot (if one is attached).

Arguments against B:

  • ElementInternals are usable today with shadowless components. So this would create a mismatch between what you can do imperatively vs declaratively.

My personal preference is A, if only to have symmetry with the imperative use case. If there aren't many great use cases for ElementInternals in shadowless components, then that's a problem with ElementInternals in general and not specifically about the declarative use case.

Also, I do have a rough sketch of a shadowless component using ElementInternals. In this case, it's an element with a default role of button and default aria-label.

Maybe a developer would use this technique if 1) they didn't want to use shadow DOM for various reasons, or 2) their custom element only needs one DOM node anyway. In this case, the component author could have a default role and aria-label:

<my-button></my-button> < !-- implicit role=button and aria-label="I am a button" -->

... but the consumer could override it.

<my-button role="tab" aria-label="I am a tab"></my-button>

@nolanlawson
Copy link

Somewhat related: ElementInternals and IDREFs #974

@zcorpan
Copy link
Contributor

zcorpan commented Apr 14, 2023

@justinfagnani

This isn't always true. you can .append() into a <template> and that'll render. I wonder if the shadowroot attribute should change that?

That would be non-conforming, see the content model https://html.spec.whatwg.org/multipage/scripting.html#the-template-element

It doesn't mean that it's not possible, but we don't need to take it into account when designing a solution to this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a11y-tracker Group bringing to attention of a11y, or tracked by the a11y Group but not needing response. custom-elements needs concrete proposal shadow-dom
Projects
None yet
Development

No branches or pull requests

5 participants