Last January, I wrote about my approach to building an accessible disclosure with vanilla JavaScript. Today, I want to share how to approach this with Petite Vue, an alternative distribution of Vue specifically optimized for progressive enhancement.
The disclosure pattern
What is a disclosure? Let’s refer to the ARIA Authoring Practices Guide (APG):
“A disclosure is a widget that enables content to be either collapsed (hidden) or expanded (visible). It has two elements: a disclosure button and a section of content whose visibility is controlled by the button. When the controlled content is hidden, the button is often styled as a typical push button with a right-pointing arrow or triangle to hint that activating the button will display additional content. When the content is visible, the arrow or triangle typically points down.”
Building the disclosure
Here’s the HTML for our accessible disclosure. You can view a demo on CodePen. We’ll discuss how it works below.
<div class="disclosure" v-scope="{ isOpen: false }">
<p v-cloak>
<button aria-controls="content" :aria-expanded="isOpen" @click="isOpen = !isOpen">
Toggle
</button>
</p>
<div id="content" v-show="isOpen">
<p>Hello there!</p>
</div>
</div>
- The
v-scope
directive (unique to Petite Vue) marks a region of the page that should be controlled by Petite Vue, along with its state. We have a single piece of state,isOpen
, with an initial value offalse
. - Combined with the CSS rule
[v-cloak] { display: none; }
, thev-cloak
directive hides the paragraph containing the button until Petite Vue is ready. We’re using it in the name of unobtrusive JavaScript. This way, if the JavaScript fails to load, the user won’t be left with an inoperable button. - The
aria-controls
attribute points to the ID of the content that’s controlled by the button. It’s a hint for assistive technologies. - The
aria-expanded
attribute indicates whether the content is collapsed or expanded. It’s another hint for assistive technologies. The:
prefix is a shorthand for thev-bind
directive. It tells Petite Vue to bind the value of thearia-expanded
attribute to the value of theisOpen
state. - The
@click
directive is a shorthand for thev-on
directive with the:click
argument. It tells Petite Vue that, on click, it should toggle theisOpen
state. - The
v-show
directive tells Petite Vue to toggle the visibility of the content based on the value of theisOpen
state.
Here’s the CSS for our accessible disclosure. It hides the paragraph with the v-cloak
directive and adds the arrow/triangle that’s mentioned in the ARIA APG. As I said in my original article, we’re adding the arrow/triangle with CSS because it’s purely decorative. It should be ignored by assistive technologies.
[v-cloak] {
display: none;
}
.disclosure [aria-expanded] {
display: flex;
align-items: center;
}
.disclosure [aria-expanded]::before {
content: "";
width: 0.5em;
height: 0.5em;
margin-right: 0.25em;
background: currentColor;
}
.disclosure [aria-expanded="false"]::before {
clip-path: polygon(0 0, 100% 50%, 0 100%);
}
.disclosure [aria-expanded="true"]::before {
clip-path: polygon(0 0, 100% 0, 50% 100%);
}
Summary
A disclosure is a widget that enables content to be either collapsed (hidden) or expanded (visible). In this article, we used Petite Vue to build one. Petite Vue is an alternative distribution of Vue specifically optimized for progressive enhancement. Until Petite Vue loads—and if it fails to load—users will only see the content. Once Petite Vue loads, the content is progressively enhanced into a disclosure.