Buttons

Each arXiv button family shares the same mechanical spec, with color used to differentiate by context: Open Blue for public pages and Access Lime for internal tools. Public pages are everywhere a reader or author can access. Internal pages include arXiv Check and the Admin Console.

Button tiers

arXiv has three button tiers: primary, secondary, and a quiet text-only button (text links can be found on the typography page).

Note

When to use a text button vs a text link: Use a text button for actions that do not navigate to a new page. Use a text link when navigating to a new page or to an anchor link on the same page.

Public
Internal
Disabled
Destructive
Relevant code
ClassFillUse for
.ds-btn-primaryOpen Blue #a5d6feThe page's call to action (HTML, PDF on the abstract page). One cluster per view.
.ds-btnWhite, warm-grey gradient borderAdjacent destinations of equal weight but lower priority (TeX Source).
.ds-btn-textNone — no fill, no border, no shadowReal but minor actions beside a bigger choice: Copy link, Show all authors, Dismiss.
Construction
Both filled variants share the V3 build: a 1.5px gradient border (lighter top → darker bottom) from dual padding-box/border-box backgrounds, plus an inner vignette. Hover brightens; press drops 1px and deepens the vignette.
Quiet tier
The text button borrows the link’s quietness, not its identity: Link Blue, never underlined, and hover is a background wash — the same feedback the other buttons give. Underlines stay with links, so a reader can still tell “this navigates” from “this acts here.”
No outline tier
The secondary is already white fill plus border, and on a white canvas a transparent fill is the same pixels as a white one.
Icons
Any .ds-btn accepts an inline SVG. The stylesheet sizes it in em, blocks the baseline gap, and stops it shrinking beside a long label. Set stroke="currentColor" and nothing else.
Disabled
One flat --ds-surface-muted fill for every variant. An action that is merely not available yet takes aria-disabled instead — see Forms.
<!-- Primary / secondary / text -->
<a class="ds-btn ds-btn-primary" href="/html/2604.22725v1">HTML</a>
<a class="ds-btn" href="/src/2604.22725v1">TeX Source</a>
<button class="ds-btn ds-btn-text" type="button">Copy link</button>

Never mix the two primary accent colors

An Access Lime primary button on a public page, or an Open Blue button in an internal tool, is a policy violation. If the context is ambiguous, settle it first and record the answer in a code comment.

A control that goes to another page is a link, even when it looks like a button. The formats on the abstract page are the common case: each one is an <a> with the button classes, so it announces as a link, opens in a new tab, and works with JavaScript off.

Note

A link cannot take the disabled attribute. To disable one, add .is-disabled, remove the href, and add aria-disabled. With the href still there the link still works while looking switched off.

Internal
Disabled
Relevant code
<a class="ds-btn ds-btn-primary" href="/html/2604.22725v1">HTML</a>
<a class="ds-btn" href="/pdf/2604.22725v1">PDF</a>

<!-- disabled: no href, and both the class and the attribute -->
<a class="ds-btn is-disabled" aria-disabled="true">Other formats</a>
.ds-btn, .ds-btn-primary, .ds-btn-text
The same classes as a button. Nothing about the link changes how they look.
.is-disabled
Gives a link the disabled look, the same as disabled gives a button. It only changes the look: remove the href so the link stops working, and add aria-disabled="true" so a screen reader says so.

Small actions attached to content

This component is a variant of text-only buttons and attach a row of tiny controls to a content element. It is used on the HTML papers page for figures, formula, and more. They differ from default text-only buttons via their font size, color, and surrounding container. They appear when hovering over the parent element.

(This content might be a figure, a formula, or other content with additional options to surface for users)
Relevant code
<figure class="fig-wrap" style="position: relative;">
  <!-- the figure, formula, or other content -->
  <div class="ds-element-pill" style="bottom: -14px; left: 50%; transform: translateX(-50%);">
    <button type="button"><svg aria-hidden="true">…</svg> Permalink</button>
    <button type="button"><svg aria-hidden="true">…</svg> Alt text</button>
    <button type="button"><svg aria-hidden="true">…</svg> Expand</button>
  </div>
</figure>
.ds-element-pill
The container: a white pill straddling the bottom edge of the content it belongs to. The wrapper supplies position: relative; the pill positions itself inside it. Documented with the other containers on Organizing content.
.is-revealed
The pill is hidden at rest and shown while the wrapped content is hovered or holds focus. The consumer adds and removes this class; the demo above keeps it on.
The actions
Plain <button> or <a> elements. The pill gives each a 24px target floor. Their type and colour have no class of their own yet; this page stages them locally.

The close control

Dismissing something is a simple job, but it needs a clear and consistent control everywhere it appears. Wether in an alert, a popover, an announcement banner, or an expanded figure, .ds-close supplies the right style.

Note

Close vs Dismiss: Use Close for something the reader opened, or when there is not space for a dismiss button. Use Dismiss for something the site put in front of the user.

On the page
On an alert
On dark chrome
Relevant code
.ds-close
The whole control. 32×32, quiet tier — no fill, no border, no shadow. It takes color: inherit, so one rule serves all four alert palettes, the pale announcement band and dark chrome without knowing which it is on. It sets no position.
.is-sr-only
Required. The icon is aria-hidden under the icon policy, so without this span the control announces as “button” and nothing more.
<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">Dismiss announcement</span>
</button>

Accessibility essentials

  • Use the right element. Use a <button> for an action that happens on this page, and an <a> for anything that goes to another page or another place on this one. Both take the same classes. Do not put a click handler on a link or an href on a button.
  • Every button needs a text label. An icon-only button gets its name from a <span class="is-sr-only"> inside it that says what the button does, such as “Copy link”. Without it, a screen reader says only “button”. Do not use title for this, and prefer the span to aria-label, because page translation tools skip attributes.
  • Say what will happen. Label a button with the action it performs: “Save changes”, “Download PDF”, “Delete file”. Avoid “OK”, “Yes” and “Submit” on their own, because they only make sense to someone who can see the whole screen.
  • Disable, do not hide. When an action is not available, keep the button in place and add the disabled attribute. A button that disappears leaves the user wondering where it went. When the user can do something to make the action available, use aria-disabled="true" instead and say what they need to do; see Forms.
  • When a button acts like a toggle. If a button switches something on and off and stays pressed, set aria-pressed="true" or "false" on it and update it when it changes. A colour change on its own tells a screen reader user nothing. For a setting that is saved, use the switch instead.

Modifiers

Icon-only buttons

A button whose whole label is an icon. .ds-btn-icon modifies the shape of a primary, secondary, or text-only button.

Public
Internal
Disabled
Destructive
Relevant code
.ds-btn-text.ds-btn-destructive
The quiet destructive: the text tier in the danger colour, for a remove action in a table row or a toolbar where a filled red on every row would be alarm rather than information. Works with a label as well as with an icon.
.ds-btn-icon
The shape. Square by aspect-ratio, min-width: 0, equal padding, no label gap. Always used with a tier — .ds-btn .ds-btn-text .ds-btn-icon, never .ds-btn-icon alone.
.is-sr-only
Required. The icon is aria-hidden under the icon policy, so without this span the control announces as “button” and nothing more. Carbon and Primer both make this name a required prop; the systems that leave it optional are the ones with the known gap here. Prefer it to aria-label, which does not survive page translation.

On dark surfaces

The primary button works everywhere. The gradient border and vignette keep the edge legible on cool, warm, and dark backgrounds. The secondary button can be adapted with a modifier class when using it on a tinted background.

Cool tint (modify with .on-tint)

Warm tint (no modifier needed)

Dark tint (modify with .on-dark)

Relevant code
.on-tint
On a cool tint, swaps the secondary's white fill for Card Grey (same luminance, warm hue) so it reads as secondary by material rather than by contrast. On a warm tint the default white secondary already sits comfortably.
.on-dark
For a field dark enough to host white text: an outreach masthead, a photo band. A white fill would read as a paper rectangle stuck to the surface, louder than the primary beside it; .on-dark drops the fill so the field shows through and carries the boundary on a white border. See outreach sites for where such fields are allowed.
Not this
A default white secondary on a cool tint pops too hard and reads as primary — that is the case .on-tint exists for. Do not put .on-tint on a warm tint: its Card Grey fill melts into the surface. And .on-dark is only correct on a dark field; on a light tint use .on-tint.
<!-- Secondary on a cool tint, and on a committed color field -->
<a class="ds-btn on-tint" href="/issues">Submit a fix</a>
<a class="ds-btn on-dark" href="/subscribe">Subscribe</a>

Button groups

A set of related buttons with a parent container class that spaces them appropriately.

Side by side

Relevant code
.ds-btn-group
The container. Flex, wrapping, vertically centred, gap --ds-space-tight. Nothing about buttons makes their spacing special: two side by side are siblings that belong together, so they take the same gap as any other such pair.

Stacked — .ds-btn-group--stack

Relevant code
.ds-btn-group--stack
The same relationship on the other axis. Items align to the start rather than stretching.

A form’s action area — .ds-btn-group--end

Relevant code
.ds-btn-group--end
Pushes the group to the trailing edge. This is the action area at the end of a form, where the primary action comes last.

One choice at each end — .ds-btn-group--split

Relevant code
.ds-btn-group--split
One choice at each end, for a pair that goes opposite ways — Back against Continue in a stepped form.

Only use for pairs. Three buttons split like this leaves the middle one belonging to neither side.