This page is for OFFER-HUB contributors working on the documentation site itself. It is not part of the public marketplace-integration guidance for teams consuming the Orchestrator API or SDK.
Internal contributor documentation for the OFFER-HUB documentation site's design system.
This page is for OFFER-HUB contributors working on the documentation site itself. It is not part of the public marketplace-integration guidance for teams consuming the Orchestrator API or SDK.
This guide documents the OFFER-HUB design system, including colors, typography, and component styling for both light and dark modes.
Use ParamTable for request parameters and ResponseSchema for response fields. Both components use the theme tokens and keep wide tables inside a labelled, keyboard-focusable scroll region on small screens. Nested fields start expanded and can be collapsed; field metadata supports defaults, enums, nullable values, and deprecation notes.
The example below is reviewed against the checked-in Orchestrator contract at public/openapi.json: the /balances operation (get-user-balances) and its response example. In the orchestrator source, keep the corresponding controller and DTO references alongside the contract when updating a schema page.
| Name | Type | Required | Description |
|---|---|---|---|
page | number | No | Page number. Default: 1 |
limit | number | No | Results per page (maximum 100). Default: 20 |
currency | string | null | No | Filter by currency. One of: USDXLMUSDCNullable |
| Name | Type | Required | Description |
|---|---|---|---|
code | number | Yes | HTTP-style response code. |
type | string | Yes | Response classification. One of: successerror |
ok | boolean | Yes | Whether the request succeeded. |
message | string | Yes | Human-readable result message. |
data | object | Yes | Payload returned by the balances controller. |
balances | array | Yes | Available and held balances grouped by currency. |
currency | string | Yes | Currency code. |
available | number | Yes | Spendable balance. |
held | number | Yes | Reserved balance. |
{
"code": 200,
"type": "success",
"ok": true,
"message": "Balances retrieved",
"data": {
"balances": [
{
"currency": "USD",
"available": 1250,
"held": 200
}
]
}
}OFFER-HUB uses CSS variables for theme-aware colors. All colors automatically adapt when switching between light and dark modes.
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--color-bg-base | #F1F3F7 | #1a1a2e | Page background |
--color-bg-elevated | #ffffff | #25253d | Cards, modals, elevated surfaces |
--color-bg-sunken | #e8eaef | #12121f | Inset areas, input backgrounds |
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--color-text-primary | #19213D | #f1f3f7 | Headings, primary text |
--color-text-secondary | #6D758F | #a0a6b8 | Body text, descriptions |
--color-text-muted | #9ca3af | #6D758F | Placeholder text, hints |
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--color-primary | #149A9B | #1fb8b9 | Primary buttons, links, accents |
--color-primary-hover | #0d7377 | #25d4d5 | Primary hover states |
--color-secondary | #002333 | #002333 | Secondary elements |
--color-accent | #15949C | #15949C | Accent highlights |
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--color-success | #16a34a | #16a34a | Success states |
--color-warning | #d97706 | #d97706 | Warning states |
--color-error | #FF0000 | #FF0000 | Error states |
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--shadow-dark | #d1d5db | #0f0f1a | Dark shadow in neumorphic effects |
--shadow-light | #ffffff | #252540 | Light shadow in neumorphic effects |
| Token | Light Mode | Dark Mode | Usage |
|---|---|---|---|
--color-border | #d1d5db | #3d3d5c | Borders, dividers |
Use these Tailwind classes for theme-aware styling:
OFFER-HUB uses Inter as the primary font:
| Weight | Class | Usage |
|---|---|---|
| 400 | font-normal | Body text |
| 500 | font-medium | Emphasis, labels |
| 700 | font-bold | Headings, buttons |
| 900 | font-black | Hero titles |
| Size | Class | Usage |
|---|---|---|
| 12px | text-xs | Small labels |
| 13px | text-[13px] | Nav links |
| 14px | text-sm | Body text, buttons |
| 16px | text-base | Default body |
| 18-24px | text-lg to text-2xl | Subheadings |
| 32-48px | text-3xl to text-5xl | Section titles |
| 56-72px | text-6xl to text-7xl | Hero titles |
All generated diagrams (Mermaid today — the same token contract is designed to carry over to a future static/offline pipeline) share one neumorphic theme module: src/lib/diagram-theme.ts. It reads colors directly from the CSS custom properties documented above — never hardcoded hex values — so every diagram matches the current site in both light and dark mode automatically, with no per-diagram theme code.
readDiagramColorTokens() reads --color-bg-elevated, --color-bg-sunken, --color-text-primary, --color-text-secondary, --color-border, --shadow-dark, and --shadow-light from whichever scope (:root or .dark) is active.getMermaidThemeVariables() maps those tokens onto Mermaid's themeVariables (node fill, text, line color, cluster background). Node and cluster borders use the neutral --color-border token — never --color-primary — so diagram structure reads through soft shadow depth, not a colored outline.getNeumorphicDiagramCSS() applies the same dual drop-shadow used by shadow-neu-raised (dark shadow bottom-right, light highlight top-left — the 145° light source from docs/design/neumorphism.md) directly to every node shape, via Mermaid's themeCSS hook.src/components/shared/MermaidDiagram.tsx is the single rendering component; src/components/docs/MermaidDiagram.tsx and src/components/architecture/MermaidDiagram.tsx are thin re-exports of it. Every fenced mermaid code block in MDX renders through it automatically via src/components/docs/mdx-components.tsx, so it already produces a correct light and a correct dark rendering of each diagram — no separate -light/-dark source files to maintain until the static diagram pipeline (tracked separately) lands.--color-text-primary, documented in docs/design/color-palette.md at 12.5:1 contrast against --color-bg-elevated — well past the 4.5:1 WCAG AA requirement for text.lineColor) use --color-text-secondary, documented at 4.8:1 against the base background — past the 3:1 AA requirement for non-text graphical elements.border-l-4-style accent bar. Contribute new diagram styling through diagram-theme.ts only.Every shape below renders through the shared theme. State names are taken from the Orchestrator's real order lifecycle (docs/architecture/state-machines.md, "Order States", in the OFFER-HUB/OFFER-HUB repo) instead of placeholder labels.
| Value | Usage |
|---|---|
-1 | Background effects (dot grid) |
0 | Default content |
10 | Elevated cards |
50 | Sticky elements |
100 | Dropdowns |
499 | Mobile menu backdrop |
500 | Navbar |
501 | Mobile menu panel |
Ensure content cards have a higher z-index than background effects (like the dot grid) to prevent visual overlap.
The theme can be toggled using the useTheme hook:
Theme preference is automatically saved to localStorage under the key offer-hub-theme and persists across sessions.
When set to "system", the theme automatically follows the user's OS preference and updates in real-time if changed.
When migrating components to support dark mode, replace hardcoded colors with theme-aware alternatives:
| Before (Hardcoded) | After (Theme-aware) |
|---|---|
bg-[#F1F3F7] | bg-bg-base |
bg-white | bg-bg-elevated |
text-[#19213D] | text-content-primary |
text-[#6D758F] | text-content-secondary |
text-[#149A9B] | text-theme-primary |
border-[#d1d5db] | border-theme-border |
style={{ background: "#F1F3F7" }} | className="bg-bg-base" |
style={{ color: "#19213D" }} | className="text-content-primary" |
Always test components in both light and dark modes after migration to ensure proper contrast and visibility.