Skip to content

Commit

Permalink
fix: slider a11y
Browse files Browse the repository at this point in the history
  • Loading branch information
giuliaghisini committed Mar 6, 2024
1 parent 75e8a8c commit ab0148a
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 52 deletions.
32 changes: 13 additions & 19 deletions src/components/ItaliaTheme/Blocks/Listing/Commons/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export const getCategory = (item, show_type, show_section, props) => {
export const useSlider = (userAutoplay, block_id) => {
const slider = useRef(null);
const sliderContainer = document.getElementById('outside-slider-' + block_id);
const sliderElement = document.querySelector(`#slider_${block_id}`);
const sliderElementSelector = `#slider_${block_id}`;
const sliderElement = document.querySelector(sliderElementSelector);
const onIntersection = (entries, opt) => {
entries.forEach((entry) =>
entry.target.classList.toggle('visible', entry.isIntersecting),
Expand All @@ -42,32 +43,26 @@ export const useSlider = (userAutoplay, block_id) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

const focusNext = (currentSlide) => {
const focusSlide = (slideIndex) => {
if (!sliderElement) return;
const sliderIsVisible = sliderContainer.classList.contains('visible');

if (!sliderIsVisible) {
slider.current.slickPause();
return;
}
const slide = sliderElement.querySelector(
`#slider_${block_id} .slick-slide[data-index="${currentSlide}"]`,

const slide = document.querySelector(
`${sliderElementSelector} .slick-slide[data-index="${slideIndex}"] .it-single-slide-wrapper`,
);

if (userAutoplay && !slide) return;

if (!slide || document.activeElement === slide) {
return;
}
// eslint-disable-next-line no-unused-expressions
else if (
// if the focus was already on a slide, move it to the current one
Array.from(
document.querySelectorAll(`#slider_${block_id} .slick-slide`),
).some((el) => el.contains(document.activeElement))
) {
slide.focus();
}

slide.focus();
};

const visibleSlide = (selector) => {
Expand All @@ -94,7 +89,7 @@ export const useSlider = (userAutoplay, block_id) => {
e.preventDefault();

const slide = visibleSlide(
`#slider_${block_id} .slick-slide[data-index="${currentSlide}"]`,
`${sliderElementSelector} .slick-slide[data-index="${currentSlide}"]`,
);
slide && slide.focus();
}
Expand All @@ -113,8 +108,7 @@ export const useSlider = (userAutoplay, block_id) => {

const SliderPrevArrow = (props) => {
// Custom handling of focus for a11y
const { className, style, onClick, focusNext, currentSlide, slideCount } =
props;
const { className, style, onClick, currentSlide, slideCount } = props;
const handleClick = (options) => {
onClick(options, false);
};
Expand All @@ -125,11 +119,11 @@ export const useSlider = (userAutoplay, block_id) => {

if (currentSlide < slideCount) {
const slide = visibleSlide(
`#slider_${block_id} .slick-slide[data-index="${currentSlide}"]`,
`${sliderElementSelector} .slick-slide[data-index="${currentSlide}"]`,
);

slide && slide.focus();
} else focusNext(0, block_id);
}
}
};
return (
Expand All @@ -145,7 +139,7 @@ export const useSlider = (userAutoplay, block_id) => {

return {
slider,
focusNext,
focusSlide,
visibleSlide,
SliderNextArrow,
SliderPrevArrow,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ const SimpleCardDefault = (props) => {
id_lighthouse,
rrule,
index,
handleKeyboardUsers = () => {}, //for slider template handler
} = props;

const getItemClass = (item) => {
Expand Down Expand Up @@ -120,7 +119,6 @@ const SimpleCardDefault = (props) => {
item={!isEditMode ? item : null}
href={isEditMode ? '#' : null}
data-element={id_lighthouse}
onKeyDown={handleKeyboardUsers}
>
{itemTitle}
</UniversalLink>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ const SlideItemDefault = ({
userAutoplay,
slider,
messages,
handleKeyboardUsers,
}) => {
return (
<React.Fragment>
Expand All @@ -31,7 +30,6 @@ const SlideItemDefault = ({
tabIndex={0}
data-slide={index}
className={'slide-link no-external-if-link'}
onKeyDown={handleKeyboardUsers}
>
{full_width ? (
<Container>
Expand Down
75 changes: 48 additions & 27 deletions src/components/ItaliaTheme/Blocks/Listing/SliderTemplate.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,34 +44,52 @@ const Slide = (props) => {
appearance,
appearanceProp,
block_id,
slider,
} = props;

const handleKeyboardUsers = (e) => {
const { key, shiftKey } = e;

if (key === 'Tab') {
e.preventDefault();
e.stopPropagation();
const slide_selector = `#slider_${block_id} .slick-slide[data-index="${index}"]`;

const focusableSlideElements = document.querySelectorAll(
`${slide_selector} a, ${slide_selector} button, ${slide_selector} [tabindex="0"]`,
);
const isFirstSlideFocusableElement =
e.target === focusableSlideElements[0];
const isLastSlideFocusableElement =
e.target === focusableSlideElements[focusableSlideElements.length - 1];

if (
(isFirstSlideFocusableElement && shiftKey) ||
(isLastSlideFocusableElement && !shiftKey)
) {
e.preventDefault();
e.stopPropagation();
//shift+tab ed è il primo elemento focusabile nella slide, oppure tab ed è l'ultimo elemento focusabile nella slide
//go to next/prev slide or to next/prev button.
} else {
return; //continue doing default bhv of Tab key, to focus next focusable element inside slide.
}

// Keeping auto pause off for now
// if (userAutoplay) setUserAutoplay(false);
// slider.current.slickPause();
let elementToFocus;

console.log(index, prevIndex, nextIndex);
if (shiftKey) {
elementToFocus =
prevIndex != null
? document.querySelector(
`#slider_${block_id} .slick-slide[data-index="${prevIndex}"]`,
)
: document.getElementById('sliderPrevArrow_' + block_id);
} else
elementToFocus =
nextIndex != null
? document.querySelector(
`#slider_${block_id} .slick-slide[data-index="${nextIndex}"]`,
)
: document.getElementById('sliderNextArrow_' + block_id);
elementToFocus.focus();
if (prevIndex != null) {
slider.current.slickGoTo(prevIndex);
} else {
document.getElementById('sliderPrevArrow_' + block_id).focus();
}
} else {
if (nextIndex != null) {
slider.current.slickGoTo(nextIndex);
} else {
document.getElementById('sliderNextArrow_' + block_id).focus();
}
}
}
};

Expand All @@ -81,13 +99,16 @@ const Slide = (props) => {
const SlideItemAppearance = appearances[appearance] ?? appearances['default'];

return (
<SingleSlideWrapper key={item['@id'] + index} index={index}>
<div className={'slide-wrapper'}>
<SingleSlideWrapper
key={item['@id'] + index}
index={index}
onKeyDown={handleKeyboardUsers}
>
<div className={'slide-wrapper'} role="presentation">
<SlideItemAppearance
{...props}
{...appearanceProp}
messages={messages}
handleKeyboardUsers={handleKeyboardUsers}
/>
</div>
</SingleSlideWrapper>
Expand Down Expand Up @@ -121,7 +142,7 @@ const SliderTemplate = ({
? items.length
: parseInt(slidesToShow);
const Slider = reactSlick.default;
const { slider, focusNext, SliderNextArrow, SliderPrevArrow } = useSlider(
const { slider, focusSlide, SliderNextArrow, SliderPrevArrow } = useSlider(
userAutoplay,
block_id,
);
Expand Down Expand Up @@ -197,11 +218,11 @@ const SliderTemplate = ({
focusOnSelect: false,
draggable: true,
accessibility: true,
nextArrow: <SliderNextArrow intl={intl} focusNext={focusNext} />,
prevArrow: <SliderPrevArrow intl={intl} focusNext={focusNext} />,
nextArrow: <SliderNextArrow intl={intl} />,
prevArrow: <SliderPrevArrow intl={intl} />,
appendDots: renderCustomDots,
// Custom handling of focus for a11y
afterChange: focusNext,
afterChange: focusSlide,
responsive: [
{
breakpoint: 980,
Expand Down Expand Up @@ -254,8 +275,8 @@ const SliderTemplate = ({
<Slide
image={image}
index={index}
nextIndex={index + 1 === items.length ? null : index + 1}
prevIndex={index - 1 === -1 ? null : index - 1}
nextIndex={index < items.length ? index + 1 : null}
prevIndex={index > 0 ? index - 1 : null}
full_width={full_width}
item={item}
show_image_title={show_image_title}
Expand Down
11 changes: 9 additions & 2 deletions src/components/ItaliaTheme/Slider/SingleSlideWrapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const messages = defineMessages({
defaultMessage: 'Slide',
},
});
const SingleSlideWrapper = ({ className, key, index, children }) => {
const SingleSlideWrapper = ({ className, key, index, children, onKeyDown }) => {
const intl = useIntl();
const wrapperKey = key ?? 'slide-wrapper-' + index;

Expand All @@ -15,12 +15,19 @@ const SingleSlideWrapper = ({ className, key, index, children }) => {
className={`it-single-slide-wrapper ${className ?? ''}`}
key={wrapperKey}
data-slide={index}
role="group"
role="button"
aria-roledescription="group"
aria-label={
intl.formatMessage(messages.carouselSlide) +
' ' +
(index ? index + 1 : '')
}
onKeyDown={onKeyDown}
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
}}
tabIndex={0}
>
{children}
</div>
Expand Down

0 comments on commit ab0148a

Please sign in to comment.