From 9ae8224688ffed9d0599d0aba6d48db88a333d50 Mon Sep 17 00:00:00 2001 From: Bishop Date: Thu, 23 Apr 2026 12:35:55 -0700 Subject: [PATCH] WIP(5514): Add short-term Slick carousel accessibility patch as optional theme library --- .../custom/az_barrio/az_barrio.libraries.yml | 14 +++++++ .../custom/az_barrio/js/slick-a11y-patch.js | 37 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 themes/custom/az_barrio/js/slick-a11y-patch.js diff --git a/themes/custom/az_barrio/az_barrio.libraries.yml b/themes/custom/az_barrio/az_barrio.libraries.yml index 900f42cddd..909531c492 100644 --- a/themes/custom/az_barrio/az_barrio.libraries.yml +++ b/themes/custom/az_barrio/az_barrio.libraries.yml @@ -76,3 +76,17 @@ toasts: dependencies: - core/drupal - az_barrio/arizona-bootstrap-js + +az-slick-a11y-patch: + js: + js/slick-a11y-patch.js: {} + dependencies: + - core/jquery + - core/drupal + +az-slick-a11y-patch: + js: + js/slick-a11y-patch.js: {} + dependencies: + - core/jquery + - core/drupal diff --git a/themes/custom/az_barrio/js/slick-a11y-patch.js b/themes/custom/az_barrio/js/slick-a11y-patch.js new file mode 100644 index 0000000000..6045375e24 --- /dev/null +++ b/themes/custom/az_barrio/js/slick-a11y-patch.js @@ -0,0 +1,37 @@ +// Accessibility runtime patch for Slick carousel (short-term fix for #5514) +// - Adjust roles on dot navigation +// - Add aria-label to track +// - Prevent focusable elements inside aria-hidden slides +(function ($, Drupal) { + 'use strict'; + $(document).once('slick-a11y-patch').each(function () { + // When slick initializes, apply corrections + $(document).on('init reInit', '.slick-slider', function (event, slick) { + var $slider = $(this); + // ensure track has accessible name + var $track = $slider.find('.slick-track'); + if ($track.length && !$track.attr('aria-label')) { + $track.attr('aria-label', $slider.data('a11y-label') || 'Carousel slides'); + } + // fix dots role + var $dots = $slider.find('.slick-dots'); + if ($dots.length) { + $dots.attr('role', 'list'); + $dots.find('li').each(function (i) { + $(this).removeAttr('role aria-selected aria-controls'); + // ensure internal button has accessible label + var $btn = $(this).find('button'); + if ($btn.length && !$btn.attr('aria-label')) { + $btn.attr('aria-label', 'Go to slide ' + (i+1)); + } + }); + } + // hide focusable children of aria-hidden slides + $slider.find('.slick-slide[aria-hidden="true"]').each(function () { + $(this).find('a, button, input, select, textarea').attr('tabindex', '-1'); + }); + // remove problematic role on slide wrapper + $slider.find('.slick-slide').removeAttr('role tabindex'); + }); + }); +})(jQuery, Drupal);