| name | expo-theme |
| description | Patrones de estilos: theme tokens, StyleSheet.create, colores, spacing. Trigger: Cuando se estilizan componentes, se usan tokens de tema, o se crean StyleSheets.
|
| license | MIT |
| metadata | {"author":"myquota","version":"1.0","auto_invoke":["Styling components","Using theme tokens","Creating StyleSheets"]} |
Propósito
Mantener estilos consistentes usando theme tokens y StyleSheet.create().
Theme Tokens
Ubicación: src/shared/theme/tokens.ts
export const colors = {
primary: "#007BFF",
danger: "#DC3545",
success: "#28A745",
warning: "#FFC107",
bgLight: "#F8F9FA",
textPrimary: "#212529",
textSecondary: "#495057",
textMuted: "#868E96",
white: "#FFFFFF",
border: "#DEE2E6",
} as const;
export const spacing = {
xs: 4,
sm: 8,
md: 16,
lg: 24,
xl: 32,
} as const;
export const fontSizes = {
xs: 11,
sm: 13,
md: 15,
lg: 18,
xl: 22,
xxl: 28,
} as const;
export const borderRadius = {
sm: 4,
md: 8,
lg: 12,
full: 9999,
} as const;
Importar Tokens
import { colors, spacing, fontSizes } from "@/shared/theme/tokens";
NUNCA hardcodear colores:
backgroundColor: "#007BFF",
backgroundColor: colors.primary,
StyleSheet Pattern
import React from "react";
import { View, Text, StyleSheet } from "react-native";
import { colors, spacing, fontSizes } from "@/shared/theme/tokens";
export default function MyComponent() {
return (
<View style={styles.container}>
<Text style={styles.title}>Título</Text>
<Text style={styles.subtitle}>Subtítulo</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: colors.bgLight,
padding: spacing.md,
},
title: {
fontSize: fontSizes.xl,
fontWeight: "700",
color: colors.textPrimary,
marginBottom: spacing.sm,
},
subtitle: {
fontSize: fontSizes.md,
color: colors.textSecondary,
},
});
Patrones Comunes
Container Centrado
centered: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
Card
card: {
backgroundColor: colors.white,
borderRadius: borderRadius.md,
padding: spacing.md,
marginBottom: spacing.sm,
shadowColor: "#000",
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.1,
shadowRadius: 2,
elevation: 2,
},
Row con Space Between
row: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
},
Separator
separator: {
height: 1,
backgroundColor: colors.border,
marginVertical: spacing.sm,
},
Button Primario
button: {
backgroundColor: colors.primary,
paddingVertical: spacing.sm,
paddingHorizontal: spacing.lg,
borderRadius: borderRadius.md,
alignItems: "center",
},
buttonText: {
color: colors.white,
fontSize: fontSizes.md,
fontWeight: "600",
},
buttonDisabled: {
backgroundColor: colors.textMuted,
},
Input
input: {
backgroundColor: colors.white,
borderWidth: 1,
borderColor: colors.border,
borderRadius: borderRadius.md,
paddingVertical: spacing.sm,
paddingHorizontal: spacing.md,
fontSize: fontSizes.md,
color: colors.textPrimary,
},
inputFocused: {
borderColor: colors.primary,
},
Estilos Condicionales
<View style={[styles.button, disabled && styles.buttonDisabled]}>
<Text style={styles.buttonText}>Guardar</Text>
</View>
<Text style={[styles.text, isError && { color: colors.danger }]}>
{message}
</Text>
Estilos Dinámicos
Si el estilo depende de props, usar función:
const getDynamicStyle = (color: string) => ({
backgroundColor: color,
padding: spacing.md,
});
<View style={getDynamicStyle(card.color)} />
Inline Styles
Solo usar para valores dinámicos que no pueden ir en StyleSheet:
<View style={{ backgroundColor: card.color }} />
<View style={{ padding: 16, backgroundColor: "#007BFF" }} />
Extender Tokens
Si necesitas un color no definido, agrégalo a tokens:
export const colors = {
newColor: "#6C757D",
} as const;
NUNCA hardcodear colores nuevos en componentes.
Anti-patterns
backgroundColor: "#007BFF",
padding: 16,
<View style={{ flex: 1, padding: 16, backgroundColor: "#fff" }} />
const styles = StyleSheet.create({...});
export default function Component() {...}
import { colors } from "../../shared/theme/tokens";
Regla: Dónde Van los Componentes
| Tipo | Ubicación |
|---|
| Componente de un solo feature | features/<feature>/components/ |
| Componente UI reutilizable (Button, Card, Input) | shared/components/ |
Checklist