blob: d2ff64096c99e4625f0f8e744b80764f8447e046 [file] [view]
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# 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 value | Visual expression |
| ------------------------- | ---------------------------------------------------------------------------- |
| **One Layer, All Storage**| One accent, one type voice, one grid — convergence over decoration. |
| **Solid Foundation** | Hairline 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 First** | Content-first layout; code and capabilities lead, ornament follows. |
| **Extensible Architecture**| CSS 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
| Concern | Location |
| ------------------------------- | ----------------------------------------- |
| CSS variables + Infima mapping | `src/css/variables.css` |
| Global styles + motif | `src/css/global.css` |
| Landing sections | `src/components/landing/sections.jsx` |
| Code window / language tabs | `src/components/landing/CodeTabs.jsx` |
| Landing styles | `src/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 variable | Light | Dark | Use |
| --------------------- | -------------------- | ----------------- | ---------------------------- |
| `--odl-bg` | `ink-0` | `#0a0d11` | Page background |
| `--odl-bg-subtle` | `ink-50` | `#0e1218` | Alternating section bands |
| `--odl-surface` | `ink-0` | `#11161c` | Cards, code window |
| `--odl-fg` | `ink-900` | `#e7ebf0` | Body text |
| `--odl-fg-muted` | `ink-600` | `#9aa6b3` | Secondary text |
| `--odl-border` | `ink-200` | `#242c35` | Hairlines, dividers |
| `--odl-bar` | `ink-950` | `#f6f8fa` | The bar motif |
| `--odl-accent` | `blue-600` | `blue-300` | Links, emphasis |
| `--odl-action-bg` | `blue-600` | `blue-500` | Solid 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.25rem` → `8rem`).
- **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
| Component | Class(es) | Notes |
| ---------------- | ------------------------------------------ | ------------------------------------------------ |
| Primary button | `.btn .btnPrimary` | Solid `action-bg`; one primary action per view. |
| Secondary button | `.btn .btnSecondary` | Hairline outline, ink text. |
| On-dark buttons | `.btnOnDark` / `.btnOnDarkGhost` | For the dark CTA panel. |
| Eyebrow | `.odl-eyebrow` (global) | Mono + accent bar; section kicker. |
| Code window | `CodeTabs` | Window chrome + language tabs + Prism highlight. |
| Value card | `.valueCard` | Mono index, title, body; 1px-gap grid. |
| Service chip | `.serviceChip` | Mono name + 15px icon, grouped by family. |
| Binding / layer | `.bindingCard` / `.layerItem` | Icon + 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.