Integrating the EBRAINS Design System

This guide is for teams building applications outside the EBRAINS UI Ecosystem monorepo. If your app is a standalone React, Angular, Vue, or vanilla project and you want to adopt the EBRAINS design system, follow these steps.

By the end, your app will have access to the component library, design tokens, utility classes, and SVG brand assets — all installed from npm.

What’s Available

The design system is published to the @ebrains organization on npm:

PackageWhat it provides
@ebrains/components44+ Stencil web components (framework-agnostic)
@ebrains/assetsCSS framework, design tokens, fonts
@ebrains/svgsSVG logos, icons, and brand assets as inline strings
@ebrains/reactReact wrappers for all components
@ebrains/angularAngular wrappers for all components
@ebrains/vueVue wrappers for all components

You only install what you need. Most apps will use @ebrains/components (or a framework wrapper) plus @ebrains/assets.

Step 1: Install Packages

React App

Angular App

Vue App

Plain HTML / Vanilla JS

Step 2: Load Styles

You have two options for styling: the pre-built CSS file or a custom Tailwind build.

Option A: Pre-built CSS (simplest)

Import the full framework in your entry point:

Or via CDN in your HTML:

<link rel="stylesheet" href="https://unpkg.com/@ebrains/assets@latest/styles/output.css">

This gives you all utility classes (bg-*, text-*, f-heading-*, p-*, flex, grid-layout, etc.), design tokens as CSS variables, and font-face declarations. See CSS Framework for the full reference.

Option B: Tailwind Build (tree-shaken)

If you want only the classes your app actually uses, set up a custom Tailwind build. See Tailwind Migration for the full setup guide.

Option C: Variables Only (lightweight)

If you just need CSS variables and fonts (8KB):

Step 3: Use Components

In React

Import components from @ebrains/react — they auto-register the underlying web components:

import { EdsButton, EdsAccordion, EdsAlert, EdsTable } from '@ebrains/react'

function App() {
  return (
    <div className="container mx-auto p-32">
      <EdsButton label="Click me" intent="brand" />

      <EdsAccordion title="Details" variant="inverse" icon="information">
        <p>Accordion content here.</p>
      </EdsAccordion>

      <EdsAlert message="Success!" intent="success" icon="checkmark-filled" />

      <EdsTable
        tableData={JSON.stringify([
          { Name: 'Alice', Role: 'Engineer' },
          { Name: 'Bob', Role: 'Designer' },
        ])}
        theme="brand"
        sortingEnabled={true}
      />
    </div>
  )
}

In Angular

Import standalone components from @ebrains/angular:

import { Component } from '@angular/core';
import { EdsButton, EdsAlert, EdsAccordion } from '@ebrains/angular';

@Component({
  standalone: true,
  imports: [EdsButton, EdsAlert, EdsAccordion],
  template: `
    <eds-button label="Click me" intent="brand"></eds-button>
    <eds-accordion title="Details" variant="inverse" icon="information">
      <p>Content here.</p>
    </eds-accordion>
    <eds-alert message="Done!" intent="success" icon="checkmark-filled"></eds-alert>
  `
})
export class AppComponent {}

In Vue

Import components from @ebrains/vue:

<template>
  <EdsButton label="Click me" intent="brand" />
  <EdsAccordion title="Details" variant="inverse" icon="information">
    <p>Content here.</p>
  </EdsAccordion>
  <EdsAlert message="Done!" intent="success" icon="checkmark-filled" />
</template>

<script setup>
import { EdsButton, EdsAccordion, EdsAlert } from '@ebrains/vue'
</script>

In Plain HTML

Load the Stencil loader and use native custom elements:

<script type="module">
  import { defineCustomElements } from '@ebrains/components/loader';
  defineCustomElements(window);
</script>

<eds-button label="Click me" intent="brand"></eds-button>

<eds-accordion title="Details" variant="inverse" icon="information">
  <p>Content here.</p>
</eds-accordion>

<eds-alert message="Done!" intent="success" icon="checkmark-filled"></eds-alert>

See Plain HTML Setup for the full Vite configuration.

Step 4: Use SVG Assets

The @ebrains/svgs package exports all brand SVGs as inline strings:

Available exports:

ExportDescription
logoPositiveEBRAINS logo for light backgrounds
logoNegativeEBRAINS logo for dark backgrounds
euSvgEU flag
gitlabColorGitLab logo (color)
gitlabBlackGitLab logo (mono)
twitterX/Twitter icon
linkedinLinkedIn icon
facebookFacebook icon
youtubeYouTube icon
mastodonMastodon icon
blueskyBluesky icon

In React

import { logoNegative } from '@ebrains/svgs'

function Logo() {
  return (
    <div
      className="bg-strongest p-24 rounded-lg"
      dangerouslySetInnerHTML={{ __html: logoNegative }}
    />
  )
}

In Vue

<template>
  <div class="bg-strongest p-24 rounded-lg" v-html="logoNegative" />
</template>

<script setup>
import { logoNegative } from '@ebrains/svgs'
</script>

In Angular

import { Component } from '@angular/core';

@Component({
  template: '<div class="bg-strongest p-24 rounded-lg" [innerHTML]="logo"></div>'
})
export class LogoComponent {
  logo = require('@ebrains/svgs').logoNegative;
}

In Plain HTML

<div id="logo" class="bg-strongest p-24 rounded-lg"></div>

<script type="module">
  import { logoNegative } from '@ebrains/svgs';
  document.getElementById('logo').innerHTML = logoNegative;
</script>

Step 5: Style with Utility Classes

Once the CSS framework is loaded, use EBRAINS utility classes throughout your templates:

<!-- Layout -->
<div class="container mx-auto p-32">
  <div class="flex flex-col gap-16 md:flex-row md:gap-32">
    ...
  </div>
</div>

<!-- Typography -->
<h1 class="f-heading-01">Page Title</h1>
<p class="f-body-02">Body text content.</p>
<span class="f-ui-02">Interface label</span>

<!-- Colors -->
<div class="bg-strongest text-inverse p-16 rounded-lg">
  Dark section with light text
</div>
<div class="bg-accent text-default p-16 rounded-lg">
  Brand green section
</div>

<!-- Spacing -->
<div class="p-24 mb-32 gap-12">Padded with margin and gap</div>

<!-- Shadows -->
<div class="shadow-md rounded-lg p-16">Elevated card</div>

See CSS Framework for the full class reference, and Tokens for the underlying design token values.

Quick Reference

Component Naming

ContextConventionExample
ReactPascalCase<EdsButton>
Angularkebab-case (in template)<eds-button>
VuePascalCase or kebab-case<EdsButton> or <eds-button>
Plain HTMLkebab-case<eds-button>

Prop Naming

ContextConventionExample
ReactcamelCasepressableLabel="..."
AngularcamelCase (property binding)[pressableLabel]="..."
VuecamelCase:pressable-label="..."
Plain HTMLkebab-casepressable-label="..."

Passing Complex Data

Objects and arrays must be passed as JSON strings in HTML attributes:

<!-- Plain HTML / Angular template -->
<eds-table
  table-data='[{"Name":"Alice"},{"Name":"Bob"}]'
  config='{"Name":{"format":"bold"}}'
></eds-table>

<!-- React (pass as JS objects) -->
<EdsTable
  tableData={JSON.stringify(data)}
  config={JSON.stringify(config)}
/>

Event Handling

ContextHow
ReactonEdsalert={handler} or onClick={handler}
Angular(edsalert)="handler($event)"
Vue@edsalert="handler"
Plain HTMLelement.addEventListener('edsalert', handler)

Minimal Example: New React App

Create a fresh React app and integrate the design system in minutes:

Then in src/main.tsx:

And in src/App.tsx:

import { EdsButton, EdsAlert } from '@ebrains/react'
import { logoPositive } from '@ebrains/svgs'

function App() {
  return (
    <div className="container mx-auto p-32">
      <div dangerouslySetInnerHTML={{ __html: logoPositive }} />
      <h1 className="f-heading-02 mb-16">My EBRAINS App</h1>
      <EdsAlert message="Welcome!" intent="success" icon="checkmark-filled" />
      <EdsButton label="Get Started" intent="brand" />
    </div>
  )
}

That’s it — components, styles, and SVGs working in a standalone project with zero monorepo dependencies.

Reference Examples

The UI Ecosystem monorepo includes sandbox apps that demonstrate the full integration for each framework:

AppFrameworkWhat it tests
apps/sandbox/test-reactReact + ViteReact wrappers + Tailwind factory build
apps/sandbox/test-webPlain HTML + ViteStencil loader + native custom elements
apps/sandbox/test-angularAngularAngular standalone wrappers
apps/sandbox/test-react-nativeReact NativeDesign tokens via StyleSheet (no web components)