Accordion

ui-accordion groups ui-accordion-item elements. Each item renders a native <details> and <summary> in its shadow root, so the browser handles opening and closing, keyboard activation and find-in-page. Put a ui-accordion-trigger and a ui-accordion-content inside each item. The trigger becomes the summary row, and the content shows when the item is open. In the default single mode, opening one item closes the others. With type="multiple" items open and close independently.

The accordion fills the width of its container.

Previewindex.html
Is it accessible? Yes. Each item is a native details element, so it works with the keyboard and screen readers. Is it styled? Yes. It uses the theme tokens, so it follows your colours, radii and dark mode. Is it animated? The chevron rotates when an item opens.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Accordion demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-narrow {
      width: min(100%, calc(var(--spacing) * 88));
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/accordion.html"></import-element>

  <div class="demo-narrow">
    <ui-accordion>
      <ui-accordion-item open>
        <ui-accordion-trigger>Is it accessible?</ui-accordion-trigger>
        <ui-accordion-content>
          Yes. Each item is a native details element, so it works with the keyboard and screen readers.
        </ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item>
        <ui-accordion-trigger>Is it styled?</ui-accordion-trigger>
        <ui-accordion-content>
          Yes. It uses the theme tokens, so it follows your colours, radii and dark mode.
        </ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item>
        <ui-accordion-trigger>Is it animated?</ui-accordion-trigger>
        <ui-accordion-content>The chevron rotates when an item opens.</ui-accordion-content>
      </ui-accordion-item>
    </ui-accordion>
  </div>
</body>
</html>

Examples

Multiple open items

Set type="multiple" to let several items stay open at once.

Previewindex.html
Shipping Orders ship within two working days. Returns Return any item within 30 days of delivery. Warranty Every product has a two-year warranty.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Accordion demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-narrow {
      width: min(100%, calc(var(--spacing) * 88));
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/accordion.html"></import-element>

  <div class="demo-narrow">
    <ui-accordion type="multiple">
      <ui-accordion-item open>
        <ui-accordion-trigger>Shipping</ui-accordion-trigger>
        <ui-accordion-content>Orders ship within two working days.</ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item open>
        <ui-accordion-trigger>Returns</ui-accordion-trigger>
        <ui-accordion-content>Return any item within 30 days of delivery.</ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item>
        <ui-accordion-trigger>Warranty</ui-accordion-trigger>
        <ui-accordion-content>Every product has a two-year warranty.</ui-accordion-content>
      </ui-accordion-item>
    </ui-accordion>
  </div>
</body>
</html>

Disabled item

A disabled item cannot be opened or closed by the user. Its summary is dimmed.

Previewindex.html
Account Manage your account details. Billing (admins only) Billing settings. Notifications Choose which emails you receive.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Accordion demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-narrow {
      width: min(100%, calc(var(--spacing) * 88));
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/accordion.html"></import-element>

  <div class="demo-narrow">
    <ui-accordion>
      <ui-accordion-item>
        <ui-accordion-trigger>Account</ui-accordion-trigger>
        <ui-accordion-content>Manage your account details.</ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item disabled>
        <ui-accordion-trigger>Billing (admins only)</ui-accordion-trigger>
        <ui-accordion-content>Billing settings.</ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item>
        <ui-accordion-trigger>Notifications</ui-accordion-trigger>
        <ui-accordion-content>Choose which emails you receive.</ui-accordion-content>
      </ui-accordion-item>
    </ui-accordion>
  </div>
</body>
</html>

Rich trigger

The trigger takes any inline markup, such as a badge.

Previewindex.html
Plan Pro Your plan renews on the first of every month. Usage 82% You have used 82% of this month's quota.
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Accordion demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
  <style>
    .demo-narrow {
      width: min(100%, calc(var(--spacing) * 88));
    }
  </style>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/accordion.html"></import-element>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/badge.html"></import-element>

  <div class="demo-narrow">
    <ui-accordion>
      <ui-accordion-item>
        <ui-accordion-trigger>Plan <ui-badge variant="secondary">Pro</ui-badge></ui-accordion-trigger>
        <ui-accordion-content>Your plan renews on the first of every month.</ui-accordion-content>
      </ui-accordion-item>
      <ui-accordion-item>
        <ui-accordion-trigger>Usage <ui-badge variant="outline">82%</ui-badge></ui-accordion-trigger>
        <ui-accordion-content>You have used 82% of this month's quota.</ui-accordion-content>
      </ui-accordion-item>
    </ui-accordion>
  </div>
</body>
</html>

Reacting to changes

Each item emits a bubbling toggle event when the user opens or closes it, and reflects its state to the open attribute.

Previewindex.htmlaccordion-events-demo.html
General General settings. Privacy Privacy settings.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Accordion demo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/dist/theme.css">
  <script type="module" src="https://cdn.jsdelivr.net/npm/@realmorg/realm@alpha/dist/realm.js"></script>
</head>
<body>
  <import-element from="https://cdn.jsdelivr.net/npm/@realmorg/ui@alpha/components/accordion.html"></import-element>

  <import-element from="./accordion-events-demo.html"></import-element>
  <accordion-events-demo></accordion-events-demo>
</body>
</html>
<custom-element name="accordion-events-demo">
  <script>
    const log = useState({ last: "Nothing toggled yet" });

    function toggled(event) {
      const item = event.target;
      log.last = `${item.dataset.name} is ${item.open ? "open" : "closed"}`;
    }
  </script>
  <style>
    :host {
      display: grid;
      gap: calc(var(--spacing) * 3);
      width: min(100%, calc(var(--spacing) * 96));
    }
    p {
      margin: 0;
      font-size: var(--text-sm);
      color: var(--muted-foreground);
    }
  </style>
  <ui-accordion type="multiple" ontoggle="toggled(event)">
    <ui-accordion-item data-name="General">
      <ui-accordion-trigger>General</ui-accordion-trigger>
      <ui-accordion-content>General settings.</ui-accordion-content>
    </ui-accordion-item>
    <ui-accordion-item data-name="Privacy">
      <ui-accordion-trigger>Privacy</ui-accordion-trigger>
      <ui-accordion-content>Privacy settings.</ui-accordion-content>
    </ui-accordion-item>
  </ui-accordion>
  <p><slot name="#log.last"></slot></p>
</custom-element>

API

Parts

Element Fills Renders
ui-accordion The container. Fills its container's width.
ui-accordion-item the default slot of ui-accordion A native <details> with a <summary> row and a chevron.
ui-accordion-trigger the <summary> of its ui-accordion-item The summary row's content. Accepts inline markup.
ui-accordion-content the body of its ui-accordion-item The content shown when the item is open, with bottom padding.

Attributes

ui-accordion

Attribute Type Default Description
type "single" | "multiple" "single" In single mode, opening an item closes every other open item in the accordion.

ui-accordion-item

Attribute Type Default Description
open boolean false Whether the item is open. Reflects.
disabled boolean false Stops the user from opening or closing the item. Setting open from script still works.

ui-accordion-trigger and ui-accordion-content have no attributes.

Events

Event Element Description
toggle ui-accordion-item Fires when the user opens or closes the item. Bubbles. Read event.target.open. Setting open from script, including the automatic closing in single mode, does not fire it.

CSS parts

Part Element Description
summary ui-accordion-item The native <summary> row.

Accessibility

Edit this page on GitHub · View as Markdown