v1.0.0

<bmx-accordion-item>

A heading with a panel under it that opens and closes. Usable on its own - one of these is a disclosure, which is a pattern in its own right and the right one for "advanced options" or a single "show more" - and usable in a bmx-accordion, which coordinates a set of them.

7 properties · 1 events · 2 methods · 7 parts

Example

On its own, an item is a disclosure — the right pattern for one "show more":

It reports bmxToggle when it opens or closes.

Inside a bmx-accordion, the accordion owns whether it may be open at the same time as its neighbours:

Content of the first section. Content of the second section.
Show markup
<div class="row">
  <p style="margin: 0">On its own, an item is a disclosure — the right pattern for one "show more":</p>
</div>

<div class="row">
  <bmx-accordion-item
    id="ex-item"
    heading="Advanced options"
    style="max-inline-size: 40rem; border: 1px solid var(--bmx-border); border-radius: var(--bmx-radius-lg)"
  >
    <bmx-switch label="Send anonymous usage statistics"></bmx-switch>
  </bmx-accordion-item>
</div>

<div class="row">
  <span class="note" id="ex-item-out">It reports <code>bmxToggle</code> when it opens or closes.</span>
</div>

<div class="row">
  <p style="margin: 0">Inside a <code>bmx-accordion</code>, the accordion owns whether it may be open at the same time as its neighbours:</p>
</div>

<div class="row">
  <bmx-accordion style="max-inline-size: 40rem">
    <bmx-accordion-item heading="First" open>Content of the first section.</bmx-accordion-item>
    <bmx-accordion-item heading="Second">Content of the second section.</bmx-accordion-item>
  </bmx-accordion>
</div>

<script type="module">
  await customElements.whenDefined('bmx-accordion-item');

  const item = document.getElementById('ex-item');
  const out = document.getElementById('ex-item-out');

  item.addEventListener('bmxToggle', event => {
    out.textContent = `bmxToggle: value="${event.detail.value}", open ${event.detail.open}`;
  });
</script>

WHY THIS ONE OWNS BOTH HALVES AND bmx-tab-panel DOES NOT

The same constraint, answered the other way round. Both patterns need two IDREFs between a control and its panel, and an IDREF cannot cross a shadow boundary - so both ends must live in one root. For tabs that root has to be the parent's, because the tabs are drawn as a strip away from their panels. Here the heading sits directly above its own panel, so the natural root is this element's: the button and the region are both drawn here, the references resolve, and bmx-accordion never has to reach across a boundary to wire anything.

That is also what makes this usable standalone. A bmx-tab-panel alone is nothing; one of these alone is a working disclosure.

THE HEADING IS A HEADING

The button is wrapped in an element carrying role="heading" and aria-level, because a screen-reader user navigates a long page by its headings and an accordion whose sections are invisible to that navigation is a page they have to read linearly. heading-level is a property rather than a fixed 3, because the right level depends on what is above it on the page, which this component cannot know.

Properties

PropertyAttributeTypeDefaultDescription
badge badge string A short count or status, rendered after the heading text.
disabled disabled boolean false Whether it can be opened.
heading heading string The heading's text.
headingLevel heading-level number 3 The heading level this section sits at, as aria-level. Set by bmx-accordion from its own heading-level so a whole accordion is consistent; set it here when using an item on its own.
icon icon string An inline SVG string, rendered before the heading text.
open open boolean false Whether the panel is showing. Mutable, so pressing the heading changes it. Inside a bmx-accordion the accordion owns this - it is the thing that knows whether another panel has to close first - and writes it on every item.
value value string What this item is identified by in the accordion's expanded and in events. Falls back to the heading and then to its position, so a set of items written with headings alone still reports something distinguishable.

Events

EventDetailDescription
bmxToggle BmxAccordionToggleDetail Fired when the item opens or closes.

Methods

MethodSignatureDescription
setFocus setFocus(options?: FocusOptions) => Promise<void> Focus this item's heading button.
toggle toggle() => Promise<void> Open or close it, as pressing the heading would.

Slots

SlotDescription
(default) The panel's content.
heading Rich heading content, in place of the heading property.

CSS shadow parts

PartDescription
badge The badge after it.
content The clipping box inside the panel. Its padding is on an inner element, so that a closed panel collapses to nothing.
header The element carrying role="heading".
icon The icon before the heading text.
marker The chevron that turns.
region The panel.
trigger The button inside it.

CSS custom properties

PropertyDescription
--bmx-accordion-heading-font-size Size of the heading text.
--bmx-accordion-heading-weight Weight of the heading text.
--bmx-accordion-hover Background of a heading under the pointer.
--bmx-accordion-marker-size Size of the chevron.
--bmx-accordion-padding-block Space inside the heading, down.
--bmx-accordion-padding-inline Space inside the heading and the panel, across.