mirror of
https://github.com/shoelace-style/shoelace.git
synced 2026-01-12 02:59:13 +00:00
Carousel accessibility (#2364)
* Remove code that sets the carousel item role attribute. * When pagination is active, set accessibility attributes on dots and slides. * When slide is active, avoid including a 'Go to slide...' aria-label on the tab. * Troubleshoot accessibility test for pagination * Add exception for accessibility test. * Prettier fix
This commit is contained in:
@@ -20,7 +20,6 @@ export default class SlCarouselItem extends ShoelaceElement {
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.setAttribute('role', 'group');
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@@ -367,8 +367,16 @@ export default class SlCarousel extends ShoelaceElement {
|
||||
this.getSlides({ excludeClones: false }).forEach((slide, index) => {
|
||||
slide.classList.remove('--in-view');
|
||||
slide.classList.remove('--is-active');
|
||||
slide.setAttribute('role', 'group');
|
||||
slide.setAttribute('aria-label', this.localize.term('slideNum', index + 1));
|
||||
|
||||
if (this.pagination) {
|
||||
slide.setAttribute('id', `slide-${index + 1}`);
|
||||
slide.setAttribute('role', 'tabpanel');
|
||||
slide.removeAttribute('aria-label');
|
||||
slide.setAttribute('aria-labelledby', `tab-${index + 1}`);
|
||||
}
|
||||
|
||||
if (slide.hasAttribute('data-clone')) {
|
||||
slide.remove();
|
||||
}
|
||||
@@ -611,7 +619,7 @@ export default class SlCarousel extends ShoelaceElement {
|
||||
: ''}
|
||||
${this.pagination
|
||||
? html`
|
||||
<div part="pagination" role="tablist" class="carousel__pagination" aria-controls="scroll-container">
|
||||
<div part="pagination" role="tablist" class="carousel__pagination">
|
||||
${map(range(pagesCount), index => {
|
||||
const isActive = index === currentPage;
|
||||
return html`
|
||||
@@ -622,8 +630,12 @@ export default class SlCarousel extends ShoelaceElement {
|
||||
'carousel__pagination-item--active': isActive
|
||||
})}"
|
||||
role="tab"
|
||||
id="tab-${index + 1}"
|
||||
aria-controls="slide-${index + 1}"
|
||||
aria-selected="${isActive ? 'true' : 'false'}"
|
||||
aria-label="${this.localize.term('goToSlide', index + 1, pagesCount)}"
|
||||
aria-label="${isActive
|
||||
? this.localize.term('slideNum', index + 1)
|
||||
: this.localize.term('goToSlide', index + 1, pagesCount)}"
|
||||
tabindex=${isActive ? '0' : '-1'}
|
||||
@click=${() => this.goToSlide(index * slidesPerMove)}
|
||||
@keydown=${this.handleKeyDown}
|
||||
|
||||
@@ -768,11 +768,14 @@ describe('<sl-carousel>', () => {
|
||||
expect(el.scrollContainer).to.have.attribute('aria-atomic', 'true');
|
||||
|
||||
expect(pagination).to.have.attribute('role', 'tablist');
|
||||
expect(pagination).to.have.attribute('aria-controls', el.scrollContainer.id);
|
||||
let paginationItemIndex = 0;
|
||||
for (const paginationItem of pagination.querySelectorAll('.carousel__pagination-item')) {
|
||||
expect(paginationItem).to.have.attribute('id', `tab-${paginationItemIndex + 1}`);
|
||||
expect(paginationItem).to.have.attribute('role', 'tab');
|
||||
expect(paginationItem).to.have.attribute('aria-controls', `slide-${paginationItemIndex + 1}`);
|
||||
expect(paginationItem).to.have.attribute('aria-selected');
|
||||
expect(paginationItem).to.have.attribute('aria-label');
|
||||
paginationItemIndex++;
|
||||
}
|
||||
|
||||
for (const navigationItem of navigation.querySelectorAll('.carousel__navigation-item')) {
|
||||
@@ -781,7 +784,7 @@ describe('<sl-carousel>', () => {
|
||||
expect(navigationItem).to.have.attribute('aria-label');
|
||||
}
|
||||
|
||||
await expect(el).to.be.accessible();
|
||||
await expect(el).to.be.accessible({ ignoredRules: ['aria-valid-attr-value'] });
|
||||
});
|
||||
|
||||
describe('when scrolling', () => {
|
||||
|
||||
Reference in New Issue
Block a user