From 27a551627a4f3ab1b1e6233c048b061045cc9c9e Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Thu, 13 Feb 2025 10:09:48 -0300 Subject: [PATCH 01/10] Feat: added tabindex logic for better accessibility support --- src/slider.js | 35 ++++++++++++++++++++++++++++++++++- src/track.js | 12 ++++++++---- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/src/slider.js b/src/slider.js index 7fdbe4a13..9799cde31 100644 --- a/src/slider.js +++ b/src/slider.js @@ -13,10 +13,34 @@ export default class Slider extends React.Component { breakpoint: null }; this._responsiveMediaHandlers = []; + this.childRefs = new Set(); + this.observer = null; } innerSliderRefHandler = ref => (this.innerSlider = ref); + setupIntersectObserver() { + if (this.observer) { + this.observer.disconnect(); + } + this.observer = new IntersectionObserver( + entries => { + entries.forEach(entry => { + entry.target.tabIndex = entry.isIntersecting ? 1 : -1; + }); + }, + { + root: null, + threshold: 0.1 + } + ); + this.childRefs.forEach(element => { + if (element) { + this.observer.observe(element); + } + }); + } + media(query, handler) { // javascript handler for css media query const mql = window.matchMedia(query); @@ -31,6 +55,9 @@ export default class Slider extends React.Component { // handles responsive breakpoints componentDidMount() { + window.addEventListener("resize", this.setupIntersectionObserver); + window.addEventListener("scroll", this.setupIntersectionObserver); + setTimeout(() => this.setupIntersectObserver(), 0); // performance monitoring //if (process.env.NODE_ENV !== 'production') { //const { whyDidYouUpdate } = require('why-did-you-update') @@ -76,6 +103,8 @@ export default class Slider extends React.Component { this._responsiveMediaHandlers.forEach(function(obj) { obj.mql.removeListener(obj.listener); }); + window.removeEventListener("resize", this.setupIntersectionObserver); + window.removeEventListener("scroll", this.setupIntersectionObserver); } slickPrev = () => this.innerSlider.slickPrev(); @@ -179,7 +208,11 @@ export default class Slider extends React.Component { row.push( React.cloneElement(children[k], { key: 100 * i + 10 * j + k, - tabIndex: -1, + ref: el => { + if (el) { + this.childRefs.add(el); + } + }, style: { width: `${100 / settings.slidesPerRow}%`, display: "inline-block" diff --git a/src/track.js b/src/track.js index b64e722e7..8fce5fac5 100644 --- a/src/track.js +++ b/src/track.js @@ -123,9 +123,13 @@ const renderSlides = spec => { key: "original" + getKey(child, index), "data-index": index, className: classnames(slideClasses, slideClass), - tabIndex: "-1", + tabIndex: !slideClasses["slick-active"] ? "-1" : "1", "aria-hidden": !slideClasses["slick-active"], - style: { outline: "none", ...(child.props.style || {}), ...childStyle }, + style: { + outline: "none", + ...(child.props.style || {}), + ...childStyle + }, onClick: e => { child.props && child.props.onClick && child.props.onClick(e); if (spec.focusOnSelect) { @@ -153,7 +157,7 @@ const renderSlides = spec => { React.cloneElement(child, { key: "precloned" + getKey(child, key), "data-index": key, - tabIndex: "-1", + tabIndex: !slideClasses["slick-active"] ? "-1" : "1", className: classnames(slideClasses, slideClass), "aria-hidden": !slideClasses["slick-active"], style: { ...(child.props.style || {}), ...childStyle }, @@ -176,7 +180,7 @@ const renderSlides = spec => { React.cloneElement(child, { key: "postcloned" + getKey(child, key), "data-index": key, - tabIndex: "-1", + tabIndex: !slideClasses["slick-active"] ? "-1" : "1", className: classnames(slideClasses, slideClass), "aria-hidden": !slideClasses["slick-active"], style: { ...(child.props.style || {}), ...childStyle }, From b6288bfd992ed846603da045cae53244a0b40b1d Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Fri, 14 Feb 2025 12:26:55 -0300 Subject: [PATCH 02/10] new version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b9c7d040..b170dfbae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-slick", - "version": "0.30.3", + "version": "0.30.4", "description": " React port of slick carousel", "main": "./lib", "files": [ From 9d3830804a9aab80dd245850eab02878d5455ae2 Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Fri, 14 Feb 2025 12:34:27 -0300 Subject: [PATCH 03/10] changed name --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b170dfbae..711ba63f7 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "react-slick", + "name": "@oggo-petersen/react-slick", "version": "0.30.4", "description": " React port of slick carousel", "main": "./lib", From 59ca95c5cb2ca821d463b21939900f42a4e732aa Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Fri, 14 Feb 2025 13:39:56 -0300 Subject: [PATCH 04/10] check if element is an instance of Element --- package.json | 2 +- src/slider.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 711ba63f7..229784799 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@oggo-petersen/react-slick", - "version": "0.30.4", + "version": "0.30.5", "description": " React port of slick carousel", "main": "./lib", "files": [ diff --git a/src/slider.js b/src/slider.js index 9799cde31..d39ecc69b 100644 --- a/src/slider.js +++ b/src/slider.js @@ -35,7 +35,7 @@ export default class Slider extends React.Component { } ); this.childRefs.forEach(element => { - if (element) { + if (element && element instanceof Element) { this.observer.observe(element); } }); From 11f1c1fdda4a863f0bb1f9302277ec78cebbc5d7 Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Tue, 18 Feb 2025 08:22:04 -0300 Subject: [PATCH 05/10] adjusted package.json version / name --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 229784799..b170dfbae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@oggo-petersen/react-slick", - "version": "0.30.5", + "name": "react-slick", + "version": "0.30.4", "description": " React port of slick carousel", "main": "./lib", "files": [ From cf1aaa71c26a63bd24e255d0be4295e0c51561cb Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Mon, 24 Feb 2025 14:56:02 -0300 Subject: [PATCH 06/10] feat: added refs, adjusted tabIndex --- src/slider.js | 2 +- src/track.js | 53 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/slider.js b/src/slider.js index d39ecc69b..b7c988832 100644 --- a/src/slider.js +++ b/src/slider.js @@ -26,7 +26,7 @@ export default class Slider extends React.Component { this.observer = new IntersectionObserver( entries => { entries.forEach(entry => { - entry.target.tabIndex = entry.isIntersecting ? 1 : -1; + entry.target.tabIndex = entry.isIntersecting ? 0 : -1; }); }, { diff --git a/src/track.js b/src/track.js index 8fce5fac5..44262f83e 100644 --- a/src/track.js +++ b/src/track.js @@ -95,6 +95,7 @@ const renderSlides = spec => { let childrenCount = React.Children.count(spec.children); let startIndex = lazyStartIndex(spec); let endIndex = lazyEndIndex(spec); + const childRefs = spec.childRefs; React.Children.forEach(spec.children, (elem, index) => { let child; @@ -122,8 +123,12 @@ const renderSlides = spec => { React.cloneElement(child, { key: "original" + getKey(child, index), "data-index": index, + ref: el => { + if (el) { + childRefs.add(el); + } + }, className: classnames(slideClasses, slideClass), - tabIndex: !slideClasses["slick-active"] ? "-1" : "1", "aria-hidden": !slideClasses["slick-active"], style: { outline: "none", @@ -157,7 +162,6 @@ const renderSlides = spec => { React.cloneElement(child, { key: "precloned" + getKey(child, key), "data-index": key, - tabIndex: !slideClasses["slick-active"] ? "-1" : "1", className: classnames(slideClasses, slideClass), "aria-hidden": !slideClasses["slick-active"], style: { ...(child.props.style || {}), ...childStyle }, @@ -180,7 +184,6 @@ const renderSlides = spec => { React.cloneElement(child, { key: "postcloned" + getKey(child, key), "data-index": key, - tabIndex: !slideClasses["slick-active"] ? "-1" : "1", className: classnames(slideClasses, slideClass), "aria-hidden": !slideClasses["slick-active"], style: { ...(child.props.style || {}), ...childStyle }, @@ -205,12 +208,54 @@ const renderSlides = spec => { export class Track extends React.PureComponent { node = null; + constructor(props) { + super(props); + this.childRefs = new Set(); + this.observer = null; + } + handleRef = ref => { this.node = ref; }; + componentDidMount() { + window.addEventListener("resize", this.setupIntersectionObserver); + window.addEventListener("scroll", this.setupIntersectionObserver); + setTimeout(() => this.setupIntersectObserver(), 0); + } + + componentWillUnmount() { + window.removeEventListener("resize", this.setupIntersectionObserver); + window.removeEventListener("scroll", this.setupIntersectionObserver); + } + + setupIntersectObserver() { + if (this.observer) { + this.observer.disconnect(); + } + this.observer = new IntersectionObserver( + entries => { + entries.forEach(entry => { + entry.target.tabIndex = entry.isIntersecting ? 0 : -1; + }); + }, + { + root: null, + threshold: 0.1 + } + ); + this.childRefs.forEach(element => { + if (element && element instanceof Element) { + this.observer.observe(element); + } + }); + } + render() { - const slides = renderSlides(this.props); + const slides = renderSlides({ + childRefs: this.childRefs, + ...this.props + }); const { onMouseEnter, onMouseOver, onMouseLeave } = this.props; const mouseEvents = { onMouseEnter, onMouseOver, onMouseLeave }; return ( From a1268dd6df90b7376a162c1729de659d1f59be3e Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Mon, 24 Feb 2025 14:58:04 -0300 Subject: [PATCH 07/10] adjusted version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index b170dfbae..9275c1995 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "react-slick", - "version": "0.30.4", + "name": "@oggo-petersen/react-slick", + "version": "0.30.6", "description": " React port of slick carousel", "main": "./lib", "files": [ From 0788b992f43d89bf735420beb0db766b1a743788 Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Tue, 4 Mar 2025 08:25:51 -0300 Subject: [PATCH 08/10] added aria hidden logic --- src/slider.js | 4 ++++ src/track.js | 6 ++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/slider.js b/src/slider.js index b7c988832..75c3d7011 100644 --- a/src/slider.js +++ b/src/slider.js @@ -27,6 +27,10 @@ export default class Slider extends React.Component { entries => { entries.forEach(entry => { entry.target.tabIndex = entry.isIntersecting ? 0 : -1; + entry.target.setAttribute( + "aria-hidden", + entry.isIntersecting ? "false" : "true" + ); }); }, { diff --git a/src/track.js b/src/track.js index 44262f83e..c67a94fe7 100644 --- a/src/track.js +++ b/src/track.js @@ -129,7 +129,6 @@ const renderSlides = spec => { } }, className: classnames(slideClasses, slideClass), - "aria-hidden": !slideClasses["slick-active"], style: { outline: "none", ...(child.props.style || {}), @@ -185,7 +184,6 @@ const renderSlides = spec => { key: "postcloned" + getKey(child, key), "data-index": key, className: classnames(slideClasses, slideClass), - "aria-hidden": !slideClasses["slick-active"], style: { ...(child.props.style || {}), ...childStyle }, onClick: e => { child.props && child.props.onClick && child.props.onClick(e); @@ -237,6 +235,10 @@ export class Track extends React.PureComponent { entries => { entries.forEach(entry => { entry.target.tabIndex = entry.isIntersecting ? 0 : -1; + entry.target.setAttribute( + "aria-hidden", + entry.isIntersecting ? "false" : "true" + ); }); }, { From a61f307be9148f837994a4efee4fd5604792966a Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Tue, 4 Mar 2025 08:27:28 -0300 Subject: [PATCH 09/10] adjusted package.json name and version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 9275c1995..b170dfbae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@oggo-petersen/react-slick", - "version": "0.30.6", + "name": "react-slick", + "version": "0.30.4", "description": " React port of slick carousel", "main": "./lib", "files": [ From 4b9afed149af39423ce0398a6f153bcdf308731b Mon Sep 17 00:00:00 2001 From: Oggo Petersen Date: Tue, 11 Mar 2025 18:10:55 -0300 Subject: [PATCH 10/10] adds refs to cloned elements --- src/track.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/track.js b/src/track.js index c67a94fe7..35671cc86 100644 --- a/src/track.js +++ b/src/track.js @@ -161,8 +161,12 @@ const renderSlides = spec => { React.cloneElement(child, { key: "precloned" + getKey(child, key), "data-index": key, + ref: el => { + if (el) { + childRefs.add(el); + } + }, className: classnames(slideClasses, slideClass), - "aria-hidden": !slideClasses["slick-active"], style: { ...(child.props.style || {}), ...childStyle }, onClick: e => { child.props && child.props.onClick && child.props.onClick(e); @@ -183,6 +187,11 @@ const renderSlides = spec => { React.cloneElement(child, { key: "postcloned" + getKey(child, key), "data-index": key, + ref: el => { + if (el) { + childRefs.add(el); + } + }, className: classnames(slideClasses, slideClass), style: { ...(child.props.style || {}), ...childStyle }, onClick: e => {