Tokens
Every visual value in the component library is a token, and every token is a CSS custom-property reference with a neutral fallback:
import { tokens } from "@nimblebrain/synapse/ui";
tokens.bg; // "var(--color-background-primary, #ffffff)"tokens.accent; // "var(--color-text-accent, #2563eb)"Components never hold a hex value. They style with these var() references, so
the pixels are decided by whatever fills the custom properties.
How the host fills them
Section titled “How the host fills them”Under the MCP ext-apps protocol, the host injects a :root block of CSS
variables into your app’s iframe: the hostContext.styles.variables payload.
Every var(--token, …) in the library re-resolves against that block:
:root { --color-background-primary: #0b0b0f; --color-text-primary: #f4f4f5; --color-text-accent: #a78bfa; --font-sans: "Your Brand Sans", system-ui, sans-serif; --border-radius-md: 0.5rem;}Because resolution happens in CSS, a theme change (including a light-to-dark
flip) is just the host swapping those variables. Every var() re-resolves and
the UI repaints with no React re-render.
Standalone, the library still renders. With no host to inject anything, color
tokens resolve through the synapse-defaults cascade layer, so they stay
theme-correct in dark as well as light — a var() fallback is a static literal and
cannot do that. That layer is installed when a theme is applied, so it covers a
connection with no host behind it (the inline adapter, or a host that ships no
tokens) but not a render that never connects at all, such as a Storybook story or a
unit test; there, and for everything the layer never covers — fonts, radii, shadows —
tokens fall back to their second argument: system fonts and plain geometry. The
library stays usable and unbranded rather than blank. See
Theming for the full resolution order.
Surfaces
Section titled “Surfaces”Background layers, lightest to most recessed.
| Token | CSS variable | Neutral fallback |
|---|---|---|
bg |
--color-background-primary |
#ffffff |
bgRaised |
--color-background-secondary |
#fafafa |
bgSubtle |
--color-background-tertiary |
#f3f4f6 |
Foreground tones plus the accent pair.
| Token | CSS variable | Neutral fallback |
|---|---|---|
fg |
--color-text-primary |
#111827 |
fgMuted |
--color-text-secondary |
#6b7280 |
fgFaint |
--color-text-tertiary |
#9ca3af |
accent |
--color-text-accent |
#2563eb |
accentFg |
--nb-color-accent-foreground |
#ffffff |
accentFg is the foreground that sits on top of an accent fill: the label
color for a primary button, for instance.
Border and ring
Section titled “Border and ring”| Token | CSS variable | Neutral fallback |
|---|---|---|
border |
--color-border-primary |
#e5e7eb |
borderStrong |
--color-border-secondary |
#d1d5db |
ring |
--color-ring-primary |
#2563eb |
ring is the focus-ring color; borderWidth (below) sets its width.
Status semantics
Section titled “Status semantics”Semantic colors for state. Each …Light pairs a saturated hue with a tinted
background for badges, banners, and status rows.
| Token | CSS variable | Neutral fallback |
|---|---|---|
danger |
--nb-color-danger |
#dc2626 |
success |
--nb-color-success |
#059669 |
warning |
--nb-color-warning |
#f59e0b |
processing |
--nb-color-processing |
#7c3aed |
processingLight |
--nb-color-processing-light |
#f3eeff |
infoLight |
--nb-color-info-light |
#eef4ff |
Fonts and weights
Section titled “Fonts and weights”Three faces and four weights. The face tokens only name a font — the library ships no font files, so these resolve to the web-safe fallbacks below unless the host supplies the faces. See Host fonts.
| Token | CSS variable | Neutral fallback |
|---|---|---|
fontSans |
--font-sans |
system-ui, -apple-system, BlinkMacSystemFont, sans-serif |
fontMono |
--font-mono |
ui-monospace, SFMono-Regular, Menlo, monospace |
fontHeading |
--nb-font-heading |
system-ui, -apple-system, BlinkMacSystemFont, sans-serif |
weightNormal |
--font-weight-normal |
400 |
weightMedium |
--font-weight-medium |
500 |
weightSemibold |
--font-weight-semibold |
600 |
weightBold |
--font-weight-bold |
700 |
Type scale
Section titled “Type scale”Every level is a size and a paired line-height. Body text has four sizes,
consumed by Text; headings have three, consumed by
Heading. The helpers textStyle(size) and
headingStyle(size) return the matching fontSize / lineHeight pair.
Text sizes
Section titled “Text sizes”| Size | Size variable | Size fallback | Line-height variable | Line-height fallback |
|---|---|---|---|---|
xs |
--font-text-xs-size |
0.75rem |
--font-text-xs-line-height |
1rem |
sm |
--font-text-sm-size |
0.875rem |
--font-text-sm-line-height |
1.25rem |
base |
--font-text-base-size |
1rem |
--font-text-base-line-height |
1.5rem |
lg |
--font-text-lg-size |
1.125rem |
--font-text-lg-line-height |
1.75rem |
Heading sizes
Section titled “Heading sizes”| Size | Size variable | Size fallback | Line-height variable | Line-height fallback |
|---|---|---|---|---|
sm |
--font-heading-sm-size |
1.25rem |
--font-heading-sm-line-height |
1.75rem |
md |
--font-heading-md-size |
1.5rem |
--font-heading-md-line-height |
2rem |
lg |
--font-heading-lg-size |
2rem |
--font-heading-lg-line-height |
2.5rem |
Corner rounding, extra-small to extra-large.
| Token | CSS variable | Neutral fallback |
|---|---|---|
radiusXs |
--border-radius-xs |
0.25rem |
radiusSm |
--border-radius-sm |
0.5rem |
radiusMd |
--border-radius-md |
0.75rem |
radiusLg |
--border-radius-lg |
1rem |
radiusXl |
--border-radius-xl |
1.5rem |
Border width
Section titled “Border width”| Token | CSS variable | Neutral fallback |
|---|---|---|
borderWidth |
--border-width-regular |
1px |
Shadows
Section titled “Shadows”Elevation from a flat hairline outline up to a lifted overlay.
| Token | CSS variable | Neutral fallback |
|---|---|---|
shadowHairline |
--shadow-hairline |
0 0 0 1px rgba(0,0,0,0.06) |
shadowSm |
--shadow-sm |
0 1px 2px rgba(0,0,0,0.05) |
shadowMd |
--shadow-md |
0 4px 6px -1px rgba(0,0,0,0.1) |
shadowLg |
--shadow-lg |
0 10px 15px -3px rgba(0,0,0,0.1) |