Skip to content

a11y reduced motion #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 4, 2021
Merged
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ import '@github/typing-effect-element'
</typing-effect>
```

## 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][].
Expand Down
2 changes: 1 addition & 1 deletion karma.config.cjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module.exports = function(config) {
module.exports = function (config) {
config.set({
frameworks: ['mocha', 'chai'],
files: [
Expand Down
22 changes: 18 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ class TypingEffectElement extends HTMLElement {
}
}

get prefersReducedMotion(): boolean {
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
}

Expand All @@ -51,6 +58,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
}

Expand Down Expand Up @@ -82,12 +92,16 @@ async function typeLines(
lineDelay: number
): Promise<void> {
for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
for (const character of lines[lineIndex].split('')) {
await wait(characterDelay)
contentElement.innerHTML += character
if (characterDelay === 0) {
contentElement.append(lines[lineIndex])
} else {
for (const character of lines[lineIndex].split('')) {
await wait(characterDelay)
contentElement.innerHTML += character
}
}

await wait(lineDelay)
if (lineDelay !== 0) await wait(lineDelay)
if (lineIndex < lines.length - 1) contentElement.append(document.createElement('br'))
}
}
Expand Down
41 changes: 41 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,21 @@ 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')
document.body.append(typingEffectElement)
Expand All @@ -76,6 +91,32 @@ describe('typing-effect', function () {
assert.equal(typingEffectElement.lineDelay, 40)
})
})

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)

assert.equal(window.matchMedia('(prefers-reduced-motion)').matches, true)
assert.equal(typingEffectElement.characterDelay, 0)
assert.equal(typingEffectElement.lineDelay, 0)
})
})
})

function once(element, eventName) {
Expand Down