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 of false.
  • Combined with the CSS rule [v-cloak] { display: none; }, the v-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 the v-bind directive. It tells Petite Vue to bind the value of the aria-expanded attribute to the value of the isOpen state.
  • The @click directive is a shorthand for the v-on directive with the :click argument. It tells Petite Vue that, on click, it should toggle the isOpen state.
  • The v-show directive tells Petite Vue to toggle the visibility of the content based on the value of the isOpen 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.