User Interface and Design - PlugImt/transat-app GitHub Wiki
Transat 2.0 features a modern, accessible, and responsive design system built with NativeWind (Tailwind CSS for React Native) and custom components.
The app supports both light and dark themes with automatic system preference detection.
- Brand Colors: Campus-inspired color scheme
- Accent Colors: Interactive elements and highlights
- Semantic Colors: Success, warning, error, and info states
- Neutral Colors: Text, backgrounds, and borders
- Headings: Multiple sizes for hierarchical content
- Body Text: Readable sizes for content
- Captions: Secondary information
- Interactive: Buttons and links
// src/themes/useThemeProvider.ts
export const useTheme = () => {
// Theme context hook providing:
// - Current theme (light/dark)
// - Theme switching functionality
// - Color tokens
// - Typography scales
}
Base layout wrapper for all screens with consistent padding and safe area handling.
import Page from "@/components/common/Page";
<Page>
{/* Screen content */}
</Page>
Versatile button component with multiple variants and states.
import { Button } from "@/components/common/Button";
<Button
variant="primary"
size="medium"
onPress={handlePress}
>
Button Text
</Button>
Custom bottom tab navigation with icons and labels.
Screen-to-screen navigation with customizable headers.
Customizable dashboard widgets for the home screen:
-
Weather Widget (
WeatherWidget
)- Current weather conditions
- Location-based forecasts
- Loading skeleton (
WeatherSkeleton
)
-
Restaurant Widget (
RestaurantWidget
)- Daily menu display
- Meal times (lunch/dinner)
- Loading state (
RestaurantWidgetLoading
)
-
Washing Machine Widget (
WashingMachineWidget
)- Machine availability status
- Real-time updates
- Loading state (
WashingMachineWidgetLoading
)
Users can reorder and enable/disable widgets through the customization modal:
import WidgetCustomizationModal from "@/components/common/WidgetCustomizationModal";
<WidgetCustomizationModal
visible={showModal}
widgets={availableWidgets}
onSave={handleSave}
onClose={handleClose}
/>
Consistent input styling with validation states:
- Text inputs
- Secure text entry (passwords)
- Multi-line text areas
- Picker components
Integration with React Hook Form and Zod for type-safe validation:
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({
email: z.string().email(),
password: z.string().min(8)
});
const { control, handleSubmit } = useForm({
resolver: zodResolver(schema)
});
Multiple loading patterns:
- Skeleton Loaders: Content placeholders
- Spinners: Activity indicators
- Progress Bars: Task progress
- Toast messages
- Modal dialogs
- Inline alerts
Custom animations for enhanced user experience:
- Loading animations
- Success/error states
- Onboarding sequences
Smooth transitions and interactions:
- Gesture handling
- Layout animations
- Custom transitions
- Adaptive layouts for different screen sizes
- Flexible typography scaling
- Touch-friendly interaction targets
- Screen reader support
- Semantic markup
- Keyboard navigation
- Color contrast compliance
- Lazy loading components
- Image optimization
- Efficient re-renders with React.memo
- Virtualized lists for large datasets
Tailwind CSS classes adapted for React Native:
import { View, Text } from "react-native";
export const ExampleComponent = () => (
<View className="flex-1 bg-white dark:bg-gray-900 p-4">
<Text className="text-lg font-semibold text-gray-800 dark:text-white">
Styled with NativeWind
</Text>
</View>
);
Helper functions for consistent styling:
// Utility classes for common patterns
const cardStyles = "bg-white dark:bg-gray-800 rounded-lg p-4 shadow-sm";
const buttonStyles = "px-6 py-3 rounded-md font-medium";
Centralized design values:
- Spacing scale (4px base)
- Border radius values
- Shadow definitions
- Animation durations
export const Card = ({ children, className, ...props }) => (
<View
className={cn(
"bg-white dark:bg-gray-800 rounded-lg p-4 shadow-sm border border-gray-200 dark:border-gray-700",
className
)}
{...props}
>
{children}
</View>
);
export const Input = ({ label, error, ...props }) => (
<View className="space-y-2">
{label && (
<Text className="text-sm font-medium text-gray-700 dark:text-gray-300">
{label}
</Text>
)}
<TextInput
className={cn(
"border border-gray-300 dark:border-gray-600 rounded-md px-3 py-2",
"bg-white dark:bg-gray-800 text-gray-900 dark:text-white",
error && "border-red-500"
)}
{...props}
/>
{error && (
<Text className="text-sm text-red-500">{error}</Text>
)}
</View>
);
// tailwind.config.js
module.exports = {
content: ["./src/**/*.{js,jsx,ts,tsx}"],
presets: [require("nativewind/preset")],
theme: {
extend: {
colors: {
primary: {
50: "#f0f9ff",
500: "#3b82f6",
900: "#1e3a8a"
}
},
fontFamily: {
sans: ["Inter", "system-ui"],
mono: ["JetBrains Mono", "monospace"]
}
}
},
plugins: []
};
/* src/app/global.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
* {
@apply border-border;
}
body {
@apply bg-background text-foreground;
}
}
- Native-feeling navigation
- Platform-appropriate icons
- iOS-specific styling patterns
- Material Design 3 components
- Android-specific behaviors
- Platform UI conventions
- Shared component logic
- Platform-specific styling
- Consistent user experience
- Lucide React Native: Primary icon library
- Expo Vector Icons: Additional platform icons
- Custom SVG icons for brand elements
- System fonts for optimal performance
- Custom fonts for brand identity
- Proper font loading and fallbacks
- Optimized image formats
- Responsive image loading
- Placeholder and error states
Next Steps: Learn about the app's navigation system in Navigation & Routing documentation.