Component Architecture
Component Architecture
Section titled “Component Architecture”Overview
Section titled “Overview”Shaker’s component architecture follows React best practices with a focus on reusability, type safety, and the RetroUI design system. Components are organized by function and use NativeWind for styling with design tokens.
Component Organization
Section titled “Component Organization”Directory Structure
Section titled “Directory Structure”components/├── BarcodeScanner.tsx # Camera-based barcode scanner├── BatchScanQueue.tsx # Batch scan queue management├── BudgetAlerts.tsx # Budget threshold alerts├── CostAnalytics.tsx # Cost analytics display├── ErrorBoundary.tsx # Error boundary wrapper├── ErrorState.tsx # Error state display├── EventCard.tsx # Event display card├── EventForm.tsx # Event create/edit form├── EventHosts.tsx # Event hosts management├── EventList.tsx # Event list display├── FlavorProfileChart.tsx # Flavor radar chart├── FlavorProfileEditor.tsx # Interactive flavor profile editor├── GuestCard.tsx # Guest display card├── IngredientMappingSuggestions.tsx # Ingredient mapping suggestions├── IngredientPicker.tsx # Single ingredient selector├── IngredientSelector.tsx # Multi-ingredient selector├── IngredientSubstitutionSuggestions.tsx # Ingredient substitution suggestions├── Input.tsx # Text input├── LoadingScreen.tsx # Full-screen loading state├── Modal.tsx # Modal dialog├── PriceHistoryChart.tsx # Price history chart├── ProductLevelIndicator.tsx # Product inventory level display├── ProductScannerDemo.tsx # Barcode scanner demo├── ProductSelectionModal.tsx # Product picker modal├── QuickUpdateModal.tsx # Quick inventory update modal├── ReplyMessageBar.tsx # Message reply bar├── RestockModal.tsx # Restock quantity modal├── RootComponent.tsx # App root wrapper├── Screen.tsx # Full-screen wrapper├── SquareButton.tsx # Square action button├── StatCard.tsx # Dashboard stat card├── StyledImage.tsx # Styled Expo image wrapper (exported as StyledExpoImage)├── SubstitutionSuggestions.tsx # Product substitution suggestions├── TagSelector.tsx # Tag selection input├── TextInput.tsx # Enhanced text input├── Toast.tsx # Toast notifications (Toast + ToastContainer)├── batch/ # Batch recipe components│ ├── BatchIngredientList.tsx # Scaled ingredient list display│ ├── BatchScalingCalculator.tsx # Serving size calculator│ └── BatchServingTracker.tsx # Batch serving tracker├── icons/ # Icon configuration│ └── FontAwesomeSetup.tsx # FontAwesome Pro library setup├── ingredients/ # Ingredient-specific components│ └── IngredientFilters.tsx # Ingredient filtering controls├── navigation/ # Navigation components│ └── HeaderButton.tsx # Header buttons (BaseHeaderButton, HeaderBackButton, HeaderActionButton, headerButtonConfig)├── products/ # Product-specific components│ ├── ProductFilters.tsx # Product filtering controls│ ├── ProductInstanceCard.tsx # Product instance display card│ ├── ProductInstanceList.tsx # Product instance list│ ├── QuantityControl.tsx # Quantity increment/decrement control│ └── TrackingModeBadge.tsx # Tracking mode indicator badge├── recipes/ # Recipe-specific components│ ├── RecipeCard.tsx # Recipe display card│ └── RecipeFilters.tsx # Recipe filtering controls├── skeletons/ # Loading skeleton components│ └── ProductCardSkeleton.tsx # Product card + list skeleton loaders└── tags/ # Tag components ├── TagBadge.tsx # Tag badge display ├── TagFilter.tsx # Tag filter input ├── TagList.tsx # Tag list display └── TagPicker.tsx # Tag picker modalDesign System Components (from dry_ui)
Section titled “Design System Components (from dry_ui)”The following components are sourced from the dry_ui design system library and re-exported via components/index.ts. They are not local files:
| Component | Description |
|---|---|
Alert | Alert banner |
Badge | Label/tag |
Button | Primary action button |
Card | Card container |
DateTimePicker | Date/time picker |
EmptyState | Empty list state |
Icon | FontAwesome icon wrapper |
Image | Styled Expo image |
Picker | Dropdown picker |
ScreenHeading | Screen title |
SegmentedControl | Segmented control |
Slider | Range slider |
SwipeableRow | Swipeable list item |
Text | Styled text |
TouchableOpacity | Styled touchable |
VerticalSpacer | Vertical spacing utility |
View | Styled view |
Core Components
Section titled “Core Components”Screen Component
Section titled “Screen Component”Full-screen wrapper with consistent styling and safe area handling.
Usage:
import { Screen } from '@/components';
export default function MyScreen() { return ( <Screen> <Text>Screen content</Text> </Screen> );}Props:
children: ReactNode- Screen contentclassName?: string- Additional NativeWind classesscrollable?: boolean- Enable ScrollView (default: true)
Card Component
Section titled “Card Component”From dry_ui design system. Re-exported via
@/components.
Container with NeoBrutalism styling (bold border, shadow, padding).
Usage:
import { Card } from '@/components';
<Card> <Text>Card content</Text></Card>Props:
children: ReactNode- Card contentclassName?: string- Additional classesonPress?: () => void- Make card pressable
Button Component
Section titled “Button Component”From dry_ui design system. Re-exported via
@/components.
Primary action button with NeoBrutalism styling.
Usage:
import { Button } from '@/components';
<Button title="Add Recipe" onPress={handlePress} variant="primary"/>Props:
title: string- Button textonPress: () => void- Press handlervariant?: 'primary' | 'secondary' | 'danger'- Style variantdisabled?: boolean- Disabled stateloading?: boolean- Loading state
SquareButton Component
Section titled “SquareButton Component”Square action button for dashboard quick actions.
Usage:
import { SquareButton } from '@/components';
<SquareButton icon="plus" label="Add Recipe" onPress={handlePress} color="primary"/>Props:
icon: IconName- FontAwesome icon namelabel: string- Button labelonPress: () => void- Press handlercolor?: ColorToken- Background color from design tokens
Icon Component
Section titled “Icon Component”From dry_ui design system. Re-exported via
@/components.
FontAwesome icon wrapper with design system integration.
Usage:
import { Icon } from '@/components';
<Icon name="whiskey-glass" size="iconLg" color="primary"/>Props:
name: IconName- FontAwesome icon namesize?: IconSize- Size from design tokenscolor?: ColorToken- Color from design tokens
Icon Sizes:
iconXs: 12pxiconSm: 16pxiconMd: 20px (default)iconLg: 24pxiconXl: 32pxicon2xl: 48pxiconBar: 24px (tab bar icons)
Domain-Specific Components
Section titled “Domain-Specific Components”BarcodeScanner
Section titled “BarcodeScanner”Camera-based barcode scanner for UPC lookup.
Usage:
import { BarcodeScanner } from '@/components';
<BarcodeScanner onScan={handleBarcodeScan} onClose={handleClose}/>Props:
onScan: (barcode: string) => void- Scan callbackonClose: () => void- Close callbackisVisible: boolean- Visibility state
Features:
- Camera permission handling
- Barcode format detection
- Visual scan feedback
- Error handling
ProductLevelIndicator
Section titled “ProductLevelIndicator”Visual indicator for product inventory level.
Usage:
import { ProductLevelIndicator } from '@/components';
<ProductLevelIndicator level={75} size="md" variant="horizontal"/>Props:
level: number- Percentage (0-100)size?: 'sm' | 'md' | 'lg'- Display sizevariant?: 'horizontal' | 'vertical'- OrientationshowLabel?: boolean- Show percentage label
Color Coding:
- 75-100%: Green (good stock)
- 25-74%: Yellow (medium stock)
- 0-24%: Red (low stock)
FlavorProfileChart
Section titled “FlavorProfileChart”Radar/spider chart displaying an ingredient’s 8-dimension flavor profile.
Usage:
import { FlavorProfileChart } from '@/components';
<FlavorProfileChart profile={{ sweet: 7, sour: 3, bitter: 2, umami: 1, spicy: 0, herbal: 4, floral: 2, fruity: 6 }} title="Flavor Profile" size="medium" showLabels showValues/>Props:
profile: IngredientProfile- 8-dimensional flavor datatitle?: string- Chart title (default:"Flavor Profile")size?: 'small' | 'medium' | 'large'- Chart size (default:'medium')showLabels?: boolean- Show flavor axis labels (default: true)showValues?: boolean- Show values on tap (default: true)className?: string- Additional NativeWind classes
FlavorProfileEditor
Section titled “FlavorProfileEditor”Interactive editor for flavor profiles.
Usage:
import { FlavorProfileEditor } from '@/components';
<FlavorProfileEditor profile={currentProfile} onChange={handleProfileChange}/>Props:
profile: IngredientProfile- Current profileonChange: (profile: IngredientProfile) => void- Change callback
Features:
- Slider controls for each dimension (0-10)
- Real-time preview
- Validation
- Reset functionality
Component Patterns
Section titled “Component Patterns”Composition Pattern
Section titled “Composition Pattern”Components use composition for flexibility:
<Card> <Card.Header> <Text>Title</Text> </Card.Header> <Card.Content> <Text>Content</Text> </Card.Content> <Card.Footer> <Button title="Action" /> </Card.Footer></Card>Render Props Pattern
Section titled “Render Props Pattern”For flexible rendering:
<List data={items} renderItem={({ item }) => ( <Card> <Text>{item.name}</Text> </Card> )}/>Controlled Components
Section titled “Controlled Components”Form inputs are controlled:
const [value, setValue] = useState('');
<Input value={value} onChangeText={setValue} placeholder="Enter name"/>Styling with NativeWind
Section titled “Styling with NativeWind”Design Tokens
Section titled “Design Tokens”Components use design tokens for consistency:
import { designTokens } from '@/styles/designTokens';
<View style={{ backgroundColor: designTokens.colors.teal.DEFAULT, borderWidth: designTokens.borders.thick, borderColor: designTokens.colors.black, padding: designTokens.spacing.md,}} />NativeWind Classes
Section titled “NativeWind Classes”Prefer NativeWind classes for styling:
<View className="bg-teal border-3 border-black p-4 rounded-lg shadow-retro-md"> <Text className="text-xl font-bold text-black"> Title </Text></View>Tailwind Variants
Section titled “Tailwind Variants”Use tailwind-variants for component variants:
import { tv } from 'tailwind-variants';
const buttonStyles = tv({ base: 'px-4 py-2 rounded-lg border-3 border-black', variants: { color: { primary: 'bg-primary', secondary: 'bg-secondary', danger: 'bg-error', }, },});Last Modified
Section titled “Last Modified”2026-03-06