So I'm creating a web component and my code is like that now
<ul class="list-with-arrow${this.inverse ? '--inverse' : ''}">
${this.listData.map((item, index) => {
return item.link ? html`
${index === 0 ? html`<hr class="list-with-arrow__bottom-line${this.inverse ? '--inverse' : ''}" />` : ''}
<div class="list-with-arrow__container">
<a class="list-with-arrow__label-container${this.inverse ? '--inverse' : ''}" href=${item.link} @click=${this.handleItemClick}>
<li data-index="${index}">
${item.title ? html`<h5 class="list-with-arrow__title${this.inverse ? '--inverse' : ''}">${item.title}</h5>` : ''}
<h4 inverse class="list-with-arrow__label${this.inverse ? '--inverse' : ''}">${item.label}</h4>
</li>
<div>
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.99999 4.93933L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L8.99999 19.0607L7.93933 18L13.9393 12L7.93933 5.99999L8.99999 4.93933Z" fill="black"/>
</svg>
</div>
</a>
</div>
Sorry if it's kinda messy, i'm using lit element. The problem is when i test it with the screen reader it'll read only the elements/texts inside it but the main behavior of the screen reader while reading a list is something like "list with 4 items" and when you leave the list it'll say "leaving list". But since i'm using some other content inside it and not only plain text the SR will read only the text inside it and when i click anywhere else it will also not say "leaving the list". Does anyone know how to make a accessible list with this kinda of binded content inside it?
your HTML is invalid, the only thing that can be contained within a <ul>
is <li>
as direct descendants.
As such if you change the first item it returns to a <li>
that will fix most issues. make sure that item.link
is also a <li>
with content inside it.
However I do notice that you have a second <li>
within the body HTML. (<li data-index="${index}">
)
This is also invalid as a <li>
must have a <ul>
or <ol>
as a parent. I would swap that out for a <div>
instead (or better yet as it just seems to contain a heading level 4 or 5 remove the outer container and use CSS to position it if you don't need the data-index
.)
Generated output should be something like this (as you said it is a little messy and there are bits of information missing):
<ul class="list-with-arrow">
<!-- outputted a list item before any of the other content -->
<li>
<hr class="list-with-arrow__bottom-line">
<div class="list-with-arrow__container">
<a class="list-with-arrow__label-container href="link">
<!--- swapped the inner list item to a div -->
<div data-index="1">
<h5 class="list-with-arrow__title">Title</h5>
</div>
<div>
<!-- notice I added focusable="false" and aria-hidden="true" to the SVG to avoid it being announced as an image without a description. -->
<!-- if this does contain useful information you should instead add a `<title>` element that describes the image -->
<svg focusable="false" aria-hidden="true" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.99999 4.93933L15.5303 11.4697C15.8232 11.7626 15.8232 12.2374 15.5303 12.5303L8.99999 19.0607L7.93933 18L13.9393 12L7.93933 5.99999L8.99999 4.93933Z" fill="black"/>
</svg>
</div>
</a>
</div>
</li>
[...further items]
</ul>
I also made some notes on the SVG on how to handle that for screen readers depending on whether it contains useful information or not.