From 2579a1eee19e65f56760a74b56348fad9c1121b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Tue, 4 May 2021 18:08:36 +0100 Subject: [PATCH 01/13] fix unpkg link --- examples/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/index.html b/examples/index.html index d6f3b87..9855aaa 100644 --- a/examples/index.html +++ b/examples/index.html @@ -11,7 +11,7 @@ From f98bd8b7c0639ea41e4eb5fca5618ae4ae48cd05 Mon Sep 17 00:00:00 2001 From: Jamie C Date: Thu, 27 May 2021 12:43:09 -0500 Subject: [PATCH 02/13] Adds tests and getters to set character and line delay to 0 when reduced motion is preferred by user. --- .eslintrc.json | 3 ++- karma.config.cjs | 2 +- src/index.ts | 14 ++++++++++++++ test/test.js | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 48300eb..2318aef 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,6 +6,7 @@ "plugin:github/typescript" ], "globals": { - "CustomElementElement": "readonly" + "CustomElementElement": "readonly", + "module": true } } diff --git a/karma.config.cjs b/karma.config.cjs index d18e564..a74e945 100644 --- a/karma.config.cjs +++ b/karma.config.cjs @@ -1,4 +1,4 @@ -module.exports = function(config) { +module.exports = function (config) { config.set({ frameworks: ['mocha', 'chai'], files: [ diff --git a/src/index.ts b/src/index.ts index 8dcd117..8d29907 100644 --- a/src/index.ts +++ b/src/index.ts @@ -39,7 +39,18 @@ class TypingEffectElement extends HTMLElement { } } + get prefersReducedMotion(): boolean { + if (this.getAttribute('data-reduced-motion') === 'false') { + return false + } else { + return window.matchMedia('(prefers-reduced-motion)').matches + } + } + get characterDelay(): number { + if (this.prefersReducedMotion) { + return 0 + } return Math.max(Math.min(0, Math.floor(Number(this.getAttribute('data-character-delay'))), 2_147_483_647)) || 40 } @@ -51,6 +62,9 @@ class TypingEffectElement extends HTMLElement { } get lineDelay(): number { + if (this.prefersReducedMotion) { + return 0 + } return Math.max(Math.min(0, Math.floor(Number(this.getAttribute('data-line-delay'))), 2_147_483_647)) || 40 } diff --git a/test/test.js b/test/test.js index 384aa84..bcad264 100644 --- a/test/test.js +++ b/test/test.js @@ -70,12 +70,34 @@ describe('typing-effect', function () { describe('delay attributes', function () { it('uses defaults when no delays specified', function () { const typingEffectElement = document.createElement('typing-effect') + typingEffectElement.setAttribute('data-reduced-motion', false) document.body.append(typingEffectElement) assert.equal(typingEffectElement.characterDelay, 40) assert.equal(typingEffectElement.lineDelay, 40) }) }) + + describe('a11y considerations', function () { + it('sets delay to 0 when media query matches (prefers-reduced-motion)', function () { + const typingEffectElement = document.createElement('typing-effect') + document.body.append(typingEffectElement) + + assert.equal(window.matchMedia('(prefers-reduced-motion)').matches, true) + assert.equal(typingEffectElement.characterDelay, 0) + assert.equal(typingEffectElement.lineDelay, 0) + }) + + it('uses data-reduced-motion attribute to override window media query', function () { + const typingEffectElement = document.createElement('typing-effect') + typingEffectElement.setAttribute('data-reduced-motion', false) + document.body.append(typingEffectElement) + + assert.equal(window.matchMedia('(prefers-reduced-motion)').matches, true) + assert.equal(typingEffectElement.characterDelay, 40) + assert.equal(typingEffectElement.lineDelay, 40) + }) + }) }) function once(element, eventName) { From 7478979f4f185bfa718969056b66c6dd99b3c373 Mon Sep 17 00:00:00 2001 From: Jamie C Date: Thu, 27 May 2021 13:11:16 -0500 Subject: [PATCH 03/13] Appends line content without delay instead of character by character for reduced motion setting. --- src/index.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8d29907..be59172 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,7 +11,8 @@ const loaded: Promise = (function () { class TypingEffectElement extends HTMLElement { async connectedCallback(): Promise { await loaded - if (this.content) await typeLines(this.lines, this.content, this.characterDelay, this.lineDelay) + if (this.content) + await typeLines(this.lines, this.content, this.characterDelay, this.lineDelay, this.prefersReducedMotion) if (this.cursor) this.cursor.hidden = true this.dispatchEvent( new CustomEvent('typing:complete', { @@ -93,12 +94,17 @@ async function typeLines( lines: string[], contentElement: HTMLElement, characterDelay: number, - lineDelay: number + lineDelay: number, + reduceMotion: boolean ): Promise { for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { - for (const character of lines[lineIndex].split('')) { - await wait(characterDelay) - contentElement.innerHTML += character + if (reduceMotion) { + contentElement.append(lines[lineIndex]) + } else { + for (const character of lines[lineIndex].split('')) { + await wait(characterDelay) + contentElement.innerHTML += character + } } await wait(lineDelay) From f3165c6521b3ab74495fc5662263401440028717 Mon Sep 17 00:00:00 2001 From: Jamie C Date: Thu, 27 May 2021 13:15:47 -0500 Subject: [PATCH 04/13] Adds a note on docs about reduced motion. --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 909e2cd..b9da737 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A custom element that shows text as if it were being typed ## Installation ``` -$ npm install @github/typing-effect-element +npm install @github/typing-effect-element ``` ## Usage @@ -21,6 +21,16 @@ import '@github/typing-effect-element' ``` +## Accessibility + +This component detects whether `prefers-reduced-motion` is set on the window + +```js +window.matchMedia('(prefers-reduced-motion)').matches === true +``` + +If this evaluates to true, any content lines provided will be appended immediately rather than being typed out with a delay. + ## Browser support Browsers without native [custom element support][support] require a [polyfill][]. From dcfafd265dee9ada23062bdd9500cd8159ecab10 Mon Sep 17 00:00:00 2001 From: Jamie C Date: Thu, 27 May 2021 14:00:50 -0500 Subject: [PATCH 05/13] Adds a condition for reduced motion where the data-reduced-motion attribute will override the window media match. If data-reduced-motion is set to true, the component will NOT animate. If data-reduced-motion is set to false, the component WILL animate. --- README.md | 20 +++++++++++++++++++- src/index.ts | 2 ++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b9da737..9cea248 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ import '@github/typing-effect-element' ## Accessibility -This component detects whether `prefers-reduced-motion` is set on the window +This component detects whether `prefers-reduced-motion` is set on the window: ```js window.matchMedia('(prefers-reduced-motion)').matches === true @@ -31,6 +31,24 @@ window.matchMedia('(prefers-reduced-motion)').matches === true If this evaluates to true, any content lines provided will be appended immediately rather than being typed out with a delay. +The data attribute `data-reduced-motion` can be used to override the window media value. + +```html + + + | + + + + + | + +``` + ## Browser support Browsers without native [custom element support][support] require a [polyfill][]. diff --git a/src/index.ts b/src/index.ts index be59172..4188a2f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -43,6 +43,8 @@ class TypingEffectElement extends HTMLElement { get prefersReducedMotion(): boolean { if (this.getAttribute('data-reduced-motion') === 'false') { return false + } else if (this.getAttribute('data-reduced-motion') === 'true') { + return true } else { return window.matchMedia('(prefers-reduced-motion)').matches } From 3d6d6447210584d5b14f02c11156c29c8c07256e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 28 May 2021 09:30:03 +0100 Subject: [PATCH 06/13] Mock `window.matchMedia` --- test/test.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/test.js b/test/test.js index bcad264..dc872d0 100644 --- a/test/test.js +++ b/test/test.js @@ -79,6 +79,21 @@ describe('typing-effect', function () { }) describe('a11y considerations', function () { + let realMatchMedia + before(() => { + realMatchMedia = window.matchMedia + window.matchMedia = mediaString => { + if (mediaString === '(prefers-reduced-motion)') { + return {matches: true} + } + return realMatchMedia(mediaString) + } + }) + + after(() => { + window.matchMedia = realMatchMedia + }) + it('sets delay to 0 when media query matches (prefers-reduced-motion)', function () { const typingEffectElement = document.createElement('typing-effect') document.body.append(typingEffectElement) From 450773ff6302a4ee00ccf99b114bc54acf918c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 28 May 2021 09:31:51 +0100 Subject: [PATCH 07/13] Set CI to run on Pull Requests as well --- .github/workflows/nodejs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml index 56849b9..2777730 100644 --- a/.github/workflows/nodejs.yml +++ b/.github/workflows/nodejs.yml @@ -1,6 +1,6 @@ name: Node CI -on: [push] +on: [push, pull_request] jobs: build: runs-on: macos-latest From 8de1eb210d42e072aea485ad5de6a18858f9e701 Mon Sep 17 00:00:00 2001 From: Jamie C Date: Fri, 28 May 2021 11:26:12 -0500 Subject: [PATCH 08/13] Reverts some inadvertent markdown formatting changes and unnecessary eslint config entry. --- .eslintrc.json | 3 +-- README.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 2318aef..48300eb 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,7 +6,6 @@ "plugin:github/typescript" ], "globals": { - "CustomElementElement": "readonly", - "module": true + "CustomElementElement": "readonly" } } diff --git a/README.md b/README.md index 9cea248..b08d3aa 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A custom element that shows text as if it were being typed ## Installation ``` -npm install @github/typing-effect-element +$ npm install @github/typing-effect-element ``` ## Usage From b07b9ba87a10ef68acf0531f66a6b80e10a5acd5 Mon Sep 17 00:00:00 2001 From: Jamie C Date: Tue, 1 Jun 2021 16:08:44 -0500 Subject: [PATCH 09/13] Adds mock condition for window.matchMedia for default case (prevents the test from setting delay to 0 when user has reduced motion set on their system). Removes code paths and mentions of attribute data-reduced-motion because including an escape hatch right now might be a bit confusing. --- README.md | 18 ------------------ src/index.ts | 8 +------- test/test.js | 26 +++++++++++++++----------- 3 files changed, 16 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index b08d3aa..ec2c204 100644 --- a/README.md +++ b/README.md @@ -31,24 +31,6 @@ window.matchMedia('(prefers-reduced-motion)').matches === true If this evaluates to true, any content lines provided will be appended immediately rather than being typed out with a delay. -The data attribute `data-reduced-motion` can be used to override the window media value. - -```html - - - | - - - - - | - -``` - ## Browser support Browsers without native [custom element support][support] require a [polyfill][]. diff --git a/src/index.ts b/src/index.ts index 4188a2f..f6cf5b6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,13 +41,7 @@ class TypingEffectElement extends HTMLElement { } get prefersReducedMotion(): boolean { - if (this.getAttribute('data-reduced-motion') === 'false') { - return false - } else if (this.getAttribute('data-reduced-motion') === 'true') { - return true - } else { - return window.matchMedia('(prefers-reduced-motion)').matches - } + return window.matchMedia('(prefers-reduced-motion)').matches } get characterDelay(): number { diff --git a/test/test.js b/test/test.js index dc872d0..32192e8 100644 --- a/test/test.js +++ b/test/test.js @@ -68,9 +68,23 @@ describe('typing-effect', function () { }) describe('delay attributes', function () { + let realMatchMedia + before(() => { + realMatchMedia = window.matchMedia + window.matchMedia = mediaString => { + if (mediaString === '(prefers-reduced-motion)') { + return {matches: false} + } + return realMatchMedia(mediaString) + } + }) + + after(() => { + window.matchMedia = realMatchMedia + }) + it('uses defaults when no delays specified', function () { const typingEffectElement = document.createElement('typing-effect') - typingEffectElement.setAttribute('data-reduced-motion', false) document.body.append(typingEffectElement) assert.equal(typingEffectElement.characterDelay, 40) @@ -102,16 +116,6 @@ describe('typing-effect', function () { assert.equal(typingEffectElement.characterDelay, 0) assert.equal(typingEffectElement.lineDelay, 0) }) - - it('uses data-reduced-motion attribute to override window media query', function () { - const typingEffectElement = document.createElement('typing-effect') - typingEffectElement.setAttribute('data-reduced-motion', false) - document.body.append(typingEffectElement) - - assert.equal(window.matchMedia('(prefers-reduced-motion)').matches, true) - assert.equal(typingEffectElement.characterDelay, 40) - assert.equal(typingEffectElement.lineDelay, 40) - }) }) }) From 7476b94ce444a6d6623b8c218cbd671445fb325b Mon Sep 17 00:00:00 2001 From: Tenki Date: Thu, 3 Jun 2021 00:46:32 +0800 Subject: [PATCH 10/13] Fix Delay Attributes Fixed the bug that lineDelay and characterDelay aren't parsed correctly --- src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 8dcd117..89fb70d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -40,7 +40,7 @@ class TypingEffectElement extends HTMLElement { } get characterDelay(): number { - return Math.max(Math.min(0, Math.floor(Number(this.getAttribute('data-character-delay'))), 2_147_483_647)) || 40 + return Math.max(0, Math.min(Math.floor(Number(this.getAttribute('data-character-delay'))), 2_147_483_647)) || 40 } set characterDelay(value: number) { @@ -51,7 +51,7 @@ class TypingEffectElement extends HTMLElement { } get lineDelay(): number { - return Math.max(Math.min(0, Math.floor(Number(this.getAttribute('data-line-delay'))), 2_147_483_647)) || 40 + return Math.max(0, Math.min(Math.floor(Number(this.getAttribute('data-line-delay'))), 2_147_483_647)) || 40 } set lineDelay(value: number) { From 77fe7b0a6b99dd1b421ee0908b40c09d23c6131d Mon Sep 17 00:00:00 2001 From: Jamie C Date: Wed, 2 Jun 2021 14:36:36 -0500 Subject: [PATCH 11/13] Replace reduceMotion logic check in typeLines with characterDelay value check. Also adds a condition to skip the await call for lines if lineDelay is not 0. --- src/index.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index f6cf5b6..975b48d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,8 +11,7 @@ const loaded: Promise = (function () { class TypingEffectElement extends HTMLElement { async connectedCallback(): Promise { await loaded - if (this.content) - await typeLines(this.lines, this.content, this.characterDelay, this.lineDelay, this.prefersReducedMotion) + if (this.content) await typeLines(this.lines, this.content, this.characterDelay, this.lineDelay) if (this.cursor) this.cursor.hidden = true this.dispatchEvent( new CustomEvent('typing:complete', { @@ -90,11 +89,10 @@ async function typeLines( lines: string[], contentElement: HTMLElement, characterDelay: number, - lineDelay: number, - reduceMotion: boolean + lineDelay: number ): Promise { for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { - if (reduceMotion) { + if (characterDelay === 0) { contentElement.append(lines[lineIndex]) } else { for (const character of lines[lineIndex].split('')) { @@ -103,7 +101,7 @@ async function typeLines( } } - await wait(lineDelay) + if (lineDelay !== 0) await wait(lineDelay) if (lineIndex < lines.length - 1) contentElement.append(document.createElement('br')) } } From 6600872805697032b1d5b725c2758385068d335a Mon Sep 17 00:00:00 2001 From: Tenki Date: Thu, 3 Jun 2021 09:38:42 +0800 Subject: [PATCH 12/13] Add test for specifying delay attributes --- test/test.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/test.js b/test/test.js index 384aa84..d405663 100644 --- a/test/test.js +++ b/test/test.js @@ -75,6 +75,19 @@ describe('typing-effect', function () { assert.equal(typingEffectElement.characterDelay, 40) assert.equal(typingEffectElement.lineDelay, 40) }) + + it('uses specified delay attributes instead of using defaults', function () { + const characterDelay = 20 + const lineDelay = 20 + document.body.innerHTML = ` + + + ` + const typingEffectElement = document.querySelector('typing-effect') + + assert.equal(typingEffectElement.characterDelay, characterDelay) + assert.equal(typingEffectElement.lineDelay, lineDelay) + }) }) }) From 150ba58eaa2371c44fdbb1406f6765b8945db21c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristj=C3=A1n=20Oddsson?= Date: Fri, 4 Jun 2021 10:05:47 +0100 Subject: [PATCH 13/13] 0.1.0 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index aca66c9..5c8d4fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@github/typing-effect-element", - "version": "0.0.2", + "version": "0.1.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@github/typing-effect-element", - "version": "0.0.2", + "version": "0.1.0", "license": "MIT", "devDependencies": { "@github/prettier-config": "0.0.4", diff --git a/package.json b/package.json index 6c6f282..fe1278c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@github/typing-effect-element", - "version": "0.0.2", + "version": "0.1.0", "description": "A custom element that shows text as if it were being typed.", "main": "dist/index.js", "module": "dist/index.js",