🧩 Components Guide
Componentes Disponibles
1. Button
Botón versátil con múltiples variantes y estados.
import { Button } from '@/components/Button';
// Variantes disponibles
<Button title="Primary" variant="primary" onPress={handlePress} />
<Button title="Secondary" variant="secondary" onPress={handlePress} />
<Button title="Outline" variant="outline" onPress={handlePress} />
<Button title="Ghost" variant="ghost" onPress={handlePress} />
<Button title="Gradient" variant="gradient" onPress={handlePress} />
// Tamaños
<Button title="Small" size="small" />
<Button title="Medium" size="medium" />
<Button title="Large" size="large" />
// Con icono
<Button
title="Add"
icon={<Plus size={18} color={Colors.textInverse} />}
onPress={handlePress}
/>
// Estado de carga
<Button title="Loading" loading={true} />
// Deshabilitado
<Button title="Disabled" disabled={true} />
Props:
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| title | string | required | Texto del botón |
| onPress | () => void | - | Handler de click |
| variant | 'primary' | 'secondary' | 'outline' | 'ghost' | 'gradient' | 'primary' | Estilo visual |
| size | 'small' | 'medium' | 'large' | 'medium' | Tamaño |
| loading | boolean | false | Estado de carga |
| disabled | boolean | false | Deshabilitar |
| icon | ReactNode | - | Icono a mostrar |
2. Card
Tarjeta para mostrar items con imagen, título y detalles.
import { Card } from '@/components/Card';
// Card default
<Card
item={item}
onPress={() => handleItemPress(item.id)}
onFavorite={() => toggleFavorite(item.id)}
isFavorite={isFavorite(item.id)}
/>
// Card horizontal (para listas)
<Card
item={item}
variant="horizontal"
onPress={handlePress}
/>
// Card compacta (para carruseles)
<Card
item={item}
variant="compact"
onPress={handlePress}
/>
Props:
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| item | Item | required | Datos del item |
| onPress | () => void | - | Handler de click |
| onFavorite | () => void | - | Handler de favorito |
| isFavorite | boolean | false | Estado de favorito |
| variant | 'default' | 'compact' | 'horizontal' | 'default' | Variante visual |
3. Input
Campo de entrada con validación y estados.
import { Input } from '@/components/Input';
// Input básico
<Input
label="Email"
value={email}
onChangeText={setEmail}
placeholder="correo@ejemplo.com"
keyboardType="email-address"
/>
// Con validación
<Input
label="Contraseña"
value={password}
onChangeText={setPassword}
secureTextEntry
error={errors.password}
/>
// Con icono
<Input
label="Buscar"
value={search}
onChangeText={setSearch}
leftIcon={<Search size={20} color={Colors.textTertiary} />}
/>
// Textarea
<Input
label="Descripción"
value={description}
onChangeText={setDescription}
multiline
numberOfLines={4}
/>
Props:
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| label | string | - | Etiqueta del campo |
| value | string | required | Valor actual |
| onChangeText | (text: string) => void | required | Handler de cambio |
| placeholder | string | - | Placeholder |
| error | string | - | Mensaje de error |
| leftIcon | ReactNode | - | Icono izquierdo |
| rightIcon | ReactNode | - | Icono derecho |
| secureTextEntry | boolean | false | Campo de contraseña |
| multiline | boolean | false | Textarea |
4. Avatar
Componente de avatar con imagen o iniciales.
import { Avatar } from '@/components/Avatar';
// Con imagen
<Avatar
source="https://example.com/avatar.jpg"
name="John Doe"
size="large"
/>
// Sin imagen (muestra iniciales)
<Avatar
name="John Doe"
size="medium"
/>
// Tamaños disponibles
<Avatar name="JD" size="small" /> // 32px
<Avatar name="JD" size="medium" /> // 48px
<Avatar name="JD" size="large" /> // 64px
<Avatar name="JD" size="xlarge" /> // 96px
// Con borde de estado
<Avatar
name="JD"
showBorder
borderColor={Colors.success}
/>
5. SkeletonLoader
Placeholder animado para estados de carga.
import { SkeletonLoader } from '@/components/SkeletonLoader';
// Rectángulo
<SkeletonLoader width={200} height={20} />
// Círculo
<SkeletonLoader width={48} height={48} borderRadius={24} />
// Card skeleton
<SkeletonLoader width="100%" height={200} borderRadius={12} />
6. EmptyState
Empty state con mensaje y acción.
import { EmptyState } from '@/components/EmptyState';
<EmptyState
icon="Heart"
title="No hay favoritos"
description="Los items que marques como favoritos aparecerán aquí"
actionTitle="Explorar"
onAction={() => router.push('/explore')}
/>
7. Toast
Notificaciones temporales.
import { useToast } from '@/contexts/ToastContext';
const { showToast } = useToast();
// Tipos de toast
showToast('Operación exitosa', 'success');
showToast('Hubo un error', 'error');
showToast('Advertencia', 'warning');
showToast('Información', 'info');
Creando Nuevos Componentes
Plantilla Base
import React from 'react';
import { View, Text, StyleSheet, ViewStyle } from 'react-native';
import { Colors, Spacing, FontSizes, FontWeights, BorderRadius } from '@/constants/colors';
interface MyComponentProps {
title: string;
subtitle?: string;
style?: ViewStyle;
testID?: string;
}
export function MyComponent({
title,
subtitle,
style,
testID
}: MyComponentProps) {
return (
<View style={[styles.container, style]} testID={testID}>
<Text style={styles.title}>{title}</Text>
{subtitle && <Text style={styles.subtitle}>{subtitle}</Text>}
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: Colors.surface,
padding: Spacing.md,
borderRadius: BorderRadius.md,
},
title: {
fontSize: FontSizes.lg,
fontWeight: FontWeights.semibold,
color: Colors.text,
},
subtitle: {
fontSize: FontSizes.sm,
color: Colors.textSecondary,
marginTop: Spacing.xs,
},
});
Checklist para Nuevos Componentes
- Definir interface de Props con tipos correctos
- Incluir
styleprop para personalización - Incluir
testIDprop para testing - Usar constantes de
colors.tspara estilos - Manejar estados: loading, error, disabled
- Agregar feedback táctil (haptics) si es interactivo
- Documentar props y ejemplos de uso