OpenDAL Design System

One Layer, All Storage. A precise, engineering-grade visual language for Apache OpenDAL™ — built to feel as dependable, fast and composable as the library itself.

This document is the source of truth for OpenDAL's web visual language. The landing page (src/pages/index.jsx) is its first full application; docs and blog inherit it through Infima variable mapping.


1. Design principles

The visual system is a direct translation of OpenDAL's engineering values.

Library valueVisual expression
One Layer, All StorageOne accent, one type voice, one grid — convergence over decoration.
Solid FoundationHairline structure, precise alignment, restraint. Nothing is decorative-only.
Fast Access (zero-cost)System fonts, no web-font requests, CSS-only motion. The page costs nothing it doesn't need.
Object Storage FirstContent-first layout; code and capabilities lead, ornament follows.
Extensible ArchitectureCSS variables compose; components are presentational and reusable.

Operating posture: engineering-minimal, light-first (dark mode is a first-class, fully designed peer), near-monochrome ink with a single precise-blue accent, and the signature solid bar lifted from the OpenDAL wordmark.


2. Where the system lives

ConcernLocation
CSS variables + Infima mappingsrc/css/variables.css
Global styles + motifsrc/css/global.css
Landing sectionssrc/components/landing/sections.jsx
Code window / language tabssrc/components/landing/CodeTabs.jsx
Landing stylessrc/components/landing/styles.module.css
Content model (copy, catalogs)src/components/landing/data.js

All shared design values are encoded as CSS custom properties, also called CSS variables, prefixed --odl-* in src/css/variables.css. Components never hardcode raw values when a matching --odl-* variable exists.


3. Color

3.1 Primitives

Ink — a cool, neutral near-black → white ramp (the monochrome backbone):

--odl-ink-{0,50,100,150,200,300,400,500,600,700,800,850,900,950} from #ffffff to #0a0d11.

Precise blue — the single brand accent:

--odl-blue-{50…900} from #edf3ff to #163172; --odl-blue-600 #1e54e0 is the canonical light-mode accent.

Functional signals (--odl-green/amber/red-*) exist mostly so inherited docs UI (admonitions, etc.) stay on-system. They are intentionally muted.

3.2 Semantic roles (theme-aware)

Components use semantic CSS variables, not primitive color variables:

CSS variableLightDarkUse
--odl-bgink-0#0a0d11Page background
--odl-bg-subtleink-50#0e1218Alternating section bands
--odl-surfaceink-0#11161cCards, code window
--odl-fgink-900#e7ebf0Body text
--odl-fg-mutedink-600#9aa6b3Secondary text
--odl-borderink-200#242c35Hairlines, dividers
--odl-barink-950#f6f8faThe bar motif
--odl-accentblue-600blue-300Links, emphasis
--odl-action-bgblue-600blue-500Solid CTA background

3.3 Rules

  • Black/white leads, blue accents. Blue is for interaction, emphasis and code highlight — never large fills (except the solid CTA).
  • Contrast: body and accent text meet WCAG AA (≥ 4.5:1) in both themes; white-on-action-bg passes for buttons. Dark mode lifts the accent to a lighter blue rather than inverting it.
  • Never rely on color alone — pair with the bar, an icon, or a label.

4. Typography

4.1 Stacks & rationale

--odl-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, …
--odl-font-mono: ui-monospace, "SF Mono", "Cascadia Code", "JetBrains Mono", …

System stacks are a deliberate choice, not a fallback: zero third-party requests (ASF privacy-friendly), zero layout shift, instant and globally consistent rendering (OpenDAL has a large global user base). The wordmark already carries the brand letterforms.

Monospace is promoted to a brand voice. It marks anything structural or technical — eyebrows/kickers, section indices, statistics, service names, code. This gives the minimal system its engineering character without a custom font.

To adopt IBM Plex instead: self-host via @fontsource/ibm-plex-sans and @fontsource/ibm-plex-mono, @import the weights in variables.css, and set --odl-font-sans/--odl-font-mono accordingly. The rest of the system needs no changes.

4.2 Scale

--odl-text-2xs (11px) · xs (12) · sm (14) · base (16) · md (18) · lg (22) · xl (28) · 2xl (36) · 3xl (48) · display clamp(44–80px).

Headings: weight 650–700, tracking -0.022em. Body: 400, line-height 1.6. Mono labels: uppercase, tracking 0.12em.


5. Spacing & layout

  • 4px rhythm: --odl-space-1…10 (0.25rem8rem).
  • Container: --odl-container 1200px, --odl-container-narrow 880px, fluid --odl-gutter clamp(1.25–2.5rem). Use the global .odl-container.
  • Section rhythm: vertical padding clamp(3.5rem, 7rem), every section separated by a single hairline (border-top: 1px var(--odl-border)), alternating with --odl-bg-subtle bands.

6. Radius & elevation

  • Radius: --odl-radius-xs 3 / sm 5 / md 8 / lg 12 / pill. Restrained by design. The bar motif is always sharp (radius 0).
  • Elevation: --odl-shadow-sm/md/lg. Prefer border-based separation; reserve real shadow for floating surfaces (the code window).

7. Motion

  • Use --odl-dur-fast 120ms, --odl-dur 200ms, and --odl-dur-slow 320ms with --odl-ease or --odl-ease-out.
  • Keep micro-interactions short: hover, tab changes, and button presses should finish within 120–200ms.
  • Use CSS-only reveal-on-scroll through .reveal and animation-timeline: view(). Browsers without support must show content immediately.
  • Animate opacity and transform by default. Animate layout only when it fixes a real layout jump, keep the movement local, and disable it for prefers-reduced-motion.
  • Never block input with animation.

8. The bar motif

The solid rectangle from the OpenDAL wordmark is the system's signature mark.

  • .odl-bar — a sharp solid rectangle for dividers/emphasis.
  • .odl-eyebrow — the canonical section kicker: monospace, uppercase, led by a small accent bar. Used above every section title.
  • As a top-border accent on principle cards, and as the section-title marker.

Used consistently, the bar makes the minimal system unmistakably OpenDAL.


9. Component patterns

ComponentClass(es)Notes
Primary button.btn .btnPrimarySolid action-bg; one primary action per view.
Secondary button.btn .btnSecondaryHairline outline, ink text.
On-dark buttons.btnOnDark / .btnOnDarkGhostFor the dark CTA panel.
Eyebrow.odl-eyebrow (global)Mono + accent bar; section kicker.
Code windowCodeTabsWindow chrome + language tabs + Prism highlight.
Value card.valueCardMono index, title, body; 1px-gap grid.
Service chip.serviceChipMono name + 15px icon, grouped by family.
Binding / layer.bindingCard / .layerItemIcon + mono label in a hairline grid.

Layout grids use a 1px gap over a border-colored background to render crisp hairline dividers between cells — a precise, technical signature.


10. Do / Don't

Do

  • Lead with ink; use blue for interaction and emphasis.
  • Use monospace for labels, indices, figures and code.
  • Keep one primary CTA per view; separate secondary actions.
  • Reach for hairlines and spacing before shadows and fills.
  • Design and test light and dark together.

Don't

  • Introduce a second accent hue or gradients-as-decoration.
  • Use emoji as icons (use the existing SVG sets in static/img/*).
  • Hardcode hex in components when a matching --odl-* CSS variable exists.
  • Add motion that conveys nothing or ignores prefers-reduced-motion.

11. Accessibility checklist

  • [ ] Text/accent contrast ≥ 4.5:1 (AA) in light and dark.
  • [ ] Show a visible :focus-visible state on every interactive element. Use the 2px accent ring by default. Use a compact accent outline, underline, or border for dense icon controls, window chrome links, and text inputs when the default ring overpowers the control.
  • [ ] Decorative icons use empty alt; meaning carried by adjacent text.
  • [ ] Code tabs are a proper tablist/tab/tabpanel with arrow-key support.
  • [ ] prefers-reduced-motion respected globally.
  • [ ] Layout holds at 375 / 768 / 1024 / 1440px without horizontal scroll.