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.
arXiv has three button tiers: primary, secondary, and a quiet text-only button (text links can be found on the typography page).
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.
| Class | Fill | Use for |
|---|---|---|
.ds-btn-primary | Open Blue #a5d6fe | The page's call to action (HTML, PDF on the abstract page). One cluster per view. |
.ds-btn | White, warm-grey gradient border | Adjacent destinations of equal weight but lower priority (TeX Source). |
.ds-btn-text | None — no fill, no border, no shadow | Real but minor actions beside a bigger choice: Copy link, Show all authors, Dismiss. |
padding-box/border-box backgrounds, plus an inner vignette. Hover brightens; press drops 1px and deepens the vignette..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.--ds-tint-warm 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.
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.
<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>
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.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.
<figure class="fig-wrap" style="position: relative;">
<!-- the figure, formula, or other content -->
<div class="ds-element-pill" role="toolbar" aria-label="Figure 1" 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>
<script src="element-pill.js" defer></script>
position: relative; the pill positions itself inside it.prefers-reduced-motion it appears
without the fade.element-pill.js, loaded once on the page, does this.
Without it, every action is its own tab stop.<button> or <a> elements, with no class of
their own. The pill gives each its small type, muted colour, a wash on hover and a 24px target
floor. .is-cta marks the one main action in Link Blue.(hover: hover) and (hover: none): a narrow window can still have a mouse..is-revealed), and a tap elsewhere hides it.alert().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.
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.
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.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><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.<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.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.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.A button whose whole label is an icon. .ds-btn-icon modifies the shape of a primary, secondary, or text-only button.
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.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.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)
.on-dark drops the fill so the field shows through and draws the boundary with a white border. See outreach sites for where such fields are allowed..on-tint exists for. Do not put .on-tint on a warm tint: its Warm Tint 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>
A smaller button for a small form, such as a single field with its own actions. .ds-btn-compact reduces the padding of a primary, secondary, text-only or icon-only button; its colour still comes from the surface.
In a small form
.ds-btn-icon.<div class="ds-btn-group ds-btn-group--end">
<button class="ds-btn ds-btn-text ds-btn-compact" type="button">Cancel</button>
<button class="ds-btn ds-btn-primary ds-btn-compact" type="submit">Rename</button>
</div>
A set of related buttons with a parent container class that spaces them appropriately.
Side by side
--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
A form’s action area — .ds-btn-group--end
One choice at each end — .ds-btn-group--split
Only use for pairs. Three buttons split like this leaves the middle one belonging to neither side.
Buttons that each turn on one choice, such as a sort bar: the buttons join into one bar, and the choice that is on is tinted. Each press applies at once. Use a sort bar for up to five ways to sort a list or a set of rows that are not a table; use a sortable column header in a table, and a Sort by select in a search form.
A sort bar
<form method="get" action="buttons.html#a-group-of-toggles">
<div class="ds-btn-group" role="group" aria-labelledby="sort-by">
<span id="sort-by">Sort charts by</span>
<input type="hidden" name="group" value="cs">
<button class="ds-btn sort-asc" type="submit" name="sort" value="category-desc" aria-pressed="true">Category <span class="sort-arrow">↑</span><span class="is-sr-only">, A to Z</span></button>
<button class="ds-btn" type="submit" name="sort" value="holds" aria-pressed="false">Current holds <span class="sort-arrow">↕</span></button>
<button class="ds-btn" type="submit" name="sort" value="weekly" aria-pressed="false">Weekly holds trend <span class="sort-arrow">↕</span></button>
<button class="ds-btn" type="submit" name="sort" value="monthly" aria-pressed="false">Monthly holds trend <span class="sort-arrow">↕</span></button>
</div>
</form>
aria-labelledby. When its buttons have aria-pressed, they join, and the bar is compact. Here the bar sits in a GET form, so it works without JavaScript; hidden inputs keep the reader's other choices in the address. The group role goes on the bar, not on the form."true" on the one that is on, "false" on the rest. Off is plain; on takes the accent tint..is-sr-only span says the direction in words.A sort bar with another control
<div class="ds-btn-group ds-btn-group--split">
<form method="get" action="buttons.html#a-group-of-toggles">
<div class="ds-btn-group" role="group" aria-labelledby="sort-by-2">
<span id="sort-by-2">Sort by</span>
<button class="ds-btn sort-desc" type="submit" name="sort" value="holds-asc" aria-pressed="true">Current holds <span class="sort-arrow">↓</span><span class="is-sr-only">, largest first</span></button>
<button class="ds-btn" type="submit" name="sort" value="category" aria-pressed="false">Category <span class="sort-arrow">↕</span></button>
</div>
</form>
<button class="ds-btn ds-btn-text" type="button">Categories (40)</button>
</div>