Estilos (NativeWind)

Estilamos con NativeWind v4 — clases utilitarias de Tailwind vía className. StyleSheet.create quedó retirado; usá style inline solo para valores que únicamente podés calcular en runtime (matemática de safe-area, un fill de SVG, un valor animado).

import { View, Text } from "react-native";

export function Badge({ label }: { label: string }) {
  return (
    <View className="rounded-full bg-primary px-3 py-1">
      <Text className="text-sm font-medium text-white">{label}</Text>
    </View>
  );
}

Los design tokens son la única fuente de verdad

Colores, spacing, tamaños de fuente, etc. viven en un único tokens.ts. La config de Tailwind los consume, y los consumidores que solo usan JS (un fill de SVG, un color de ActivityIndicator) importan el mismo archivo — así hay exactamente un lugar para cambiar un color.

// tailwind.config.js
const { tokens } = require("./src/shared/constants/tokens");

module.exports = {
  content: ["./app/**/*.{ts,tsx}", "./src/**/*.{ts,tsx}"],
  presets: [require("nativewind/preset")],
  theme: {
    extend: { colors: tokens.colors, spacing: tokens.spacing },
  },
};

El helper cn()

Combiná clases condicionales y que se sobreescriben con clsx + tailwind-merge:

// src/shared/constants/cn.ts
import clsx, { type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export const cn = (...inputs: ClassValue[]) => twMerge(clsx(inputs));
<View className={cn("p-4", isActive && "bg-primary", className)} />

Agregá prettier-plugin-tailwindcss para que las clases queden siempre ordenadas de la misma forma.

Advertencia

Las utilidades de animación (transition-*, animate-*) dependen de que Reanimated esté linkeado. Si tu proyecto no linkea Reanimated, estas clases explotan en runtime. O no las uses — manejá la animación desde JavaScript — o agregá Reanimated a propósito y confirmá que está linkeado antes de depender de ellas.