Progressive disclosure

Every way arXiv shows less than it has, and how a reader gets the rest. A paper page holds far more than any one reader wants at once — twenty-two authors, eleven versions, four hundred references, the full licence text — and the choice is never whether to hide something but which affordance does the hiding, because each one makes a different promise about what is behind it.

Accordion

Native <details>/<summary>. No JavaScript, keyboard and screen-reader behaviour for free, and the browser's find-in-page can open a closed panel to show a match inside it — which no hand-built accordion does. A +/− glyph replaces the default marker. Two dressings, one element.

Note

Two rules rather than one: a single rule reads as a heading with an underline, while two give the disclosure a top and a bottom, so a reader can see that what appears below the first rule belongs to the label above it.

Versions
v3 · current
24 Apr 2026
v2
2 Mar 2026
v1
10 Jan 2026
Paper information
arXiv ID
2604.22725
Subjects
gr-qc · hep-th
Licence
CC BY 4.0
Related
Connected papers, datasets, and code links.
Relevant code
<div class="ds-acc-stack">
  <details class="ds-acc" open>
    <summary>Versions</summary>
    <div class="ds-acc-body">
      <dl>
        <dt>v3 · current</dt><dd>24 Apr 2026</dd>
        <dt>v2</dt><dd><a href="#">2 Mar 2026</a></dd>
        <dt>v1</dt><dd><a href="#">10 Jan 2026</a></dd>
      </dl>
    </div>
  </details>
  <details class="ds-acc">
    <summary>Paper information</summary>
    <div class="ds-acc-body">
      <dl>
        <dt>arXiv ID</dt><dd><a href="#">2604.22725</a></dd>
        <dt>Subjects</dt><dd>gr-qc · hep-th</dd>
        <dt>Licence</dt><dd><a href="#">CC BY 4.0</a></dd>
      </dl>
    </div>
  </details>
  <details class="ds-acc">
    <summary>Related</summary>
    <div class="ds-acc-body">Connected papers, datasets, and code links.</div>
  </details>
</div>
.ds-acc
On a <details>. Ruled: no box, no fill, no horizontal padding. The label sits on the same left edge as the prose around it, with a rule above and below. The <summary> is the label; the +/− marker comes from the stylesheet.
.ds-acc-body
Holds the panel content, directly after the <summary>. A <dl> inside it renders as label and value pairs, one column on a narrow screen.
.ds-acc-stack
The container for a list of disclosures. Stacked in it they butt together and read as one ruled list: each shared edge is a single line, because the preceding item's lower rule is the next item's upper one.
[open]
Present on the one panel that starts open, if any. See Which affordance under Rules.

Two levels, inside a card

A disclosure inside another one is the second level: indented one step, its label a step smaller. Two levels is the limit a reader can keep track of. Shown inside a card with a heading, the paper reader's sidebar, where the stack ends the card and the card's own edge closes it.

Paper information

Versions
v3 · current
24 Apr 2026
v2
2 Mar 2026
v1
10 Jan 2026
Metadata
Subjects
General Relativity and Quantum Cosmology (gr-qc); Cosmology and Nongalactic Astrophysics (astro-ph.CO)
Identifiers
Related
Connected papers, datasets, and code links.
Relevant code
<div class="ds-card">
  <h3>Paper information</h3>
  <div class="ds-acc-stack">
    <details class="ds-acc" open>
      <summary>Versions</summary>
      <div class="ds-acc-body">
        <dl>
          <dt>v3 · current</dt><dd>24 Apr 2026</dd>
          <dt>v2</dt><dd><a href="#">2 Mar 2026</a></dd>
          <dt>v1</dt><dd><a href="#">10 Jan 2026</a></dd>
        </dl>
      </div>
    </details>
    <details class="ds-acc">
      <summary>Metadata</summary>
      <div class="ds-acc-body">
        <details class="ds-acc">
          <summary>Subjects</summary>
          <div class="ds-acc-body">General Relativity and Quantum Cosmology (<a href="#">gr-qc</a>); Cosmology and Nongalactic Astrophysics (<a href="#">astro-ph.CO</a>)</div>
        </details>
        <details class="ds-acc">
          <summary>Identifiers</summary>
          <div class="ds-acc-body">
            <dl>
              <dt>arXiv ID</dt><dd><a href="#">2604.22725</a></dd>
              <dt>DOI</dt><dd><a href="#">10.48550/arXiv.2604.22725</a></dd>
            </dl>
          </div>
        </details>
      </div>
    </details>
    <details class="ds-acc">
      <summary>Related</summary>
      <div class="ds-acc-body">Connected papers, datasets, and code links.</div>
    </details>
  </div>
</div>
.ds-acc inside .ds-acc-body
The second level. Indented one step, its label a step smaller.
.ds-card > .ds-acc-stack:last-child
A stack that ends a card drops the last disclosure's lower rule, because the card's edge closes it. With content below the stack, the rule stays.
h3 before the stack
The heading names the group, so it is found by heading navigation and every disclosure inside it is announced under that name.

Show more

The other disclosure. An accordion hides a labelled section; this reveals the tail of something already begun. The reader is already reading the thing — the control only says how much of it is left.

Note

A tail cannot be a details element, because a summary would put a heading in the middle of a sentence.

Relevant code
<ul>
  <li><a href="#">R. Almeida</a></li>
  <li><a href="#">K. Nakamura</a></li>
  <li><a href="#">P. Oyelaran</a></li>
  <li><a href="#">S. Weiss</a></li>
  <li><a href="#">J. Petrov</a></li>
  <li><a href="#">M. Dupont</a></li>
  <li><a href="#">A. Haddad</a></li>
  <li><a href="#">L. Cheng</a></li></ul><span id="authors-tail" hidden>, <a href="#">T. Okonkwo</a>,
  <a href="#">E. Lindqvist</a>, <a href="#">N. Ravindran</a>, <a href="#">C. Müller</a>,
  <a href="#">D. Ferreira</a>, <a href="#">B. Szász</a>, <a href="#">G. Yilmaz</a>,
  <a href="#">H. Iwata</a>, <a href="#">V. Novotná</a>, <a href="#">O. Adeyemi</a>,
  <a href="#">F. Rossi</a>, <a href="#">W. Nguyễn</a>, <a href="#">Z. Kowalczyk</a>,
  <a href="#">Y. Þórsson</a></span>
<button type="button" class="ds-show-more" id="authors-toggle"
        aria-expanded="false" aria-controls="authors-tail">… show all 22 authors</button>
.ds-show-more
On a <button type="button"> at the end of the visible part. An accordion is <details>, so the browser supplies the semantics; a tail cannot be, so this is a real <button> that has to declare for itself what the browser would otherwise have said, with the three attributes below.
[aria-expanded]
"false" / "true", flipped on every toggle. Without it the control announces as a button that does something unspecified.
[aria-controls]
The id of the region it reveals.
[hidden]
On the region, the attribute and not a class. The hidden names are then out of the tab order and out of find-in-page while they are off screen, and the collapse still works with no CSS loaded at all.

Very long author lists are a third tier, not yet promoted

Above roughly a hundred names, expanding in place dumps the reader into pages of links with the collapse control scrolled out of reach. The mockups answer this with a scrollable region capped in height, with a collapse control at both ends. That pattern is validated in the abstract mockup (open it with ?authors=many) but is specific to the paper surface, so it belongs in the reader stylesheet rather than here. Until that stylesheet exists, treat the mockup as the reference.

Popover

A lookup the reader wants without leaving their sentence: what reference 47 is, what footnote 3 says. It is the only disclosure here that does not move the page — which is exactly why it suits a reader mid-paragraph, and why it is wrong for anything they might want to keep open while they read on.

Note

Size it for content nobody has measured: a bibliography entry, a footnote and a contents list are all different lengths, and none of them is known when the component is written.

Reference 47
Ashtekar, A. and Bojowald, M. Quantum geometry and the Schwarzschild singularity. Class. Quantum Grav. 23 (2006). Jump to reference
Relevant code
<span class="ds-popover" role="region" aria-label="Reference 47">
  <div class="ds-popover-title">Reference 47</div>
  <button type="button" class="ds-close">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>
    <span class="is-sr-only">Close reference 47</span>
  </button>
  Ashtekar, A. and Bojowald, M. <em>Quantum geometry and the Schwarzschild singularity.</em>
  Class. Quantum Grav. 23 (2006).
  <a href="#">Jump to reference</a>
</span>
.ds-popover
The panel. It is position: fixed: the host sets top and left, and moves it to <body> if the trigger has a transformed ancestor. Closed, it carries the hidden attribute.
.ds-popover-title
The label line at the top of the panel. It leaves room for the close control.
.ds-close
The close control, the same one the alert and the announcement band use, documented on Buttons. The popover supplies its corner position and nothing else. It needs a <span class="is-sr-only"> that says what it closes.
[role="region"], [aria-label]
Together they make the panel a named landmark, so a screen reader user can find it and hear what it holds.
--ds-popover-width, --ds-popover-max-height
Set per use; past that height it scrolls, and overscroll-behavior: contain stops that scroll running on into the page beneath once it reaches the end.
.ds-inline-active
On the trigger while its popover is open: a light-blue wash and an underline, so a reader glancing back at the paragraph can see which citation the panel belongs to. Pair it with aria-expanded on the trigger, which is what carries the same fact to a screen reader; the wash is the visible half of one state, not a decoration.

Header dropdown menus

A property whose sections need grouping adds .ds-site-header-dropdown, built on <details> so it opens and closes with no JavaScript. A page may add close-on-outside-click and Esc as enhancement. The bar that carries the menus is documented on Site header.

Relevant code
<nav class="ds-site-header ds-site-header--light" aria-label="Design system">
  <a href="/" class="ds-site-header-logo">arXiv Design System</a>
  <details class="ds-site-header-dropdown">
    <summary>Design Patterns</summary>
    <div class="ds-site-header-menu">
      <span class="ds-panel-label">Components</span>
      <a href="colors.html">Colors</a>
      <a href="progressive-disclosure.html" aria-current="page">Progressive disclosure</a>
      <!-- … -->
    </div>
  </details>
  <details class="ds-site-header-dropdown">
    <summary>Docs</summary>
    <div class="ds-site-header-menu">
      <a href="using.html">Using the system</a>
      <!-- … -->
    </div>
  </details>
</nav>
.ds-site-header-dropdown
A <details> group in the bar. Optional. The summary sits in the bar and takes the surface tokens, so it is correct on either variant.
.ds-site-header-menu
The floating panel. Right-anchored, capped to the viewport. A floating panel is a light surface whichever bar summoned it, the same way a popover is. The menu anchors to its trigger’s right edge: the nav always sits at the right of the bar, and a left-anchored menu runs off the viewport on the last item — which is every bar’s last item, not an edge case.
.ds-panel-label
Group headings inside a menu use the system-wide label, not a bespoke class.
aria-current="page"
On the menu link for the page the reader is on. The menu shows it in bold, and a screen reader announces it.

Contents bar

A long page’s own table of contents: one control that names the section the reader is in and opens the list of the others. This one lists the sections of the page you are reading, shown on its own without the bar that carries it at the top of the page.

Contents
Relevant code
<div class="ds-container ds-zone-secondary">
  <header class="ds-page-header">…</header>

  <div class="ds-full ds-toc-bar">
    <div class="ds-toc-bar-inner">
      <details class="ds-toc">
        <summary class="ds-toc-trigger">
          <svg aria-hidden="true">…</svg>
          <span class="ds-toc-text"><span class="ds-toc-prefix">Contents</span></span>
          <svg class="ds-toc-chevron" aria-hidden="true">…</svg>
        </summary>
        <nav class="ds-toc-menu" aria-label="Contents">
          <ol></ol>      <!-- filled by verification/gen-anchors.py -->
        </nav>
      </details>
    </div>
  </div>

  <div class="ds-full ds-zone-primary">…</div>
</div>
<script src="toc.js" defer></script>
.ds-toc
The control, a <details>. It works on its own anywhere, and it opens with JavaScript off.
.ds-toc-trigger
The <summary>. Holds the list icon, .ds-toc-text with its .ds-toc-prefix, and .ds-toc-chevron.
.ds-toc-menu
The list, a <nav> holding an <ol>. The link to the current section gets .is-current. A page whose sections are numbered puts each number in .ds-toc-num.
.ds-toc-bar
The edge-to-edge row that carries the control. A direct child of .ds-container, with .ds-full. Placed directly before .ds-zone-primary, it sits on that zone’s top edge. The bar is always sticky: it keeps to the top of the viewport, where it becomes .is-stuck and tightens, and it sets scroll-padding-top so an anchor lands below it. Sticky chrome is governed by DESIGN-POLICIES; check there before adding the bar to a page.
.ds-toc-bar-inner
The bar’s three-slot grid, which keeps the control centred whatever sits beside it.
  • The list is generated, not written. verification/gen-anchors.py fills the <ol> from the page’s section headings, and --check fails when the two disagree. Leave the list empty and run the generator.
  • It opens without JavaScript. toc.js adds closing on Escape, closing on a click outside, and the name of the current section on the control.
  • One per page. toc.js drives the first .ds-toc it finds, which on this page is the bar at the top; the control in the card above comes later in the document, so it opens and closes on its own and nothing else.

Accessibility essentials

  • Prefer <details> wherever it fits. It carries the expanded state, the keyboard behaviour and the announcement without any script, and find-in-page can open a closed panel to reveal a match. A hand-built accordion loses all four, and losing find-in-page on a research site is the expensive one.
  • The summary is the whole label. Never put a second interactive control inside it — a link or button in a <summary> is reachable but its activation fights the disclosure's own.
  • Hide with the hidden attribute, not with a class. Content hidden by a class that fails to load is invisible but still tabbable, which puts a keyboard user in a place they cannot see.
  • Every custom toggle owns aria-expanded. Its absence is the single most common defect in this pattern: the control announces as a button, does something visible to everyone else, and says nothing.
  • The label counts. “show all 22 authors”, not “show more”. A reader deciding whether to expand is asking how much is behind it, and someone using a screen reader hears the control with no view of the list at all. Return the label to “show fewer” when open.
  • Escape closes a popover and returns focus to the chip that opened it. A reader who opened it from the keyboard must not be stranded at the end of the document. Close it on outside click and on scroll as well: the panel is position: fixed, so left open it would follow the viewport while the sentence it belongs to scrolls away.
  • A menu is a disclosure, not an ARIA menu. role="menu" is for application menus — the kind with arrow-key roving focus and menu items that are not links. A list of links is a disclosure, and W3C’s own guidance is to build it this way. Using role="menu" here would make a screen reader promise keyboard behaviour the component does not have. The state comes free: <summary> is announced as a button with an expanded/collapsed state, without a single ARIA attribute. That is most of why this is <details>.
  • Mark the current page. The menu link for the page the reader is on takes aria-current="page".
  • Everything is reachable from the keyboard, with JavaScript off. Open, close and keyboard operation are native; outside-click and Escape are enhancements layered on top. Escape closes a menu and returns focus to the trigger. The second half matters: without it, a keyboard user who opened the menu, tabbed into it and pressed Escape is left holding focus on a link that is no longer visible. Return focus only when it was inside the menu — Escape pressed elsewhere on the page must not move it.

Modifiers

Rail

The rules go, for a disclosure inside a container that already frames it — the paper page's sidebar, where the rail's own hairline dividers do the separating. Internals go single-column for the narrow measure, and the +/− marker turns Link Blue so a closed disclosure still reads as interactive.

Versions
v3 · current
24 Apr 2026
v2
2 Mar 2026
Paper information
Single-column inside the narrow rail.
Relevant code
<details class="ds-acc ds-acc-rail" open>
  <summary>Versions</summary>
  <div class="ds-acc-body">
    <dl>
      <dt>v3 · current</dt><dd>24 Apr 2026</dd>
      <dt>v2</dt><dd><a href="#">2 Mar 2026</a></dd>
    </dl>
  </div>
</details>
<details class="ds-acc ds-acc-rail">
  <summary>Paper information</summary>
  <div class="ds-acc-body">Single-column inside the narrow rail.</div>
</details>
.ds-acc-rail
Added beside .ds-acc on the <details>, inside a container whose own dividers already separate its contents, such as an <aside>.

Rules

Which affordance

The question that separates them is not how much is hidden. It is what relationship the hidden thing has to what the reader is looking at.

UseWhen the hidden content isCosts the reader
Accordion
.ds-acc
A labelled section the reader can decide about from its label alone — Versions, Paper information, Related. One click, stays on the page, keeps their place.
Show more
.ds-show-more
The tail of something already begun — authors nine through twenty-two, the rest of a category list. There is no label to give it, because it is not a different thing. One click, expands in place, no new surface.
Popover
.ds-popover
A lookup the reader wants without leaving their sentence — what reference 47 is, what footnote 3 says. Nothing permanent. It closes on Escape and does not move the page.
A link to a full page Something with its own identity — a different paper, an author's other work, the full licence. Leaves the page. Pay this only when the destination deserves a URL.

Motion and layering