Expandable

javascript

An expandable, sometimes called an accordion, is an element that can be hidden / revealed with a sliding transition.

From a purely visual standpoint, all you need is a container of class s-expandable and a child of class s-expandable--content. Toggle the state class is-expanded on the container to collapse / expand the content. Care must be taken to keep the collapsing functionality accessible.

<div class="s-card">
<button class="s-btn s-btn__filled"
data-controller="s-expandable-control"
data-s-expandable-control-toggle-class="is-selected"
aria-expanded="false"
aria-controls="expandable-example">

Show first paragraph
</button>
<div class="s-expandable" id="expandable-example">
<div class="s-expandable--content">

</div>
</div>
</div>

Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

Accusata reprimique interesset in sea, est graece dictas scriptorem ea. Consul facete mediocritatem quo et. Idque hendrerit theophrastus in vim, eum possit feugiat fastidii id. Idque invenire at quo, accusata salutandi sadipscing et qui. Eos doming adipiscing ea, eu pri debitis indoctum dissentiet. At libris labores adolescens eos, ex nec nobis aeterno.

It’s also possible to control the state of multiple elements from a single s-expandable-control by listing all the ids for the controlled elements in the aria-controls attribute.

<div class="s-card">
<button class="s-btn s-btn__filled"
data-controller="s-expandable-control"
data-s-expandable-control-toggle-class="is-selected"
aria-expanded="false"
aria-controls="expandable-first expandable-last">

Show first and last paragraphs
</button>
<div class="s-expandable" id="expandable-first">
<div class="s-expandable--content">

</div>
</div>

<div class="s-expandable" id="expandable-last">
<div class="s-expandable--content">

</div>
</div>
</div>

Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

Accusata reprimique interesset in sea, est graece dictas scriptorem ea. Consul facete mediocritatem quo et. Idque hendrerit theophrastus in vim, eum possit feugiat fastidii id. Idque invenire at quo, accusata salutandi sadipscing et qui. Eos doming adipiscing ea, eu pri debitis indoctum dissentiet. At libris labores adolescens eos, ex nec nobis aeterno.

Aenean aliquet vitae erat sed luctus. Nullam elementum orci id leo lacinia fringilla. Quisque rutrum mauris at mi rhoncus, vel vulputate erat pellentesque. Sed blandit rhoncus sem at pulvinar. Curabitur maximus, metus a facilisis efficitur, ipsum eros faucibus quam, nec mollis lectus nunc ut diam.

In the usual case in which you have a button or other clickable element that toggles the expanded state, you can use the built-in s-expandable-control functionality. See the JavaScript introduction for general information on JS in Stacks.

  1. Give all desired s-expandable elements an id attribute.
  2. Give your button an aria-controls attribute whose value is a space-separated list of all IDs in 1.
  3. Give your button an aria-expanded attribute whose value is true or false depending on the initial state of your expandables.
  4. Give your button a data-controller="s-expandable-control" attribute.
  5. If your button is an element that is not focusable by default, be sure to make it keyboard-reachable with tabindex="0"
  6. Give your button an aria-label attribute that makes it clear that this is a expanding/collapsing control, unless this is already clear from its text content

A common need is for one or more CSS classes to be applied to the expandable control whenever the state is toggled, e.g. to indicate a “selected” state. To achieve this, you can add the data-s-expandable-control-toggle-class attribute. The value should be a space-separated list of CSS classes. These classes will be added to the control whenever it expands the expandable, and removed whenever it collapses it.

See the previous section for an example of all of this.

If you are writing custom CSS to indicate the selected state of the expandable control, consider targetting [aria-controls="true"] instead of creating a new class.

If your expandable control is a checkbox or radio button, then the visibility of the expandable will be synchronized with the radio / checkbox state:


<div class="grid--cell">
<input class="s-radio" type="radio" name="mood-choice" id="mood-happy"
data-controller="s-expandable-control"
aria-controls="mood-happy-text" />

</div>
<div class="grid--cell">
<label class="d-block mb4 s-label fw-normal" for="mood-happy">Happy</label>
<div class="s-expandable" id="mood-happy-text">
<p class="s-expandable--content">@Svg.FaceSmile</p>
</div>
</div>
What is your mood?

When an s-expandable-control collapses or expands an element, it will fire an event of type s-expandable-control:hide or s-expandable-control:show, respectively. This event is fired synchronously. The event’s target element is the s-expandable-control element, not the expandable itself.