Skip to main content

Get Involved

Whether you are a developer, designer, writer, project builder, or just someone passionate about Cardano.

Design Tokens

Design tokens are the shared styling vocabulary for cardano.org. When you write CSS, reach for a token instead of a raw value. This keeps spacing, color, and motion consistent across pages built by different contributors, and it means a change to the palette or scale happens in one place.

All tokens are CSS custom properties defined in src/css/custom.css. They are global, so any *.module.css file can use them without an import.

Enforced in CI

yarn test:css fails the build if a --site-* or other project variable is used without being defined. Do not invent new hardcoded hex colors or one-off spacing values; use or extend the tokens below.

How tokens are organized

Two namespaces, by design:

  • --ifm-* are Infima (Docusaurus) variables. Use these for anything the framework already owns: the brand color and its ramp, neutral greys, and surfaces. Docusaurus's own components (navbar, buttons, admonitions) read them too.
  • --site-* are this project's own tokens for everything Infima does not provide: semantic status colors, spacing, radius, elevation, motion, and focus.

Neutrals have no --site-* tokens on purpose. Use Infima's theme-aware emphasis scale rather than a second grey palette:

UseToken
Body textvar(--ifm-font-color-base)
Strong textvar(--ifm-color-emphasis-900)
Muted / secondary textvar(--ifm-color-emphasis-600)
Borders, dividersvar(--ifm-color-emphasis-200) / -300
Card / panel backgroundvar(--ifm-background-surface-color)
Page backgroundvar(--ifm-background-color)

These already invert correctly in dark mode, which is why you should not reach for a hardcoded grey.

Color

Brand

The Cardano blue and its ramp live on Infima's primary variables. The ramp is a proper mono-hue ladder: darker variants for hover and active states, lighter variants for soft fills.

TokenLightUse
--ifm-color-primary#0033ADBrand blue, default
--ifm-color-primary-dark#002a8eHover on filled buttons/links
--ifm-color-primary-darker#00257dActive / pressed
--ifm-color-primary-darkest#001f68Strongest accent
--ifm-color-primary-light-lightest#0038be#0042e1Lighter accents

For rgba() use the RGB triple: rgba(var(--ifm-color-primary-rgb), 0.5).

In dark mode the whole ramp shifts to a lighter blue automatically; you do not need to handle it per component.

Semantic status

One canonical value each, with dark-mode variants already defined:

TokenLightMeaning
--site-success#2da06aSuccess, positive
--site-warning#d97706Warning, caution
--site-danger#dc3545Error, destructive
--site-infobrand blueInformational

Brand tints

Translucent primary, for soft fills and hover backgrounds (prefer these over a hardcoded rgba(0,51,173,…)):

  • --site-tint-weak: rgba(var(--ifm-color-primary-rgb), 0.06)
  • --site-tint-strong: rgba(var(--ifm-color-primary-rgb), 0.12)

Spacing

An 8px-based scale. Use it for padding, margins, and gaps.

TokenValue
--site-space-3xs0.25rem (4px)
--site-space-2xs0.5rem (8px)
--site-space-xs0.75rem (12px)
--site-space-sm1rem (16px)
--site-space-md1.5rem (24px)
--site-space-lg2rem (32px)
--site-space-xl3rem (48px)
--site-space-2xl4rem (64px)
--site-space-3xl6rem (96px)

For vertical rhythm between sections, the Spacer Box component wraps sm / lg / 3xl.

Corner radius

TokenValueUse
--site-radius-sm6pxSmall controls
--site-radius-md8pxDefault card
--site-radius-lg12pxLarge cards
--site-radius-xl16pxFeature panels
--site-radius-pill999pxPills, chips

Circular elements use border-radius: 50% directly.

Elevation

Four shadow steps, each with a stronger dark-mode variant already defined:

TokenUse
--site-shadow-xsSubtle lift
--site-shadow-smResting card
--site-shadow-mdRaised card
--site-shadow-lgHover / floating

Motion

TokenValueUse
--site-duration-fast150msSmall state changes
--site-duration-base200msDefault
--site-duration-slow300msLarger transitions
--site-easecubic-bezier(0.4, 0, 0.2, 1)Standard easing
--site-lift-2pxCanonical hover lift (transform: translateY(var(--site-lift)))

A typical hover transition:

.card {
transition: transform var(--site-duration-base) var(--site-ease),
box-shadow var(--site-duration-base) var(--site-ease);
}
.card:hover {
transform: translateY(var(--site-lift));
box-shadow: var(--site-shadow-lg);
}

Wrap non-essential animation in @media (prefers-reduced-motion: reduce) and disable it there.

Focus

There is a global keyboard-focus baseline in custom.css, so most interactive elements get a consistent ring for free:

:focus-visible {
outline: 2px solid var(--ifm-color-primary);
outline-offset: 2px;
}

Do not remove focus outlines. If a component needs a shadow-style ring instead of an outline, use --site-focus-ring.

Breakpoints

Breakpoints are not tokens: CSS custom properties cannot be used inside @media queries, and the project has no preprocessor. Use these three canonical values so component collapse points stay in sync with the navbar and sidebar:

WidthUse
996pxPrimary. Matches the Docusaurus navbar/sidebar collapse.
768pxTablet.
480pxMobile.

yarn test:css blocks the 966px typo (a transposition of 996px) from coming back.

Adding a token

If you genuinely need a value the scales do not cover, add it to the relevant block in src/css/custom.css (with its dark-mode variant if it is a color or shadow) rather than hardcoding it in a component. Keep the naming consistent with the existing --site-* groups.