-
Notifications
You must be signed in to change notification settings - Fork 86
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
399 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,3 +83,8 @@ dt { | |
dd { | ||
margin-left: 20px; | ||
} | ||
|
||
em { | ||
font-style: normal; | ||
font-weight: bold; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<template> | ||
|
||
<DocsPageTemplate> | ||
|
||
<DocsPageSection title="1. Install the plugin" anchor="#install-plugin"> | ||
<p>Kolibri Design System (KDS) is a Vue plugin. Register it in your application alongside scripts that are needed for its full functioning:</p> | ||
|
||
<!-- eslint-disable --> | ||
<DocsShowCode language="javascript"> | ||
import KThemePlugin from 'kolibri-design-system/lib/KThemePlugin'; | ||
import trackInputModality from 'kolibri-design-system/lib/styles/trackInputModality'; | ||
import trackMediaType from 'kolibri-design-system/lib/styles/trackMediaType'; | ||
|
||
Vue.use(KThemePlugin); | ||
|
||
trackInputModality(); | ||
trackMediaType(); | ||
</DocsShowCode> | ||
<!-- eslint-enable --> | ||
|
||
This ensures the following: | ||
|
||
<ul> | ||
<li>Installs <code>$themeBrand</code>, <code>$themeTokens</code> <code>$themePalette</code>, and <code>$computedClass</code> helpers on all Vue instances.</li> | ||
<li>Provides <code>$coreOutline</code>, <code>$inputModality</code>, <code>$mediaType</code>, and <code>$isPrint</code> computed properties as well as <code>$print</code> method to all Vue instances.</li> | ||
<li>Globally registers all KDS Vue components.</li> | ||
<li>Inserts assertive and polite ARIA live regions to your application's document body (see <DocsInternalLink href="/usekliveregion" text="useKLiveRegion" /> to understand how to utilize them).</li> | ||
</ul> | ||
</DocsPageSection> | ||
|
||
<DocsPageSection title="2. Initialize theme" anchor="#initialize-theme"> | ||
<p> | ||
Until this section is better documented (TODO link GH issue), refer to <DocsExternalLink href="https://github.com/learningequality/kolibri/blob/develop/kolibri/core/assets/src/styles/initializeTheme.js" text="Kolibri's initializeTheme.js" />. | ||
</p> | ||
</DocsPageSection> | ||
|
||
</DocsPageTemplate> | ||
|
||
</template> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
<template> | ||
|
||
<DocsPageTemplate apiDocs> | ||
|
||
<DocsPageSection title="Overview" anchor="#overview"> | ||
<p>A composable that offers <code>sendPoliteMessage</code> and <code>sendAssertiveMessage</code> functions that send polite and assertive messages to their corresponding ARIA live regions.</p> | ||
</DocsPageSection> | ||
|
||
<DocsPageSection title="When to use live regions" anchor="#usage"> | ||
<p>Before sending messages to live regions, always research carefully if you really need it for the task ahead. Live regions can be <DocsExternalLink href="https://www.sarasoueidan.com/blog/accessible-notifications-with-aria-live-regions-part-2/#avoid-live-regions-if-you-can" text="buggy and inconsistent" />. There are often better alternatives, such as utilizing <DocsExternalLink href="https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes" text="WAI-ARIA attributes" />. A good rule of thumb is to use live regions only when there's no other way.</p> | ||
</DocsPageSection> | ||
|
||
<DocsPageSection title="Usage" anchor="#usage"> | ||
<p>Since polite and assertive regions are inserted to an application's document body automatically <DocsInternalLink href="/installation#install-plugin" text="during the KDS installation process" />, the only thing you need to do to deliver messages is to import and call <code>sendPoliteMessage</code> or <code>sendAssertiveMessage</code> from any place in your application.</p> | ||
|
||
<p>These two methods are also used internally from some KDS components to provide a11y out of the box. Always check that you don't send messages to announce updates that are already being announced from KDS to prevent from duplicate announcements.</p> | ||
|
||
<h3>Polite message</h3> | ||
|
||
<p>Sending a polite message updates the text content of <code>aria-live="polite"</code> region. <em>Use it to send messages that can wait to be announced until the user is idle. This message should typically be the most commonly used.</em></p> | ||
|
||
<p>Send polite messages with <code>sendPoliteMessage(message)</code>:</p> | ||
|
||
<!-- eslint-disable --> | ||
<!-- prevent prettier from changing indentation --> | ||
<DocsShowCode language="javascript"> | ||
import useKLiveRegion from 'kolibri-design-system/lib/composables/useKLiveRegion'; | ||
|
||
export default { | ||
setup() { | ||
const { sendPoliteMessage } = useKLiveRegion(); | ||
sendPoliteMessage('Polite message'); | ||
} | ||
}; | ||
</DocsShowCode> | ||
<!-- eslint-enable --> | ||
|
||
<h3>Assertive message</h3> | ||
|
||
<p>Sending an assertive message updates the text content of <code>aria-live="assertive"</code> region. <em>It should be used with caution because it disrupts the user's flow. Use it only to send messages that require immediate attention, such as errors.</em></p> | ||
|
||
<p>Send assertive messages with <code>sendAssertiveMessage(message)</code>:</p> | ||
|
||
<!-- eslint-disable --> | ||
<!-- prevent prettier from changing indentation --> | ||
<DocsShowCode language="javascript"> | ||
import useKLiveRegion from 'kolibri-design-system/lib/composables/useKLiveRegion'; | ||
|
||
export default { | ||
setup() { | ||
const { sendAssertiveMessage } = useKLiveRegion(); | ||
sendPoliteMessage('Assertive message'); | ||
} | ||
}; | ||
</DocsShowCode> | ||
<!-- eslint-enable --> | ||
</DocsPageSection> | ||
|
||
<DocsPageSection title="Demo" anchor="#demo"> | ||
<p>Send messages below and turn on your screen reader or observe the content of <code><div id="k-live-region"></code> in the browser console.</p> | ||
|
||
<DocsShow language="html"> | ||
<KTextbox label="Polite message" :value="politeMessageInput" @input="updatePoliteMessage" /> | ||
<KButton @click="sendPoliteMessage(politeMessageInput)"> | ||
Send | ||
</KButton> | ||
</DocsShow> | ||
|
||
<DocsShow language="html"> | ||
<KTextbox label="Assertive message" :value="assertiveMessageInput" @input="updateAssertiveMessage" /> | ||
<KButton @click="sendAssertiveMessage(assertiveMessageInput)"> | ||
Send | ||
</KButton> | ||
</DocsShow> | ||
</DocsPageSection> | ||
|
||
<DocsPageSection title="Related" anchor="#related"> | ||
<ul> | ||
<li> | ||
<DocsInternalLink href="/installation#initialize-dom" text="KDS installation step" /> that attaches live regions to an application's DOM | ||
</li> | ||
</ul> | ||
</DocsPageSection> | ||
</DocsPageTemplate> | ||
|
||
</template> | ||
|
||
|
||
<script> | ||
import { ref } from '@vue/composition-api'; | ||
import useKLiveRegion from '../../lib/composables/useKLiveRegion'; | ||
export default { | ||
setup() { | ||
const { _mountLiveRegion, sendPoliteMessage, sendAssertiveMessage } = useKLiveRegion(); | ||
const politeMessageInput = ref('Polite hello'); | ||
const updatePoliteMessage = message => { | ||
politeMessageInput.value = message; | ||
}; | ||
const assertiveMessageInput = ref('I cannot wait'); | ||
const updateAssertiveMessage = message => { | ||
assertiveMessageInput.value = message; | ||
}; | ||
return { | ||
_mountLiveRegion, | ||
updatePoliteMessage, | ||
politeMessageInput, | ||
updateAssertiveMessage, | ||
assertiveMessageInput, | ||
sendPoliteMessage, | ||
sendAssertiveMessage, | ||
}; | ||
}, | ||
mounted() { | ||
this._mountLiveRegion(this.$root.$el); | ||
}, | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
import useKLiveRegion from '../index.js'; | ||
|
||
const { _mountLiveRegion, sendPoliteMessage, sendAssertiveMessage } = useKLiveRegion(); | ||
function removeWhitespaceFromHtml(htmlString) { | ||
// https://stackoverflow.com/a/33108909 | ||
return htmlString.replace(/>\s+|\s+</g, function(m) { | ||
return m.trim(); | ||
}); | ||
} | ||
|
||
// check that document.body.innerHTML includes html string | ||
function assertDocumentBodyIncludes(htmlString) { | ||
expect( | ||
removeWhitespaceFromHtml(document.body.innerHTML).includes(removeWhitespaceFromHtml(htmlString)) | ||
).toBeTruthy(); | ||
} | ||
|
||
describe('useKLiveRegion', () => { | ||
it(`'_mountLiveRegion' inserts the live regions to a given element`, () => { | ||
expect(document.body.innerHTML).toEqual(''); | ||
|
||
_mountLiveRegion(); | ||
|
||
assertDocumentBodyIncludes(` | ||
<div id="k-live-region" class="visuallyhidden"> | ||
<div aria-live="polite"> | ||
</div> | ||
<div aria-live="assertive"> | ||
</div> | ||
</div> | ||
`); | ||
}); | ||
|
||
it(`'sendPoliteMessage' updates the live region with the message`, async () => { | ||
_mountLiveRegion(); | ||
await new Promise(resolve => setTimeout(resolve, 100)); | ||
|
||
assertDocumentBodyIncludes(` | ||
<div id="k-live-region" class="visuallyhidden"> | ||
<div aria-live="polite"> | ||
</div> | ||
<div aria-live="assertive"> | ||
</div> | ||
</div> | ||
`); | ||
|
||
sendPoliteMessage('Polite message'); | ||
await new Promise(resolve => setTimeout(resolve, 100)); | ||
assertDocumentBodyIncludes(` | ||
<div id="k-live-region" class="visuallyhidden"> | ||
<div aria-live="polite"> | ||
Polite message | ||
</div> | ||
<div aria-live="assertive"> | ||
</div> | ||
</div> | ||
`); | ||
|
||
// cleanup | ||
sendPoliteMessage(''); | ||
}); | ||
|
||
it(`'sendAssertiveMessage' updates the live region with the message`, async () => { | ||
_mountLiveRegion(); | ||
await new Promise(resolve => setTimeout(resolve, 100)); | ||
|
||
assertDocumentBodyIncludes(` | ||
<div id="k-live-region" class="visuallyhidden"> | ||
<div aria-live="polite"> | ||
</div> | ||
<div aria-live="assertive"> | ||
</div> | ||
</div> | ||
`); | ||
|
||
sendAssertiveMessage('Assertive message'); | ||
await new Promise(resolve => setTimeout(resolve, 100)); | ||
assertDocumentBodyIncludes(` | ||
<div id="k-live-region" class="visuallyhidden"> | ||
<div aria-live="polite"> | ||
</div> | ||
<div aria-live="assertive"> | ||
Assertive message | ||
</div> | ||
</div> | ||
`); | ||
|
||
// cleanup | ||
sendAssertiveMessage(''); | ||
}); | ||
}); |
Oops, something went wrong.