From 808a0cae893a8754a61ed09a18f697e5d28f5f9e Mon Sep 17 00:00:00 2001 From: clvarley Date: Fri, 23 Dec 2022 09:24:12 +0000 Subject: [PATCH 1/4] Expose ability to move focus to element after scroll --- src/scroll.js | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/scroll.js b/src/scroll.js index 0e96720..79b200c 100644 --- a/src/scroll.js +++ b/src/scroll.js @@ -2,7 +2,7 @@ import { getDocumentYOffset } from "./position"; import { TIMING_EASE_IN_OUT } from "./timing"; /** - * Wrapper to provide `scrollTo` fallback for older browsers + * Wrapper to allow use of the `behavior: smooth` option on supporting browsers * * @internal * @param {ScrollToOptions} options Scroll options @@ -15,12 +15,27 @@ const tryScroll = (options) => { } }; +/** + * Wrapper to allow use of the `preventScroll` option on supporting browsers + * + * @internal + * @param {HTMLElement} element Target element + */ +const tryFocus = (element) => { + try { + element.focus({ preventScroll: true }); + } catch (e) { + element.focus(); + } +}; + /** * Available options used to control softScroll behaviour * * @typedef {Object} Options * @property {?number} padding Buffer above element (in pixels) * @property {?number} duration Scroll duration (in milliseconds) + * @property {?boolean} focus Move keyboard focus to element * @property {?easingFunction} timing Easing function */ @@ -63,6 +78,7 @@ const animateScroll = (target, duration, timing) => { const simpleScroll = (target, options) => { const padding = (options && options.padding) || 0; const duration = (options && options.duration) || 0; + const focus = (options && options.focus); const timing = (options && options.timing) || TIMING_EASE_IN_OUT; const target_y = getDocumentYOffset(target) - padding; @@ -71,6 +87,10 @@ const simpleScroll = (target, options) => { } else { animateScroll(target_y, duration, timing); } + + if (focus) { + tryFocus(target); + } }; export { simpleScroll }; From ffe734f1129f9195a5b141e61e5830fd6291ee7a Mon Sep 17 00:00:00 2001 From: clvarley Date: Fri, 23 Dec 2022 09:33:46 +0000 Subject: [PATCH 2/4] Respect users preference of 'prefers-reduced-motion' setting --- src/a11y.js | 10 ++++++++++ src/scroll.js | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 src/a11y.js diff --git a/src/a11y.js b/src/a11y.js new file mode 100644 index 0000000..02e2f17 --- /dev/null +++ b/src/a11y.js @@ -0,0 +1,10 @@ +/** + * Determine whether or not the user has requested reduced motion + * + * @return {boolean} Reduced motion requested? + */ +const reducedMotion = () => { + return window.matchMedia("(prefers-reduced-motion)").matches; +}; + +export { reducedMotion }; diff --git a/src/scroll.js b/src/scroll.js index 79b200c..49a37a3 100644 --- a/src/scroll.js +++ b/src/scroll.js @@ -1,4 +1,5 @@ import { getDocumentYOffset } from "./position"; +import { reducedMotion } from "./a11y"; import { TIMING_EASE_IN_OUT } from "./timing"; /** @@ -82,7 +83,7 @@ const simpleScroll = (target, options) => { const timing = (options && options.timing) || TIMING_EASE_IN_OUT; const target_y = getDocumentYOffset(target) - padding; - if (!duration) { + if (!duration || reducedMotion()) { tryScroll({ top: target_y, left: 0, behavior: "smooth" }); } else { animateScroll(target_y, duration, timing); From 3b599349ed77a646d7f8645a42b33006b8b5c131 Mon Sep 17 00:00:00 2001 From: clvarley Date: Fri, 23 Dec 2022 09:39:17 +0000 Subject: [PATCH 3/4] Updated comment regarding `focus` option --- src/scroll.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scroll.js b/src/scroll.js index 49a37a3..422a47f 100644 --- a/src/scroll.js +++ b/src/scroll.js @@ -36,7 +36,7 @@ const tryFocus = (element) => { * @typedef {Object} Options * @property {?number} padding Buffer above element (in pixels) * @property {?number} duration Scroll duration (in milliseconds) - * @property {?boolean} focus Move keyboard focus to element + * @property {?boolean} focus Move focus to element after scroll * @property {?easingFunction} timing Easing function */ From 4757d2d39709c1a93087766d1dafd5c0be393608 Mon Sep 17 00:00:00 2001 From: clvarley Date: Fri, 23 Dec 2022 09:50:42 +0000 Subject: [PATCH 4/4] Bumped version number and updated readme --- README.md | 13 ++++++++++++- package.json | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0c96e0e..963038b 100644 --- a/README.md +++ b/README.md @@ -84,10 +84,21 @@ expose more in the future. | Property | Type | Purpose | Default | | :------- | :--- | :------ | :------ | -| `duration` | [`number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) | Time (in milliseconds) the scroll animation should take | 0 | +| `duration` | [`number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) | Time (in milliseconds) the scroll animation should take[*](#caveats) | 0 | | `padding` | [`number`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) | Padding (in pixels) to be left above the element | 0 | +| `focus` | [`boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) | Whether or not to focus the element after scroll | `false` | | `timing` | [`function`](#timing) | Function used to control how the animation will be timed | [TIMING_EASE_IN_OUT](#ease-in-out) | +## Caveats + +As standard `simpleScroll` respects the [`prefers-reduced-motion`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-reduced-motion) +setting. On systems where this flag has been enabled the `duration` and +`timing` options are silently ignored, with control instead being handled by the +default browser scrolling behaviour. + +If you find your scroll animations aren't respecting the `duration` option this +may be why. + ## Timing By default, `simpleScroll` uses a [cubic ease-in-out](https://easings.net/#easeInOutCubic) diff --git a/package.json b/package.json index bcd26f4..52459ee 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@clvarley/simple-scroll", - "version": "1.0.1", + "version": "1.1.0", "description": "Simple utility to make scrolling elements into view easier.", "type": "module", "keywords": [