Styling & Theming
Styling & Theming
Section titled “Styling & Theming”Overview
Section titled “Overview”Shaker uses the RetroUI design system, a NeoBrutalism-inspired design language featuring bold colors, thick borders, and solid shadows. The styling is implemented with NativeWind (Tailwind CSS for React Native) and centralized design tokens.
RetroUI Design System
Section titled “RetroUI Design System”Design Principles
Section titled “Design Principles”NeoBrutalism Aesthetic:
- Bold, high-contrast colors
- Thick black borders (3-6px)
- Solid shadows (no blur)
- Playful, energetic feel
- Accessibility-first approach
Key Characteristics:
- Borders: 2-6px solid black borders on interactive elements
- Shadows: Offset shadows without blur for depth
- Colors: Vibrant, saturated colors with high contrast
- Typography: Bold weights for headings, clear hierarchy
- Spacing: Generous padding and margins
- Animations: Snappy, playful transitions (200-300ms)
Color Palette
Section titled “Color Palette”Primary Colors
Section titled “Primary Colors”colors: { primary: '#FFD803', // Bright Yellow secondary: '#FF6B9D', // Pink accent: '#00D9FF', // Cyan teal: '#14B8A6', // Teal (main brand color)}Semantic Colors
Section titled “Semantic Colors”colors: { success: '#10B981', // Green warning: '#F59E0B', // Orange error: '#EF4444', // Red info: '#3B82F6', // Blue}Neutral Colors
Section titled “Neutral Colors”colors: { black: '#000000', white: '#FFFFFF', gray: { 50: '#F9FAFB', 100: '#F3F4F6', 200: '#E5E7EB', 300: '#D1D5DB', 400: '#9CA3AF', 500: '#6B7280', 600: '#4B5563', 700: '#374151', 800: '#1F2937', 900: '#111827', }}Typography
Section titled “Typography”Font Sizes
Section titled “Font Sizes”fontSize: { xs: 12, // Small labels sm: 14, // Body text (small) base: 16, // Body text (default) lg: 18, // Large body text xl: 20, // Small headings '2xl': 24, // Medium headings '3xl': 30, // Large headings '4xl': 36, // Extra large headings '5xl': 48, // Display text}Font Weights
Section titled “Font Weights”fontWeight: { normal: '400', medium: '500', semibold: '600', bold: '700', extrabold: '800', black: '900',}Usage Guidelines:
- Headings:
bold(700) orextrabold(800) - Body text:
normal(400) ormedium(500) - Emphasis:
semibold(600) - Buttons:
bold(700)
Spacing Scale
Section titled “Spacing Scale”Based on 4px base unit:
spacing: { xs: 4, // 4px sm: 8, // 8px md: 16, // 16px (default) lg: 24, // 24px xl: 32, // 32px '2xl': 48, // 48px '3xl': 64, // 64px '4xl': 96, // 96px}Borders
Section titled “Borders”borders: { thin: 2, // 2px - subtle borders medium: 3, // 3px - standard borders thick: 6, // 6px - prominent borders}Usage:
- Cards: 3px border
- Buttons: 3px border
- Headers/Tab bar: 6px border
- Inputs: 2px border
Shadows
Section titled “Shadows”Solid offset shadows (no blur) for NeoBrutalism:
shadows: { xs: { offsetX: 1, offsetY: 1 }, sm: { offsetX: 2, offsetY: 2 }, md: { offsetX: 4, offsetY: 4 }, // Default lg: { offsetX: 6, offsetY: 6 }, xl: { offsetX: 8, offsetY: 8 }, '2xl': { offsetX: 12, offsetY: 12 },}Implementation:
shadowColor: '#000000',shadowOffset: { width: 4, height: 4 },shadowOpacity: 1,shadowRadius: 0, // No blurelevation: 0, // Android: no elevationBorder Radius
Section titled “Border Radius”borderRadius: { none: 0, sm: 4, md: 8, // Default lg: 12, xl: 16, '2xl': 24, full: 9999, // Circular}Design Tokens
Section titled “Design Tokens”Runtime Tokens (designTokens.ts)
Section titled “Runtime Tokens (designTokens.ts)”Centralized design tokens for runtime use:
import { designTokens } from '@/styles/designTokens';
// ColorsdesignTokens.colors.primarydesignTokens.colors.teal.DEFAULTdesignTokens.colors.gray[500]
// TypographydesignTokens.typography.fontSize.xldesignTokens.typography.fontWeight.bold
// SpacingdesignTokens.spacing.mddesignTokens.spacing.xl
// BordersdesignTokens.borders.thick
// ShadowsdesignTokens.shadows.mdTailwind Theme (theme.js)
Section titled “Tailwind Theme (theme.js)”Theme configuration for NativeWind:
module.exports = { theme: { extend: { colors: require('./styles/theme/colors'), spacing: require('./styles/theme/extend/spacing'), fontSize: require('./styles/theme/extend/typography').fontSize, // ... } }}NativeWind Usage
Section titled “NativeWind Usage”Basic Styling
Section titled “Basic Styling”import { View, Text } from 'react-native';
<View className="bg-teal p-4 rounded-lg border-3 border-black shadow-retro-md"> <Text className="text-xl font-bold text-black"> Hello RetroUI </Text></View>Responsive Design
Section titled “Responsive Design”<View className="p-4 sm:p-6 md:p-8"> <Text className="text-base md:text-lg lg:text-xl"> Responsive text </Text></View>Conditional Styling
Section titled “Conditional Styling”<View className={`p-4 ${isActive ? 'bg-primary' : 'bg-gray-200'}`}> <Text>Conditional styling</Text></View>Dark Mode Support
Section titled “Dark Mode Support”<View className="bg-white dark:bg-gray-900"> <Text className="text-black dark:text-white"> Adapts to color scheme </Text></View>Component Styling Patterns
Section titled “Component Styling Patterns”Card Component
Section titled “Card Component”<View className="bg-white border-3 border-black rounded-lg shadow-retro-md p-4"> <Text className="text-xl font-bold mb-2">Card Title</Text> <Text className="text-base">Card content</Text></View>Style Breakdown:
bg-white: White backgroundborder-3: 3px borderborder-black: Black border colorrounded-lg: 12px border radiusshadow-retro-md: 4px offset shadowp-4: 16px padding
Button Component
Section titled “Button Component”<TouchableOpacity className="bg-primary border-3 border-black rounded-lg px-6 py-3 shadow-retro-sm active:shadow-none active:translate-x-1 active:translate-y-1"> <Text className="text-base font-bold text-black text-center"> Press Me </Text></TouchableOpacity>Press Effect:
active:shadow-none: Remove shadow on pressactive:translate-x-1 active:translate-y-1: Move button to simulate depth
Input Component
Section titled “Input Component”<TextInput className="bg-white border-2 border-black rounded-md px-4 py-3 text-base focus:border-primary" placeholder="Enter text" placeholderTextColor="#9CA3AF"/>Utility Functions
Section titled “Utility Functions”RetroUI Utilities (utils/retroUtils.ts)
Section titled “RetroUI Utilities (utils/retroUtils.ts)”Helper functions for creating RetroUI styles:
import { getRetroShadow, createRetroCard } from '@/styles/utils/retroUtils';
// Get shadow styleconst shadowStyle = getRetroShadow('md');// Returns: { shadowColor: '#000', shadowOffset: { width: 4, height: 4 }, ... }
// Create card styleconst cardStyle = createRetroCard('#FFFFFF', 'md', 'lg');// Returns complete card style objectAvailable Utilities:
getRetroShadow(size)- Get shadow stylegetColoredShadow(color, size)- Get colored shadowcreateRetroCard(bg, shadow, radius)- Create card stylecreateRetroButton(bg, shadow)- Create button stylegetSpacing(size)- Get spacing valuegetBorderRadius(size)- Get border radius valuecombineStyles(...styles)- Merge style objectsgetPressStyle()- Get press animation style
Base Styles (baseStyles.ts)
Section titled “Base Styles (baseStyles.ts)”Pre-defined class name utilities:
import { retroCN } from '@/styles/baseStyles';
<View className={retroCN.card}> <Text className={retroCN.heading}>Title</Text></View>Available Classes:
retroCN.card- Card containerretroCN.cardPrimary- Primary colored cardretroCN.button- Button baseretroCN.input- Input baseretroCN.heading- Heading textretroCN.body- Body text
Animations
Section titled “Animations”Animation Keyframes
Section titled “Animation Keyframes”animations: { 'retro-bounce': { '0%, 100%': { transform: 'translateY(0)' }, '50%': { transform: 'translateY(-10px)' }, }, 'retro-press': { '0%': { transform: 'translate(0, 0)' }, '100%': { transform: 'translate(4px, 4px)' }, }, 'retro-shake': { '0%, 100%': { transform: 'translateX(0)' }, '25%': { transform: 'translateX(-10px)' }, '75%': { transform: 'translateX(10px)' }, },}Usage with React Native Animated
Section titled “Usage with React Native Animated”import { Animated } from 'react-native';
const bounceAnim = useRef(new Animated.Value(0)).current;
Animated.spring(bounceAnim, { toValue: 1, friction: 3, tension: 40, useNativeDriver: true,}).start();
<Animated.View style={{ transform: [{ translateY: bounceAnim }] }}> <Text>Bouncing!</Text></Animated.View>Accessibility
Section titled “Accessibility”Color Contrast
Section titled “Color Contrast”All color combinations meet WCAG AA standards:
- Primary on Black: 4.5:1 contrast ratio
- White on Teal: 4.8:1 contrast ratio
- Black on White: 21:1 contrast ratio
Touch Targets
Section titled “Touch Targets”Minimum touch target size: 44pt × 44pt (iOS HIG standard)
<TouchableOpacity className="min-h-[44px] min-w-[44px] items-center justify-center" accessible={true} accessibilityLabel="Add Recipe" accessibilityRole="button"> <Icon name="plus" size="iconLg" /></TouchableOpacity>Screen Reader Support
Section titled “Screen Reader Support”<View accessible={true} accessibilityLabel="Recipe card" accessibilityHint="Double tap to view recipe details"> <Text>Recipe Name</Text></View>Platform-Specific Styling
Section titled “Platform-Specific Styling”iOS vs Android
Section titled “iOS vs Android”import { Platform } from 'react-native';
<View style={{ ...Platform.select({ ios: { shadowColor: '#000', shadowOffset: { width: 4, height: 4 }, shadowOpacity: 1, shadowRadius: 0, }, android: { elevation: 0, // No elevation for flat design }, }),}} />Safe Area Handling
Section titled “Safe Area Handling”import { useSafeAreaInsets } from 'react-native-safe-area-context';
function MyScreen() { const insets = useSafeAreaInsets();
return ( <View style={{ paddingTop: insets.top, paddingBottom: insets.bottom }}> <Text>Content</Text> </View> );}Best Practices
Section titled “Best Practices”1. Use Design Tokens
Section titled “1. Use Design Tokens”✅ Good:
backgroundColor: designTokens.colors.primary❌ Bad:
backgroundColor: '#FFD803'2. Prefer NativeWind Classes
Section titled “2. Prefer NativeWind Classes”✅ Good:
<View className="bg-primary p-4 rounded-lg" />❌ Bad:
<View style={{ backgroundColor: '#FFD803', padding: 16, borderRadius: 12 }} />3. Use Semantic Color Names
Section titled “3. Use Semantic Color Names”✅ Good:
className="bg-success text-white"❌ Bad:
className="bg-green-500 text-white"4. Maintain Consistent Spacing
Section titled “4. Maintain Consistent Spacing”Use the spacing scale consistently:
- Small gaps:
gap-2(8px) - Medium gaps:
gap-4(16px) - Large gaps:
gap-6(24px)
5. Apply Shadows Consistently
Section titled “5. Apply Shadows Consistently”- Cards:
shadow-retro-md - Buttons:
shadow-retro-sm - Modals:
shadow-retro-lg
Customization
Section titled “Customization”Extending the Theme
Section titled “Extending the Theme”To add custom colors or tokens, edit styles/theme/colors.js:
module.exports = { // Existing colors... custom: { DEFAULT: '#YOUR_COLOR', hover: '#HOVER_COLOR', foreground: '#TEXT_COLOR', },};Creating Custom Components
Section titled “Creating Custom Components”Use the utility functions to maintain consistency:
import { createRetroCard, getRetroShadow } from '@/styles/utils/retroUtils';
const customCardStyle = createRetroCard( designTokens.colors.accent, // Background 'lg', // Shadow size 'xl' // Border radius);
<View style={customCardStyle}> <Text>Custom Card</Text></View>Resources
Section titled “Resources”Last Modified
Section titled “Last Modified”2026-01-05