Components · Collapse
Components

Collapse

A disclosure hides content that most people do not need, and it is worth having only when that is actually true. The default implementation is <details> and <summary>: the browser gives you the state, the keyboard behaviour, the semantics and — importantly — in-page find, which every hand-rolled accordion breaks.

Disclosure

Independent items, any number open at once. This is the default and covers most cases.

How is the overall rating calculated?

The overall figure is the mean of the seven category scores an athlete gave, weighted equally. It is not a weighted average of star counts, and organisers cannot change the weighting.

Can an organiser remove a review?

No. An organiser can reply to a review and can report one that breaks the guidelines, which sends it to moderation. Removal is a moderation decision, never an organiser one.

Why does this event say “unverified”?

It was added by an athlete rather than claimed by its organiser. It is fully readable and ratable, but it is excluded from regional rankings until someone claims it.

Accordion

One open at a time. Justified only when the sections are long enough that comparing two is not something anyone would want — which is rarer than it sounds. If a user might want to read two panels side by side, the accordion is fighting them.

Communication

What the event told you before the day, on the day and after it — the entry emails, the start-line briefing, and whether the published schedule matched what happened.

Provisions

What was on the support tables, how far apart they were, and whether anything was left for the final finishers.

Assistance

Marshals, medical cover, bag drop and lost property — and what actually happened when someone needed help.

The name attribute on <details> gives exclusive accordion behaviour with no JavaScript at all. Where it is unsupported, every panel simply opens independently — the content stays reachable, which is the correct way for this to degrade.

Specification

PropertyValueWhy
Element<details> / <summary>State, keyboard and find-in-page for free
Trigger height52px minimumComfortably past the 44px floor for a full-width row
Trigger type--text-ui, weight 500, primary inkIt is a heading and a control at once
Divider1px hairline between itemsThe system separates planes with a line
Iconchevron-down closed, chevron-up openSwapped, not rotated — see below
Icon positionTrailingThe label starts at the same x as the body text below it
MotionColour only on the triggerHeight animation is the single biggest jank source in a list
BodyIndented to the label, --text-baseThe panel belongs to the trigger, visibly

Why the chevron does not rotate. Motion allows transform in exactly two places — the bottom sheet and the spinner. A rotating chevron is a third, and it buys nothing a swapped icon does not: the open state is already unambiguous from the panel below it.

Structure

<!-- Default: independent disclosures -->
<details class="collapse">
  <summary>
    <span class="collapse__title">How is the overall rating calculated?</span>
    <span class="collapse__icon" aria-hidden="true"><!-- lucide:chevron-down --></span>
  </summary>
  <div class="collapse__body"><p>The overall figure is the mean of …</p></div>
</details>

<!-- Accordion: a shared name makes them exclusive, no JS -->
<details class="collapse" name="categories">…</details>
<details class="collapse" name="categories">…</details>

If you must hand-roll it — because the trigger has to sit outside the panel — the button carries aria-expanded and aria-controls, the panel carries the referenced id, and the panel is hidden with the hidden attribute rather than height: 0, so find-in-page and Tab both skip it.

Rules

  • Never collapse something people need. Price, required steps, error messages, the terms someone is agreeing to, and anything that changes a decision. A disclosure is for depth, not for tidiness.
  • The trigger states the answer's subject, not its existence. “How is the overall rating calculated?” — not “More information”.
  • Do not open on hover. It fires on the way to somewhere else, and there is no hover on a phone.
  • Do not nest disclosures. Two levels of hiding means the second level is never found. Nested depth is a sign the page needs restructuring.
  • An open panel must survive a re-render. Collapsing everything when a filter changes discards the user's place.
  • Deep links open their target. If a panel is addressable, arriving at its URL must open it and move focus to the trigger.
Sporting Scouter Design System
Every token on this site is generated from theme.css.