Mobile Tokens
Token mapping for React Native / NativeWind mobile applications (stock-app-mobile, customer-app, buyer-app).
NativeWind / Tailwind Config
The mobile apps use NativeWind (Tailwind CSS for React Native). Add these to tailwind.config.js:
js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./app/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
],
presets: [require('nativewind/preset')],
theme: {
extend: {
colors: {
brand: {
DEFAULT: '#2D6B4A',
hover: '#245A3E',
light: '#E8F0EC',
subtle: '#F0F5F2',
},
success: '#2D7D46',
warning: '#D4910A',
danger: {
DEFAULT: '#C4463A',
light: '#FCEAE8',
},
info: '#2563EB',
surface: {
body: '#FAFAF7',
card: '#FFFFFF',
inset: '#F3F1EC',
hover: '#EDEAE3',
},
border: {
DEFAULT: '#E5E2DB',
strong: '#D4D0C8',
},
text: {
1: '#1A1816',
2: '#57534E',
3: '#A8A29E',
},
},
fontFamily: {
sans: ['PlusJakartaSans-Regular'],
'sans-medium': ['PlusJakartaSans-Medium'],
'sans-semibold': ['PlusJakartaSans-SemiBold'],
'sans-bold': ['PlusJakartaSans-Bold'],
display: ['Lora-Regular'],
'display-italic': ['Lora-Italic'],
mono: ['JetBrainsMono-Regular'],
'mono-medium': ['JetBrainsMono-Medium'],
'mono-semibold': ['JetBrainsMono-SemiBold'],
'mono-bold': ['JetBrainsMono-Bold'],
},
borderRadius: {
sm: 4,
md: 8,
lg: 12,
xl: 16,
'2xl': 20,
},
},
},
plugins: [],
}StyleSheet Constants
For cases where NativeWind is not used (e.g., animated components, third-party library styling):
ts
import { StyleSheet, Platform } from 'react-native'
export const BumiColors = {
brand: '#2D6B4A',
brandHover: '#245A3E',
brandLight: '#E8F0EC',
success: '#2D7D46',
warning: '#D4910A',
danger: '#C4463A',
dangerLight: '#FCEAE8',
info: '#2563EB',
bgBody: '#FAFAF7',
bgCard: '#FFFFFF',
bgInset: '#F3F1EC',
bgHover: '#EDEAE3',
border: '#E5E2DB',
borderStrong: '#D4D0C8',
text1: '#1A1816',
text2: '#57534E',
text3: '#A8A29E',
} as const
export const BumiSpacing = {
xs: 4,
sm: 8,
md: 12,
base: 16,
lg: 20,
xl: 24,
'2xl': 32,
'3xl': 40,
'4xl': 48,
} as const
export const BumiRadius = {
sm: 4,
md: 8,
lg: 12,
xl: 16,
'2xl': 20,
full: 9999,
} as const
export const BumiTypography = StyleSheet.create({
heading1: {
fontFamily: 'Lora-Regular',
fontSize: 28,
lineHeight: 34,
color: BumiColors.text1,
},
heading2: {
fontFamily: 'PlusJakartaSans-Bold',
fontSize: 20,
lineHeight: 28,
color: BumiColors.text1,
},
heading3: {
fontFamily: 'PlusJakartaSans-SemiBold',
fontSize: 16,
lineHeight: 24,
color: BumiColors.text1,
},
body: {
fontFamily: 'PlusJakartaSans-Regular',
fontSize: 14,
lineHeight: 22,
color: BumiColors.text1,
},
bodySmall: {
fontFamily: 'PlusJakartaSans-Regular',
fontSize: 13,
lineHeight: 20,
color: BumiColors.text2,
},
label: {
fontFamily: 'PlusJakartaSans-SemiBold',
fontSize: 11,
lineHeight: 16,
letterSpacing: 0.5,
textTransform: 'uppercase',
color: BumiColors.text2,
},
mono: {
fontFamily: 'JetBrainsMono-Regular',
fontSize: 13,
lineHeight: 20,
color: BumiColors.text1,
},
monoBold: {
fontFamily: 'JetBrainsMono-SemiBold',
fontSize: 13,
lineHeight: 20,
color: BumiColors.text1,
},
})
export const BumiShadows = Platform.select({
ios: {
sm: { shadowColor: '#1C1A14', shadowOffset: { width: 0, height: 1 }, shadowOpacity: 0.06, shadowRadius: 3 },
md: { shadowColor: '#1C1A14', shadowOffset: { width: 0, height: 4 }, shadowOpacity: 0.06, shadowRadius: 6 },
lg: { shadowColor: '#1C1A14', shadowOffset: { width: 0, height: 10 }, shadowOpacity: 0.06, shadowRadius: 15 },
},
android: {
sm: { elevation: 2 },
md: { elevation: 4 },
lg: { elevation: 8 },
},
})Expo-Specific Values
ts
import { Platform, StatusBar } from 'react-native'
import Constants from 'expo-constants'
export const BumiLayout = {
/** Safe area top inset (notch + status bar) */
safeAreaTop: Constants.statusBarHeight ?? 0,
/** Bottom tab bar height including safe area */
tabBarHeight: Platform.select({ ios: 83, android: 64 }) ?? 64,
/** Standard header height */
headerHeight: 56,
/** Bottom sheet handle area height */
sheetHandleHeight: 32,
/** Minimum touch target (WCAG) */
minTouchTarget: 44,
/** Screen horizontal padding */
screenPadding: 16,
/** Card content padding */
cardPadding: 16,
/** Status bar style */
statusBarStyle: 'dark-content' as const,
} as constFont Loading (Expo)
ts
import { useFonts } from 'expo-font'
export function useLoadFonts() {
const [loaded] = useFonts({
'PlusJakartaSans-Regular': require('../assets/fonts/PlusJakartaSans-Regular.ttf'),
'PlusJakartaSans-Medium': require('../assets/fonts/PlusJakartaSans-Medium.ttf'),
'PlusJakartaSans-SemiBold': require('../assets/fonts/PlusJakartaSans-SemiBold.ttf'),
'PlusJakartaSans-Bold': require('../assets/fonts/PlusJakartaSans-Bold.ttf'),
'PlusJakartaSans-ExtraBold': require('../assets/fonts/PlusJakartaSans-ExtraBold.ttf'),
'Lora-Regular': require('../assets/fonts/Lora-Regular.ttf'),
'Lora-Italic': require('../assets/fonts/Lora-Italic.ttf'),
'JetBrainsMono-Regular': require('../assets/fonts/JetBrainsMono-Regular.ttf'),
'JetBrainsMono-Medium': require('../assets/fonts/JetBrainsMono-Medium.ttf'),
'JetBrainsMono-SemiBold': require('../assets/fonts/JetBrainsMono-SemiBold.ttf'),
'JetBrainsMono-Bold': require('../assets/fonts/JetBrainsMono-Bold.ttf'),
})
return loaded
}Font files
Font files should be placed in assets/fonts/ at the app root. Download from Google Fonts and include the specific weights listed above.
React Native specifics
- React Native does not support CSS
font-weightnatively --- use separate font family names for each weight letterSpacingin React Native uses absolute pixels, notemunitstextTransformis supported but may behave differently on Android