mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-23 23:33:54 +00:00
Disable animations when user prefers reduced motion
When browser preference for reduced motion is enabled: * Disables bolding of table of contents * Disables sticky header transition Bug: T254399 Change-Id: I8ef9e59b258fed977ce370da352b1924832d842b
This commit is contained in:
parent
7d75bb37ad
commit
c269419af3
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
{
|
||||
"resourceModule": "skins.vector.legacy.js",
|
||||
"maxSize": "2 kB"
|
||||
"maxSize": "2.2 kB"
|
||||
},
|
||||
{
|
||||
"resourceModule": "skins.vector.search",
|
||||
|
|
|
@ -53,6 +53,15 @@ module.exports = function tableOfContents( props ) {
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the user prefer reduced motion?
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
const prefersReducedMotion = () => {
|
||||
return window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets an `ACTIVE_SECTION_CLASS` on the element with an id that matches `id`.
|
||||
* If the element is not a top level heading (e.g. element with the
|
||||
|
@ -78,7 +87,12 @@ module.exports = function tableOfContents( props ) {
|
|||
|
||||
const topSection = /** @type {HTMLElement} */ ( selectedTocSection.closest( `.${PARENT_SECTION_CLASS}` ) );
|
||||
|
||||
if ( selectedTocSection === topSection ) {
|
||||
// The bolding of sections is arguably not "motion", however does provide a distraction to readers
|
||||
// who are scrolling by visibly changing the table of contents. This can be removed if someone has
|
||||
// a strong argument for why this should not be considered motion.
|
||||
if ( prefersReducedMotion() ) {
|
||||
return;
|
||||
} else if ( selectedTocSection === topSection ) {
|
||||
activeTopSection = topSection;
|
||||
activeTopSection.classList.add( ACTIVE_SECTION_CLASS );
|
||||
} else {
|
||||
|
@ -144,8 +158,7 @@ module.exports = function tableOfContents( props ) {
|
|||
Math.min( containerRect.bottom, window.innerHeight );
|
||||
|
||||
// Respect 'prefers-reduced-motion' user preference
|
||||
const mediaQuery = window.matchMedia( '(prefers-reduced-motion: reduce)' );
|
||||
const scrollBehavior = ( !mediaQuery || !mediaQuery.matches ) ? 'smooth' : undefined;
|
||||
const scrollBehavior = prefersReducedMotion() ? 'smooth' : undefined;
|
||||
|
||||
// Manually increment and decrement TOC scroll rather than using scrollToView
|
||||
// in order to account for threshold
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
justify-content: space-between;
|
||||
box-sizing: border-box;
|
||||
|
||||
// If the user has expressed their preference for reduced motion, then disable animation for the sticky header.
|
||||
@media ( prefers-reduced-motion: reduce ) {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
@media ( min-width: @width-breakpoint-desktop ) {
|
||||
padding: 6px 25px;
|
||||
}
|
||||
|
|
|
@ -29,3 +29,23 @@
|
|||
@media print {
|
||||
@import './layouts/print.less';
|
||||
}
|
||||
|
||||
/**
|
||||
* Respect users who prefer reduced motion.
|
||||
* This code can be removed if and when it is upstreamed to ResourceLoaderSkinModule
|
||||
* (see T254399).
|
||||
*/
|
||||
/* stylelint-disable declaration-no-important, time-min-milliseconds */
|
||||
@media ( prefers-reduced-motion: reduce ) {
|
||||
*,
|
||||
:before,
|
||||
:after {
|
||||
animation-delay: -1ms !important; /* 1 */
|
||||
animation-duration: 1ms !important; /* 1 */
|
||||
animation-iteration-count: 1 !important; /* 1 */
|
||||
background-attachment: initial !important; /* 2 */
|
||||
scroll-behavior: auto !important; /* 3 */
|
||||
transition-delay: 0s !important; /* 4 */
|
||||
transition-duration: 0s !important; /* 4 */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -92,6 +92,11 @@ function mount( templateProps = {} ) {
|
|||
}
|
||||
|
||||
describe( 'Table of contents', () => {
|
||||
beforeEach( () => {
|
||||
// @ts-ignore
|
||||
global.window.matchMedia = jest.fn( () => ( {} ) );
|
||||
} );
|
||||
|
||||
describe( 'renders', () => {
|
||||
test( 'when `vector-is-collapse-sections-enabled` is false', () => {
|
||||
const toc = mount();
|
||||
|
|
Loading…
Reference in a new issue