Token system

native-mate uses a semantic token system. Instead of hardcoded colours, you reference tokens like theme.colors.primary — and the correct light/dark value is resolved automatically.

Token shape

Every resolved theme has this structure:

ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
interface ResolvedTheme {
  colors: {
    background: string      // page/screen background
    surface: string         // card, input, overlay bg
    border: string          // dividers, outlines
    foreground: string      // primary text
    mutedForeground: string // secondary text, placeholders
    primary: string         // brand/action colour
    primaryForeground: string
    destructive: string
    destructiveForeground: string
    success: string
    successForeground: string
    warning: string
    warningForeground: string
    overlay: string         // modal scrim
    input: string
    ring: string            // focus ring
    // + more
  }
  spacing: { xs: 4, sm: 8, md: 12, lg: 16, xl: 24, '2xl': 32, '3xl': 48 }
  radius: { sm: 6, md: 10, lg: 16, xl: 24, full: 9999 }
  typography: {
    size: { xs: 11, sm: 13, md: 15, lg: 17, xl: 20, '2xl': 24, '3xl': 30 }
    weight: { regular: '400', medium: '500', semibold: '600', bold: '700' }
    lineHeight: { tight: 18, normal: 22, relaxed: 28 }  // absolute px
  }
  animation: {
    speed: { fast: 150, normal: 250, slow: 400 }         // ms
    easing: { standard, decelerate, spring }
  }
}

useTheme()

Access the current resolved theme directly inside any component wrapped in ThemeProvider.

tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { useTheme } from '@native-mate/core'
import { StyleSheet, View } from 'react-native'

function MyComponent() {
  const theme = useTheme()

  return (
    <View
      style={{
        backgroundColor: theme.colors.surface,
        borderRadius: theme.radius.md,
        padding: theme.spacing.lg,
      }}
    />
  )
}

makeStyles()

The preferred way to define styles. Call it at module level — it returns a hook that calls StyleSheet.create() once per theme change.

tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { makeStyles } from '@native-mate/core'

// Called at module level — returns a hook
const useStyles = makeStyles((theme) => ({
  container: {
    backgroundColor: theme.colors.background,
    padding: theme.spacing.lg,
  },
  title: {
    fontSize: theme.typography.size.lg,
    fontWeight: theme.typography.weight.bold,
    color: theme.colors.foreground,
  },
}))

function MyComponent() {
  const styles = useStyles() // memoised per theme change
  return <View style={styles.container} />
}
Note on lineHeight: Values are absolute pixels (not CSS multipliers).tight: 18, normal: 22, relaxed: 28. React Native requires absolute line heights.