Saltar al contenido principal

Get Involved

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

Component Guidelines

Follow these conventions when you add a component or build a page. They keep the site consistent, translatable, and accessible, and several are enforced in CI.

Reuse before you create​

Shared components are the default. Before you write a component or page markup, look up what already exists in the component overview. Most pages are composed from Site Hero, Boundary Box, Title With Text, Divider, and Spacer Box.

If a component almost fits, extend it with an additive prop that leaves existing pages unchanged. Do not copy it into a slightly different version.

Where a component belongs​

KindLocationWhenRequirements
Shared componentsrc/components/Layout/A generic layout or UI pattern with no topic of its own, such as a section title, divider, tabs, accordion, or modalJSDoc for its props, a doc page under docs/get-involved/components/, a row in the overview table
Feature widgetsrc/components/<Name>/Reusable within one topic, such as App Tile or QuizJSDoc for its props, a doc page
Page-specific componentsrc/components/<PageName>/Only for an interactive tool (data visualization, wallet or chain flow, calculator, search) or deliberate art direction used on one pageA short explanation in the pull request of why no existing component fits. Its inner parts, such as titles, grids, and FAQ lists, still come from shared components

Do not add page CSS for a pattern that a shared component already covers, such as a card grid, a section heading block, or an FAQ list. Page CSS is fine for art direction and fine-tuning.

If you are unsure whether something should become a shared component, ask in the issue or pull request before you build it.

Document props with JSDoc​

Describe the props of every shared component and feature widget in a JSDoc block above the component, so editors and AI agents see them where the code is:

/**
* Section title with body text and an optional call to action.
*
* @param {object} props
* @param {string} props.title Heading text.
* @param {string|Array|object} [props.description] Body text as a string, an array of paragraphs, or `{ list: [...] }`.
* @param {string} [props.buttonLabel] Label of the optional button.
* @param {string} [props.buttonLink] Target of the optional button.
*/
export default function TitleWithText({ title, description, buttonLabel, buttonLink }) {

The props table on the component's doc page lists the same props. yarn test:component-docs (part of yarn test) compares the two for every shared component and the feature widgets listed in scripts/check-component-docs.js, and warns about a missing JSDoc block, a missing doc page, or prop names that differ. When you add a feature widget outside src/components/Layout/, add its name to the WIDGETS list in that script.

Write the doc page from the template​

Start a new doc page from docs/get-involved/components/_template.md. Files that start with an underscore are not built, so the template only exists in the repository. A doc page covers:

  • what the component renders and when to use it, with a link to the alternative,
  • a usage example with translated strings,
  • a props table that matches the JSDoc block,
  • a live preview, or one sentence on why there is none (runtime data such as a wallet or an API response, changes to the document head, a full page or homepage hero),
  • accessibility, translation, and styling notes, and related components.

Do not attribute examples to a page file ("from src/pages/x.js"), because those examples go stale when the page changes. Name the pages that use a component only after checking them with git grep. Write prop names exactly as the component destructures them, with one props table per export for a module with several exports. Live previews pass headingLevel={2} or a deeper level, so the doc page keeps a single <h1>.

Styling: use tokens​

Style with the design tokens rather than hardcoded values. Put component styles in a co-located styles.module.css (CSS Modules), and use the shared --site-* and --ifm-* variables for color, spacing, radius, shadow, and motion.

yarn test:css fails the build on undefined variables and known breakpoint typos, so keep to the documented scales.

Dark mode is required​

Every component must be legible in both light and dark mode. This is free if you use tokens and Infima's neutral scale (--ifm-color-emphasis-*, --ifm-background-surface-color), because those invert automatically.

The common bug is a hardcoded light surface with theme-aware text:

/* Wrong: white never inverts, so text disappears in dark mode */
.box { background: white; color: var(--ifm-color-emphasis-900); }

/* Right: the surface inverts with the theme */
.box { background: var(--ifm-background-surface-color); color: var(--ifm-color-emphasis-900); }

Check your work by toggling the theme switch in the navbar.

Images: resolve with base URL​

Non-default locales are served under a path prefix (/de/, /ja/). A hardcoded /img/... path breaks there. Resolve image paths through Docusaurus:

import useBaseUrl from "@docusaurus/useBaseUrl";

<img src={useBaseUrl("/img/example.png")} alt="Example" />

Use the Docusaurus <Link> component for internal navigation, never a raw <a href>. <Link> keeps client-side routing and the active locale prefix; a raw anchor triggers a full reload and drops the locale.

import Link from "@docusaurus/Link";

<Link to="/governance">Governance</Link>

Translatable text​

Wrap any new user-facing string so it can be translated. Do not hardcode English in JSX.

import Translate, { translate } from "@docusaurus/Translate";

// As an element
<Translate id="home.hero.title">A new way to transact</Translate>

// Where a plain string is needed (props, alt text)
alt={translate({ id: "home.hero.alt", message: "Cardano logo" })}

Translations themselves are managed through Crowdin, not by editing locale files directly.

Accessibility​

Accessibility rules (jsx-a11y) run in CI and block the build when violated.

  • Use a real <button> or <Link> for anything clickable. If you must attach onClick to a <div>, add role, tabIndex={0}, and a keyboard handler.
  • Do not remove focus outlines. The global :focus-visible baseline gives every control a consistent ring; keep it.
  • Give images meaningful alt text, and mark purely decorative images aria-hidden.