OpenELIS Global Style Guide — v1 Foundations
OpenELIS Global — Style Guide v1 Foundations
Status: Published v1 Foundations (2026-04-23)
Owner: Casey Iiams-Hauser · Audience: Developers + designers contributing to OpenELIS Global
Source of truth: Live app attesting.openelis-global.org+DIGI-UW/OpenELIS-Global-2developbranch. All tokens in this document are observed from the shipped app, not aspirational.
Supersedes: Replaces the prior body of this page (Taib, May 2025) in color + typography sections. Prior framing is preserved in §1 and §2. See §13 Migration notes.
Table of contents
Purpose & scope
Design system stack
Brand tokens
Typography
Color
Spacing, radius, elevation
Forms
Voice & tone
Notifications
Accessibility floor
Known non-Carbon utilities
Appendix — known technical debt
Migration notes
1. Purpose & scope
OpenELIS Global is a laboratory information system used across diverse health systems and countries. Each deployment has different needs, but they share the same challenges: inconsistent user experience, uneven frontend tooling, and fragmented engineering practices across contributors. Historically, visual and interaction design across OpenELIS implementations has drifted, making collaboration harder and increasing the cost of maintenance and onboarding.
This guide is the response. It sets the baseline for a unified, modern, accessible design language across every OpenELIS Global interface, regardless of country, customization, or use case. It helps contributors ship faster with fewer regressions. It ensures the software stays usable for everyone — users on low-bandwidth networks, older hardware, and varying levels of digital literacy or ability.
This documentation is not theoretical. It is derived from the shipped app and the repo — real implementation experience, active deployments, and the lessons of maintaining a global open-source LIS. The aim is to reduce guesswork, eliminate inconsistency, and make OpenELIS easier to contribute to, extend, and scale.
Objectives
A clear, consistent user experience across every OpenELIS interface.
Maintainability and scalability of both design and code.
Accessibility, internationalization, and responsive behavior by default.
A shared vocabulary that lets distributed contributors collaborate without re-litigating decisions.
Who this guide is for
Software engineers writing frontend or backend code that touches the UI.
UX/UI designers producing layouts, workflows, and visual elements.
QA testers verifying functionality aligns with expected behavior.
Documentation writers preparing user manuals and technical guides.
Implementers and administrators customizing or deploying OpenELIS for a specific lab or country.
What v1 covers (and what it doesn't)
v1 covers brand tokens, typography, color, spacing/radius, forms, voice & tone, notifications, accessibility floor, and known non-Carbon utilities.
v1 does not cover component-level patterns (data tables, workplan grids, referral queues, report shells), page-shell patterns, iconography catalog, or data-viz conventions. Those land in v2 Patterns.
How to use this page
Every section has a stable heading. Reference those headings from Jira stories, PR descriptions, and design reviews. If a new UI introduces something this guide doesn't cover, the default is to follow Carbon upstream and raise a v2 Patterns ticket.
2. Design system stack
Why Carbon
OpenELIS Global adopts the IBM Carbon Design System as the foundation for its UI layer. Carbon is professionally maintained, actively developed, shipped with a first-class React component library, has strong accessibility defaults built in, and provides a token-based theming surface that makes it straightforward to apply OpenELIS's brand without maintaining a bespoke component library.
Carbon enables OpenELIS to maintain a unified, scalable interface while reducing maintenance overhead. Contributors focus on lab-specific functionality rather than on reinventing inputs, tables, and modals.
Alternative design systems (Ant Design, Material UI, Bootstrap) were considered; Carbon was chosen for: (1) open-source enterprise-grade maintenance by IBM, (2) explicit design-token + theming architecture that supports the split-shell brand override we ship, (3) native React components with TypeScript support, and (4) strong accessibility + i18n story aligned with OpenELIS's global deployment profile.
Key principles for implementers
Consistency — Use Carbon components for all new features. Do not reach for non-Carbon alternatives when a Carbon component exists.
Extensibility — Customize via Carbon theme tokens, not custom CSS. The split-shell brand override is the template.
Interoperability — Follow Carbon's API patterns when integrating with third-party libraries (Formik, charting, maps, etc.).
Dependency matrix
The shipped versions (from frontend/package.json):
Package | Version | Role |
|---|---|---|
|
| Current React component library (class prefix |
|
| Token packages (White, Gray 10, Gray 90, Gray 100) |
|
| Iconography |
|
| Data visualization |
| — | React bindings for charts |
|
| Legacy v10 (class prefix |
|
| Still on React 17 |
|
| SCSS compiler |
|
| Micro-frontend plumbing for JSP ↔ React coexistence |
Rule: New code uses @carbon/react (prefix cds--) only. Do not introduce new carbon-components v10 (bx--) imports. Existing v10 usage is legacy and will be migrated out incrementally.
3. Brand tokens
OpenELIS ships a split-shell theme: the top header and left side nav render in Carbon's g100 dark theme with a navy override; the content area renders in Carbon's White theme with a custom warm-light background.
Canonical theme file: frontend/src/index.scss
Token | Value | Where applied |
|---|---|---|
Brand navy |
|
|
Brand navy (hover) |
|
|
Content background |
|
|
Shell text on navy |
| Header and side-nav |
For implementers rebranding OpenELIS: change --site-branding-header for the header color, and the layer-01 override in index.scss for the side nav. Those are the two hooks.
The #0f62fe Carbon Blue 60 still governs primary buttons, links, and focus rings inside the content area — that's unchanged from Carbon defaults.
4. Typography
Base font stack (shipped):
"IBM Plex Sans", system-ui, -apple-system, "system-ui", ".SFNSText-Regular", sans-serifBody: 16px / 400 / #161616 (Carbon Gray 100). Links: #0f62fe / 14px (Carbon Blue 60, --cds-link-primary).
Heading rule
Semantic heading level must match the Carbon productive-type scale:
HTML element | Carbon token | Size | Weight | Use |
|---|---|---|---|---|
|
| 42px | 300 | Page title (one per page) |
|
| 32px | 400 | Primary section |
|
| 28px | 400 | Subsection |
|
| 20px | 400 | Sub-subsection |
|
| 16px | 600 | Small heading |
|
| 14px | 600 | Label-like heading |
Known drift (flag for cleanup): the current order-entry page uses h2 at both 32px and 20px and h3 at 28px — heading levels don't correlate with the type scale. Also, dashboard h4 is styled with #4b5563 (Tailwind Gray 600), not a Carbon gray. New code must conform to the table above; cleanup tickets are queued in §12.
Numeric + tabular data: use font-variant-numeric: tabular-nums on tables of counts, accession numbers, and result values so digits align across rows.
Line-height and letter-spacing come from the Carbon type tokens themselves — do not override them with custom values. If a layout feels too tight or too loose, adjust container spacing, not the font metrics.
Do not use all-caps headings. Do not introduce new font families.
Carbon type token reference
A shorthand mapping between Carbon type tokens and their typical role in OpenELIS:
Carbon token | Role | Use |
|---|---|---|
| Page title | h1 on page shells |
| Major section | h2 section breaks |
| Subsection | h3 subsections |
| Minor subsection | h4 within a section |
| Small heading | h5, card / panel title |
| Label-like heading | h6, table header emphasis |
| Long-form body | Paragraph body in descriptive content |
| Default body | Body copy in forms and admin pages |
| Compact body | Inline text in table cells |
| Labels and UI text | Input labels, small UI text |
| Helper text | Helper text under form inputs, captions |
| Form labels | Input and select labels |
5. Color
OpenELIS uses Carbon White as the base content theme, with the split-shell navy described in §3. Status + notification semantic colors come from Carbon directly and are pinned below.
Status + notification colors (Carbon)
Semantic role | Token | Hex |
|---|---|---|
Error / danger |
|
|
Warning |
|
|
Success |
|
|
Info |
|
|
Neutral scale (in use)
Token | Hex | Use |
|---|---|---|
|
| Tile, modal, input background (Carbon White theme) |
|
| Field 01, card surfaces |
Content area override |
|
|
|
| Dividers |
|
| Body text, icons |
|
| De-emphasized text, helper text |
|
| Placeholders, disabled text |
Interaction tokens (Carbon defaults in the content area)
These are Carbon defaults that drive buttons, links, and focus — they are NOT the OpenELIS brand (navy #295785 is). They govern interactive elements inside the White-theme content area only.
Token | Hex | Use |
|---|---|---|
|
| Primary link color, primary button |
|
| Secondary link, hover state |
|
| Visited link |
|
| Primary action button |
|
| Secondary action button |
|
| Secondary button hover |
|
| Tertiary action button |
|
| Focus ring (do not override) |
Rule: if you're about to introduce a hex value that isn't in this page or in Carbon's default tokens, stop — you're drifting. Use the nearest Carbon token or file a ticket to extend this page.
6. Spacing, radius, elevation
Spacing
Use Carbon's 8px-step spacing scale via tokens: $spacing-01 (2px) through $spacing-13 (160px). The most common in OpenELIS: $spacing-03 (8px), $spacing-05 (16px), $spacing-07 (32px).
Do not use raw pixel values in new code. Do not use Tailwind spacing utilities.
Radius
OpenELIS is a sharp-cornered app. border-radius: 0 is the default across inputs, buttons, cards, modals, and tiles. Carbon's own default.
Two intentional exceptions:
Element | Radius | Rationale |
|---|---|---|
Dashboard tiles |
| Deliberate softness on the dashboard home — the one place users spend free-scan time |
Tags ( |
| Carbon tag default — pill-style |
Do not introduce other radii. If you think you need one, file a ticket first.
Elevation
Use Carbon's $shadow tokens for elevation (modals, dropdowns). Do not layer custom box-shadow values.
7. Forms
OpenELIS uses @carbon/react inputs wired to formik for state + yup for validation.
Field anatomy
Property | Value |
|---|---|
Field height |