Skip to content

Semantic Tokens

Semantic tokens provide meaning to design values. They describe what a value is used for, not what it looks like. Most importantly, they adapt automatically to themes.

Semantic colors are the primary way to apply color in Synchronicity. They resolve to different primitives based on the active theme.

TokenLightDarkTrue Black
backgroundcream-10void-90void-100
surfacecream-20void-80void-90
surface-elevatedcream-10void-70void-80
// Light mode
lightColors.background // #faf8f3 (cream-10)
lightColors.surface // #f5f2ea (cream-20)
// Dark mode
darkColors.background // #0a0a0f (void-90)
darkColors.surface // #12121a (void-80)
// True Black
trueBlackColors.background // #000000 (void-100)
trueBlackColors.surface // #0a0a0f (void-90)
TokenLightDarkTrue Black
text-primarywarm-90cool-10cool-10
text-secondarywarm-60cool-50cool-50
text-tertiarywarm-50cool-60cool-60
text-disabledwarm-40cool-70cool-70
text-inversecool-10warm-90warm-90
TokenValueUsage
gold-primarygold-60Primary brand color
gold-secondarygold-50Lighter brand accent
gold-hovergold-70Hover state
gold-pressedgold-80Pressed state
gold-subtlegold-10Subtle backgrounds
TokenLightDarkTrue Black
bordercream-40void-60void-70
border-subtlecream-30void-70void-80
border-strongcream-50void-50void-60
border-focusgold-60gold-60gold-60
TokenValueUsage
success#22c55ePositive feedback
error#ef4444Errors, destructive
warning#f59e0bCaution, attention
info#3b82f6Information
// Light theme colors
export const lightColors = {
// Backgrounds
background: '#faf8f3',
surface: '#f5f2ea',
'surface-elevated': '#faf8f3',
// Text
'text-primary': '#1a1814',
'text-secondary': '#6b6459',
'text-tertiary': '#8c8579',
'text-disabled': '#a9a295',
'text-inverse': '#f8f9fa',
// Gold
'gold-primary': '#d4af37',
'gold-secondary': '#eec33e',
'gold-hover': '#b8962f',
'gold-pressed': '#9a7d27',
'gold-subtle': '#fef9e7',
// Borders
border: '#ddd8ca',
'border-subtle': '#ebe7dc',
'border-strong': '#c9c4b5',
'border-focus': '#d4af37',
// States
success: '#22c55e',
error: '#ef4444',
warning: '#f59e0b',
info: '#3b82f6',
};

Semantic spacing maps numeric values to meaningful names.

TokenValueUsage
xs4pxTight gaps, icon spacing
sm8pxCompact spacing
md16pxStandard spacing
lg24pxGenerous spacing
xl32pxSection spacing
2xl48pxLarge sections
3xl64pxPage sections
export const spacing = {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
'2xl': 48,
'3xl': 64,
};

Semantic type scale with complete text styles.

export const typography = {
display: {
fontSize: 48,
fontWeight: '700',
lineHeight: 56,
letterSpacing: -0.5,
},
h1: {
fontSize: 32,
fontWeight: '700',
lineHeight: 40,
letterSpacing: -0.5,
},
h2: {
fontSize: 24,
fontWeight: '600',
lineHeight: 32,
letterSpacing: 0,
},
h3: {
fontSize: 20,
fontWeight: '600',
lineHeight: 28,
letterSpacing: 0,
},
'body-lg': {
fontSize: 17,
fontWeight: '500',
lineHeight: 26,
letterSpacing: 0,
},
body: {
fontSize: 15,
fontWeight: '400',
lineHeight: 22,
letterSpacing: 0,
},
'body-sm': {
fontSize: 13,
fontWeight: '400',
lineHeight: 18,
letterSpacing: 0,
},
caption: {
fontSize: 12,
fontWeight: '500',
lineHeight: 16,
letterSpacing: 0.5,
},
footnote: {
fontSize: 11,
fontWeight: '400',
lineHeight: 14,
letterSpacing: 0,
},
};

Combined duration and easing tokens.

export const motion = {
duration: {
instant: 100,
fast: 200,
normal: 300,
slow: 500,
slower: 700,
slowest: 1000,
},
easing: {
linear: 'linear',
easeIn: 'cubic-bezier(0.4, 0, 1, 1)',
easeOut: 'cubic-bezier(0, 0, 0.2, 1)',
easeInOut: 'cubic-bezier(0.4, 0, 0.2, 1)',
breath: 'cubic-bezier(0.45, 0, 0.55, 1)',
},
breathing: {
inhale: 3600,
hold: 1200,
exhale: 4800,
total: 9600,
},
};

Physics-based animation configs for React Native Reanimated.

export const springMotion = {
gentle: { damping: 20, stiffness: 100, mass: 1 },
bouncy: { damping: 10, stiffness: 150, mass: 0.8 },
stiff: { damping: 30, stiffness: 300, mass: 0.5 },
slow: { damping: 25, stiffness: 80, mass: 1.2 },
};
export const radius = {
none: 0,
sm: 4,
md: 8,
lg: 12,
xl: 16,
'2xl': 24,
full: 9999,
};
export const zIndex = {
behind: -1,
base: 0,
raised: 10,
dropdown: 100,
sticky: 200,
overlay: 300,
modal: 400,
toast: 500,
tooltip: 600,
};

The recommended approach for components:

import { createTheme } from '@synchronicity/tokens';
const theme = createTheme('dark');
function MyComponent() {
return (
<View style={{
backgroundColor: theme.colors.background,
padding: theme.spacing.md,
}}>
<Text style={{
color: theme.colors['text-primary'],
...theme.typography.body,
}}>
Hello
</Text>
</View>
);
}

For app-wide theming:

import { ThemeProvider, useTheme } from '@synchronicity/react-native';
// App root
function App() {
return (
<ThemeProvider initialTheme="dark">
<MyApp />
</ThemeProvider>
);
}
// In any component
function MyComponent() {
const { colors, spacing, typography } = useTheme();
return (
<View style={{
backgroundColor: colors.background,
padding: spacing.md,
}}>
<Text style={{
color: colors['text-primary'],
...typography.body,
}}>
Themed content
</Text>
</View>
);
}

When you need semantic tokens without the full theme:

import * as semantic from '@synchronicity/tokens/semantic';
const darkBg = semantic.colors.dark.background;
const lightBg = semantic.colors.light.background;
const space = semantic.spacing.md;