lit / lit/lit

[lit-element] Use of aria in lit Element

Open
#3,813 2 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
21.8k
Forks
1.1k
Avg merge
18h 25m
Merged PRs (30d)
2

Description

### Should this be an RFC?

- [x] This is not a substantial change

### Which package is this a feature request for?

Lit Core (lit / lit-html / lit-element / reactive-element)

### Description

It would be useful if we could reflect the aria attributes of an HTML element to the shadowdom elements, and upon hydration, remove the aria attributes (but somehow keeping its reactivity) from the HTML element and keep them on the shadowdom elements.

For example, when I was creating a stepper component, I ran into an accessibility problem. If a user uses the stepper component two times (or two components that contain the `` element) on a page like this:

```html

```

It would render like this:
```html

```

But this is wrong according to https://dequeuniversity.com/rules/axe/4.6/landmark-unique?application=axeAPI because there are no unique landmarks applied to ``.

The solution would be to add an aria-label to describe what the `` is for, so screen readers can tell what the `` is used for.

When rendering the component using the aria-label method:

```html

```

It would be rendered like this:
```html



```

The problem with this is that when someone is using a screen reader, it would read out:
"stepper 1, group"
"stepper 1, navigation"
"stepper 2, group"
"stepper 2, navigation"

This is wrong. What we want to be rendered and read out is:
```html



```

So that when a user is navigating with a screen reader, things would be read out like:
"nav 1, navigation"
"nav 2, navigation"

The user should be able to control the aria-label of `` by setting an aria-label attribute to ``. Adding an extra prop like navAriaLabel would not be developer-friendly because the developer would have to remember an extra non-native HTML property.

### Alternatives and Workarounds

it's possible to achieve this only for the first render by doing:

```js
export class StepperElement extends LitElement {
render() {
return html`...`;
}

updated(p) {
if (this.ariaLabel) {
this.ariaLabel = '';
}
}
}

const renderResult = render(html`

`);
```

This works on first render, but if you update your element again, nav aria-label will be empty. Besides, this doesn't work with SSR.

I also tried (With a developer from the discord channel), to find a loophole and make it work for ssr:

```js
@customElement('stepper-element')
export class StepperElement extends LitElement {

@state() navAriaLabel = undefined;

willUpdate(p) {
if (this.navAriaLabel === undefined && this.ariaLabel) {
this.navAriaLabel = this.ariaLabel;
this.removeAttribute('aria-label');
}
}

render() {
return html`...`;
}
}

const renderResult = render(html`

`);
```

But if you try to render this as is, it doesn't work because aria-label is removed from stepper and loses its reactivity. Besides that, this dosn't work with SSR.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue names Lit Core packages—lit, lit-html, lit-element, and reactive-element—and shows render() and willUpdate() examples; begin by checking how aria-label reactivity and SSR are handled across those entry points. Compare client and SSR rendering for the two-stepper example. Done should preserve updates while exposing the label only on the shadow-DOM nav, but the design needs maintainer guidance.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
accessibility, frontend
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.