UTA DevHub

UI Architecture Overview

Comprehensive guide to UI folder organization, component hierarchy, and integration with the core architecture for consistent frontend development.

UI Architecture Overview

Overview

This document provides a comprehensive guide to our UI architecture, explaining how the ui/ folder integrates with our core architecture to create a scalable, maintainable, and AI-collaboration-friendly component system. It establishes the foundation for consistent UI development across all frontend projects.

Purpose & Scope

This guide helps developers and AI collaborators understand:

  • How UI components fit within our overall architecture
  • The relationship between foundation, patterns, and business components
  • Integration patterns with domains, features, and shared utilities
  • Design token usage and theming strategies
  • Component development workflows for maximum consistency

UI Architecture Philosophy

Design Principles

Our UI architecture follows these core principles:

  1. Separation of Concerns: Clear boundaries between presentation, behavior, and business logic
  2. Atomic Composition: Build complex interfaces from simple, reusable components
  3. Design Token Integration: Consistent theming through centralized design tokens
  4. AI-Friendly Structure: Predictable patterns that enable seamless AI collaboration
  5. Feature Integration: Smooth integration with our feature-based architecture

Three-Layer Architecture (Canonical Definition)

Single Source of Truth: This is the canonical definition of our three-layer UI architecture. All other documents should reference this section rather than duplicating the explanation.

Our UI system is organized into three distinct layers, each with specific responsibilities and clear boundaries. This architecture ensures maximum reusability, maintainability, and clarity in component organization.

Foundation Layer

The Foundation Layer contains atomic UI building blocks that form the base of our design system.

Characteristics:

  • Single Responsibility: Each component has one clear purpose
  • No Business Logic: Pure presentation components with no domain knowledge
  • Design Token Driven: All styling comes from centralized design tokens
  • Highly Reusable: Used across multiple patterns and features
  • Accessibility First: Built with WCAG compliance as a core requirement

Examples:

  • Button - Primary action component
  • Input - Text input fields
  • Text - Typography component
  • Card - Content container
  • Icon - Icon display component

Import Pattern:

import { Button, Input, Text } from '@/ui/foundation';

Patterns Layer

The Patterns Layer combines foundation components to create complex, reusable UI patterns.

Characteristics:

  • Composed Architecture: Built exclusively from foundation components
  • Complex Behavior: Handle sophisticated user interactions
  • Reusable Patterns: Common UI patterns used across features
  • No Domain Logic: Generic and not tied to specific business entities
  • Configurable: Flexible through props and composition

Examples:

  • Modal - Overlay dialogs using Card, Button, and Text
  • Form - Complete form wrapper with validation
  • DataTable - Data grid with sorting/filtering
  • SearchBox - Search input with suggestions
  • Toast - Notification messages

Import Pattern:

import { Modal, Form, DataTable } from '@/ui/patterns';

Business Layer

The Business Layer contains domain-aware components that understand business entities and logic.

Characteristics:

  • Domain Aware: Work with specific business entities (Product, User, Order)
  • Feature Shared: Used across multiple features
  • Business Logic: Handle domain-specific calculations and rules
  • API Integration: May use domain hooks for data fetching
  • Context Sensitive: Behavior changes based on business context

Examples:

  • ProductCard - Product display with pricing logic
  • UserAvatar - User profile with role indicators
  • OrderStatus - Order state with business rules
  • PaymentMethod - Payment display with validation
  • AddToCart - Shopping cart integration

Import Pattern:

import { ProductCard, UserAvatar, OrderStatus } from '@/ui/business';

Layer Dependencies

The architecture enforces strict dependency rules:

Dependency Rules:

  1. Foundation components can only import from design tokens and shared utilities
  2. Patterns can import from Foundation but not from Business
  3. Business can import from both Foundation and Patterns
  4. Features can import from all three layers
  5. Never import across features or from features into UI layers

Decision Framework

When creating a new component, ask these questions:

  1. Does it have business logic or domain knowledge?

    • Yes → Business Layer
    • No → Continue to question 2
  2. Is it composed of multiple other components?

    • Yes → Patterns Layer
    • No → Foundation Layer
  3. Is it used in only one feature?

    • Yes → Keep it in the feature folder
    • No → Move to appropriate UI layer

This three-layer approach ensures:

  • Clear separation of concerns
  • Maximum component reusability
  • Predictable component locations
  • Easy onboarding for new developers
  • Efficient AI collaboration

UI Folder Structure Deep Dive

Complete UI Organization

ui/
├── foundation/                # Atomic design system components
│   ├── Button/
│   │   ├── Button.tsx
│   │   ├── Button.test.tsx
│   │   ├── types.ts
│   │   └── index.ts
│   ├── Input/
│   ├── Text/
│   ├── Card/
│   ├── Icon/
│   └── index.ts              # Foundation barrel export

├── patterns/                 # Composed UI patterns
│   ├── Modal/
│   │   ├── Modal.tsx
│   │   ├── Modal.test.tsx
│   │   ├── types.ts
│   │   ├── components/       # Internal modal components
│   │   │   ├── ModalHeader.tsx
│   │   │   ├── ModalBody.tsx
│   │   │   └── ModalFooter.tsx
│   │   └── index.ts
│   ├── Form/
│   ├── DataTable/
│   ├── SearchBox/
│   └── index.ts              # Patterns barrel export

├── business/                 # Domain-aware components
│   ├── ProductCard/
│   │   ├── ProductCard.tsx
│   │   ├── ProductCard.test.tsx
│   │   ├── types.ts
│   │   └── index.ts
│   ├── UserAvatar/
│   ├── OrderStatus/
│   ├── PriceDisplay/
│   └── index.ts              # Business barrel export

└── index.ts                  # Main UI barrel export

Component Hierarchy and Dependencies

Foundation Layer Architecture

Purpose and Characteristics

Foundation components are the atomic building blocks of our design system:

  • Single Responsibility: Each component has one clear purpose
  • No Business Logic: Pure presentation components
  • Design Token Driven: All styling comes from core/shared/styles/
  • Highly Reusable: Used across multiple patterns and features
  • Accessible: Built with accessibility as a core requirement

Foundation Component Categories

Core Interactive Elements

foundation/
├── Button/           # Primary action component
├── IconButton/       # Icon-only button variant
├── Link/            # Navigation and external links
└── Pressable/       # Custom touchable areas

Form Elements

foundation/
├── Input/           # Text input fields
├── TextArea/        # Multi-line text input
├── Select/          # Dropdown selection
├── Checkbox/        # Boolean selection
├── Radio/           # Single choice from group
└── Switch/          # Toggle component

Display Elements

foundation/
├── Text/            # Typography component
├── Heading/         # Semantic headings
├── Icon/            # Icon display
├── Image/           # Image with loading states
├── Avatar/          # User profile images
└── Badge/           # Status indicators

Layout Elements

foundation/
├── Box/             # Generic container
├── Card/            # Content cards
├── Divider/         # Visual separators
├── Spacer/          # Layout spacing
└── Container/       # Page containers

Foundation Component Example

For a complete implementation example of a foundation component, including all variants, states, accessibility features, and testing patterns, see the Button Component.

Foundation components like Button demonstrate key principles:

  • Single responsibility (action triggering)
  • Design token usage for all styling
  • Comprehensive prop interfaces
  • Built-in accessibility
  • No business logic

Patterns Layer Architecture

Purpose and Characteristics

Pattern components combine foundation components to create complex, reusable UI patterns:

  • Composed Architecture: Built from foundation components
  • Complex Behavior: Handle sophisticated user interactions
  • Reusable Patterns: Common UI patterns used across features
  • No Domain Logic: Generic, not tied to specific business entities
  • Configurable: Flexible through props and composition

Pattern Component Categories

patterns/
├── Tabs/            # Tab navigation
├── Breadcrumb/      # Navigation hierarchy
├── Pagination/      # Data pagination
└── Menu/            # Dropdown menus

Data Display Patterns

patterns/
├── DataTable/       # Data grid with sorting/filtering
├── List/            # Virtualized lists
├── Timeline/        # Event timelines
└── Stats/           # Statistics display

Feedback Patterns

patterns/
├── Modal/           # Overlay dialogs
├── Toast/           # Notification messages
├── Alert/           # Warning/error alerts
├── Tooltip/         # Contextual help
└── LoadingSpinner/  # Loading states

Form Patterns

patterns/
├── Form/            # Complete form wrapper
├── FormField/       # Label + Input + Error
├── SearchBox/       # Search with suggestions
└── FileUpload/      # File upload widget

Pattern Component Example

For a comprehensive pattern component example showing how to compose foundation components into complex UI patterns, see the Modal Pattern.

Pattern components like Modal demonstrate:

  • Composition of multiple foundation components
  • Complex interaction handling
  • Flexible configuration through props
  • Accessibility management
  • No domain-specific logic

Business Layer Architecture

Purpose and Characteristics

Business components understand domain entities and contain business logic:

  • Domain Aware: Work with business entities (Product, User, Order)
  • Feature Shared: Used across multiple features
  • Business Logic: Handle domain-specific calculations and rules
  • API Integration: May use domain hooks for data fetching
  • Context Sensitive: Behavior changes based on business context

Business Component Categories

Entity Display Components

business/
├── ProductCard/       # Product information display
├── UserProfile/       # User profile information
├── OrderSummary/      # Order details display
└── PaymentMethod/     # Payment information display

Status and State Components

business/
├── OrderStatus/       # Order status indicators
├── PaymentStatus/     # Payment state display
├── UserRole/          # User role badges
└── StockIndicator/    # Product availability

Interactive Business Components

business/
├── AddToCart/         # Add product to cart
├── UserActions/       # User management actions
├── ShareProduct/      # Product sharing functionality
└── RateProduct/       # Product rating component

Business Component Example

// ui/business/ProductCard/ProductCard.tsx
import React from 'react';
import { View, TouchableOpacity } from 'react-native';
import { Card } from '@/ui/foundation/Card';
import { Text } from '@/ui/foundation/Text';
import { Button } from '@/ui/foundation/Button';
import { Image } from '@/ui/foundation/Image';
import { Badge } from '@/ui/foundation/Badge';
import { useProduct } from '@/core/domains/products/hooks';
import { formatCurrency } from '@/core/shared/utils/number';
import { theme } from '@/core/shared/styles/theme';
import type { ProductCardProps } from './types';
 
/**
 * Product card component with business logic
 * Integrates with product domain for data and actions
 */
export const ProductCard: React.FC<ProductCardProps> = ({
  productId,
  onPress,
  onAddToCart,
  showActions = true,
  compact = false,
}) => {
  const { data: product, isLoading } = useProduct(productId);
 
  if (isLoading || !product) {
    return <Card>Loading...</Card>;
  }
 
  const handleAddToCart = () => {
    onAddToCart?.(product);
  };
 
  const isOutOfStock = product.stock <= 0;
  const isLowStock = product.stock > 0 && product.stock <= 5;
 
  return (
    <TouchableOpacity onPress={() => onPress?.(product)}>
      <Card style={{ padding: theme.spacing.md }}>
        <Image
          source={{ uri: product.imageUrl }}
          style={{
            width: '100%',
            height: compact ? 120 : 200,
            borderRadius: theme.radii.md,
          }}
          resizeMode="cover"
        />
        
        <View style={{ marginTop: theme.spacing.sm }}>
          <View style={{
            flexDirection: 'row',
            justifyContent: 'space-between',
            alignItems: 'flex-start',
          }}>
            <Text 
              variant="heading" 
              size={compact ? 'medium' : 'large'}
              numberOfLines={2}
              style={{ flex: 1 }}
            >
              {product.name}
            </Text>
            
            {isOutOfStock && (
              <Badge variant="error">Out of Stock</Badge>
            )}
            {isLowStock && (
              <Badge variant="warning">Low Stock</Badge>
            )}
          </View>
          
          {!compact && (
            <Text 
              variant="body" 
              color="secondary"
              numberOfLines={3}
              style={{ marginTop: theme.spacing.xs }}
            >
              {product.description}
            </Text>
          )}
          
          <View style={{
            flexDirection: 'row',
            justifyContent: 'space-between',
            alignItems: 'center',
            marginTop: theme.spacing.sm,
          }}>
            <Text variant="heading" size="large" color="primary">
              {formatCurrency(product.price)}
            </Text>
            
            {showActions && (
              <Button
                variant="primary"
                size="small"
                onPress={handleAddToCart}
                disabled={isOutOfStock}
              >
                {isOutOfStock ? 'Unavailable' : 'Add to Cart'}
              </Button>
            )}
          </View>
        </View>
      </Card>
    </TouchableOpacity>
  );
};

Design Token Integration

Token Usage Hierarchy

Token Categories and Usage

Color Tokens

// All UI components must use color tokens
import { theme } from '@/core/shared/styles/theme';
 
// ✅ Correct usage
const styles = {
  backgroundColor: theme.colors.primary[500],
  color: theme.colors.text.primary,
  borderColor: theme.colors.border.default,
};
 
// ❌ Never hardcode colors
const styles = {
  backgroundColor: '#3b82f6',  // Wrong!
  color: '#000000',            // Wrong!
};

Typography Tokens

import { typography } from '@/core/shared/styles/typography';
 
// ✅ Use typography tokens
const textStyles = {
  fontSize: typography.sizes.large,
  fontWeight: typography.weights.bold,
  lineHeight: typography.lineHeights.normal,
};

Spacing Tokens

import { theme } from '@/core/shared/styles/theme';
 
// ✅ Use spacing tokens
const layoutStyles = {
  padding: theme.spacing.md,
  margin: theme.spacing.lg,
  gap: theme.spacing.sm,
};

Integration with Core Architecture

Domain Integration Patterns

Business components can integrate with domains through hooks:

// ui/business/ProductCard/ProductCard.tsx
import { useProduct } from '@/core/domains/products/hooks';
import { useCart } from '@/core/domains/cart/hooks';
 
export const ProductCard: React.FC<ProductCardProps> = ({ productId }) => {
  // ✅ Business components can use domain hooks
  const { data: product } = useProduct(productId);
  const { addItem } = useCart();
  
  const handleAddToCart = () => {
    addItem(product);
  };
  
  // Component implementation
};

Feature Integration Patterns

Features compose UI components to create complete user experiences:

// features/product-catalog/screens/ProductListScreen.tsx
import { ProductCard } from '@/ui/business/ProductCard';
import { SearchBox } from '@/ui/patterns/SearchBox';
import { Button } from '@/ui/foundation/Button';
 
export const ProductListScreen = () => {
  return (
    <View>
      <SearchBox onSearch={handleSearch} />
      
      {products.map(product => (
        <ProductCard
          key={product.id}
          productId={product.id}
          onPress={navigateToProduct}
          onAddToCart={handleAddToCart}
        />
      ))}
      
      <Button onPress={loadMore}>Load More</Button>
    </View>
  );
};

AI Collaboration Benefits

Predictable Structure

The three-layer architecture provides clear guidelines for AI:

AI: "Create a foundation Button component"
→ Goes to ui/foundation/Button/
→ Uses design tokens
→ No business logic
→ Single responsibility

AI: "Create a business ProductCard component"  
→ Goes to ui/business/ProductCard/
→ Uses domain hooks
→ Contains business logic
→ Accepts Product entities

Consistent Prompting

Standardized AI prompts ensure consistency:

// Foundation component prompt
"Create a foundation [Component] component that:
- Uses design tokens from core/shared/styles/
- Has no business logic
- Includes proper TypeScript interfaces
- Follows accessibility guidelines"
 
// Pattern component prompt  
"Create a pattern [Component] component that:
- Composes foundation components
- Handles complex UI behavior
- Remains domain-agnostic
- Includes comprehensive prop interfaces"
 
// Business component prompt
"Create a business [Component] component that:
- Integrates with [domain] data
- Uses foundation/pattern components for UI
- Contains domain-specific logic
- Handles business entity props"

Migration and Adoption Strategy

Existing Project Migration

  1. Audit Current Components

    • Categorize existing components
    • Identify dependencies and usage patterns
  2. Create UI Folder Structure

    • Set up foundation/patterns/business folders
    • Move components to appropriate locations
  3. Implement Design Token Integration

    • Replace hardcoded values with tokens
    • Update styling patterns
  4. Update Import Paths

    • Fix all component imports
    • Add barrel exports for clean imports

New Project Setup

  1. Initialize UI Structure

    • Create folder hierarchy
    • Set up barrel export files
  2. Implement Core Foundation Components

    • Start with Button, Text, Card basics
    • Build up component library gradually
  3. Establish Patterns

    • Create common patterns as needed
    • Document usage examples
  4. Add Business Components

    • Build domain-aware components
    • Integrate with domain hooks