Skip to main content

Tamagui Troubleshooting Guide

Overview

This document captures the issues we encountered with Tamagui and how we solved them. It's a reference for future developers who might run into similar problems.


Issues We Encountered

1. Theme Tokens Not Working ($primary, $secondary, etc.)

Problem:

  • Custom theme tokens like $primary were undefined or not applying
  • Nested token references (primary: "$color6") weren't resolving properly

Root Cause:

  • Tamagui's palette system with createThemes was over-engineered for our needs
  • Nested token references caused resolution issues

Solution:

  • Hardcode the color values directly in the theme instead of using palette references
  • Use direct HSL values: primary: "hsla(239, 84%, 67%, 1)"

Working Config:

themes: {
light: {
...themes.light,
primary: "hsla(239, 84%, 67%, 1)", // Direct value
secondary: "hsla(230, 94%, 82%, 1)", // Direct value
// etc...
}
}

2. Inconsistent Prop Names (bg vs background)

Problem:

  • backgroundColor caused TypeScript errors
  • bg worked in some contexts but not others
  • Inconsistent behavior between Tamagui components

Solution:

  • Always use background (not backgroundColor or bg)
  • This is the canonical Tamagui prop name

Working Example:

<Button background="$primary">Works</Button>
<YStack background="$secondary">Also works</YStack>

3. Custom Button Component Issues

Problem:

  • Custom Button component wasn't properly inheriting Tamagui's theme system
  • Theme tokens weren't available in custom styled components

Solution:

  • Ensure custom components extend Tamagui's base components properly
  • Use styled() with the correct base component

Working Example:

const StyledButton = styled(TamaguiButton, {
name: "Button",
variants: {
link: {
true: {
background: "$primary", // Use theme tokens
color: "$color12",
},
},
},
})

Best Practices (What Actually Works)

1. Theme Configuration

// ✅ DO: Use direct color values
primary: "hsla(239, 84%, 67%, 1)"

// ❌ DON'T: Use nested references
primary: "$color6"

2. Component Props

// ✅ DO: Use canonical Tamagui props
<Button background="$primary" color="$color12">

// ❌ DON'T: Use React Native props
<Button backgroundColor="$primary">

3. Custom Components

// ✅ DO: Extend Tamagui components
const MyButton = styled(TamaguiButton, { ... })

// ❌ DON'T: Create from scratch
const MyButton = styled(View, { ... })

Common Pitfalls

1. Palette System Complexity

  • Tamagui's createThemes with palettes is over-engineered for most apps
  • Stick to simple theme objects with direct color values

2. Token Resolution Issues

  • Nested token references ($primary: "$color6") often don't work
  • Use direct color values instead

3. Prop Name Confusion

  • background is the correct prop (not backgroundColor or bg)
  • Check Tamagui's type definitions for the right prop names

4. Custom Component Inheritance

  • Custom components must properly extend Tamagui base components
  • Don't create components from scratch if you want theme support

Debugging Tips

1. Check Theme Object

const theme = useTheme()
console.log("Theme object:", theme)
console.log("Theme keys:", Object.keys(theme))

2. Test Direct Values

// Test if the component works with direct values
<Button background="#6366f1">Test</Button>

// Then test with theme tokens
<Button background="$primary">Test</Button>

3. Clear Caches

expo start -c

Our Final Working Setup

1. Config Structure

// tamagui.config.ts
const config = {
...defaultConfig,
themes: {
...defaultConfig.themes,
light: {
...themes.light,
primary: "hsla(239, 84%, 67%, 1)",
secondary: "hsla(230, 94%, 82%, 1)",
// ... other semantic colors
},
},
defaultTheme: "light",
}

2. Usage in Components

// ✅ This works
<Button background="$primary" onPress={handlePress}>
<Text color="white">Click me</Text>
</Button>

<YStack background="$background" padding="$4">
<Text color="$color">Content</Text>
</YStack>

Conclusion

Tamagui is powerful but can be frustratingly complex. For most apps, simple is better:

  • Use direct color values in themes
  • Stick to canonical prop names
  • Extend existing Tamagui components
  • Don't over-engineer with palettes unless you really need them

Remember: A working, simple solution is better than a broken, complex one.


References

  • Tamagui Docs
  • [Our Working Config] check../tamagui.config.ts
  • [Our Custom Button] check ../app/components/Button.tsx