# Design Document: Site Improvements - Footer & Companies ## Overview This design implements site-wide improvements including spacing standardization, a complete footer component with contact information and social links, an animated company logos banner with infinite scroll, and reorganization of the Experience section into Software/Hardware categories. The implementation maintains the existing minimalist design system using Monument Extended typography, #ccff00 accent color, and Framer Motion animations. The design focuses on three main areas: 1. **Spacing System Standardization**: Applying consistent spacing tokens across all sections 2. **Footer Component**: A new footer with contact info, social links, and copyright 3. **CompanyLogos Component**: An infinite-scroll animated banner displaying company logos 4. **Experience Section Refactor**: Categorizing experiences into Software and Hardware groups All components follow the established design system patterns from `globals.css` and integrate with the existing Framer Motion animation infrastructure. ## Architecture ### Component Structure ``` app/ ├── components/ │ ├── Footer.tsx (replace existing) │ ├── CompanyLogos.tsx (new) │ ├── Experience.tsx (refactor) │ └── Section.tsx (update spacing) ├── page.tsx (update layout) └── globals.css (spacing documentation) ``` ### Data Flow 1. **Footer Component**: Static data (email, social links) defined as constants within the component 2. **CompanyLogos Component**: Logo data (company names, image paths) defined as constants, rendered with animation 3. **Experience Component**: Existing data from `usePortfolioData()` hook, filtered and categorized by type field ### Animation Strategy All animations use Framer Motion with reduced motion support: - **CompanyLogos**: Continuous horizontal scroll using `animate` with infinite loop - **Footer**: Subtle hover states on social links - **Experience**: Existing stagger animations maintained, category headers added ## Components and Interfaces ### 1. Footer Component **Purpose**: Display contact information, social links, and copyright in a consistent footer layout. **Props**: None (self-contained component) **Structure**: ```tsx interface SocialLink { name: string; href: string; icon: string; // SVG path or icon identifier ariaLabel: string; } const socialLinks: SocialLink[] = [ { name: 'GitHub', href: 'https://github.com/...', icon: '...', ariaLabel: 'Visit GitHub profile' }, { name: 'LinkedIn', href: 'https://linkedin.com/...', icon: '...', ariaLabel: 'Visit LinkedIn profile' }, // ... more links ]; ``` **Layout**: - Desktop: Three-column grid (contact info | social links | copyright) - Tablet: Two-column grid (contact/social | copyright) - Mobile: Single column stack **Styling**: - Background: `var(--ink)` with `border-t: 1px solid rgba(255,255,255,0.06)` - Typography: Monument Extended for headings, Geist Mono for body text - Accent: `var(--slash)` for link hover states - Padding: `py-sp-12 px-sp-16` (desktop), `py-sp-8 px-sp-6` (mobile) ### 2. CompanyLogos Component **Purpose**: Display an infinite-scrolling banner of company logos after the header. **Props**: None (self-contained component) **Structure**: ```tsx interface CompanyLogo { name: string; imagePath: string; alt: string; } const companies: CompanyLogo[] = [ { name: 'Apolo Energia', imagePath: '/logos/apolo.svg', alt: 'Apolo Energia logo' }, { name: 'Julia Beauty Lashes', imagePath: '/logos/julia.svg', alt: 'Julia Beauty Lashes logo' }, { name: 'Innovo', imagePath: '/logos/innovo.svg', alt: 'Innovo logo' }, { name: 'TeraByteShop', imagePath: '/logos/terabyte.svg', alt: 'TeraByteShop logo' }, { name: 'Pichau', imagePath: '/logos/pichau.svg', alt: 'Pichau logo' }, ]; ``` **Animation Implementation**: ```tsx // Duplicate logo array for seamless loop const duplicatedLogos = [...companies, ...companies]; // Framer Motion animation {duplicatedLogos.map((logo, index) => ( {logo.alt} ))} ``` **Reduced Motion Handling**: ```tsx const shouldReduceMotion = useReducedMotion(); // If reduced motion, display static grid instead of animation {shouldReduceMotion ? (
{companies.map(logo => )}
) : ( )} ``` **Styling**: - Container: `overflow-hidden` with `border-b: 1px solid var(--border)` - Background: `var(--paper)` with optional subtle grid pattern - Logo sizing: `h-12` (48px) with `grayscale` filter, `grayscale-0` on hover - Spacing: `py-sp-8` vertical padding, `gap-sp-12` between logos ### 3. Experience Component Refactor **Purpose**: Organize experience entries into Software and Hardware categories. **Changes**: 1. Add category filtering logic 2. Render two separate sections with category headers 3. Maintain existing card structure and animations **Implementation**: ```tsx const softwareExperiences = sortedExperiences.filter(exp => exp.type === 'Software'); const hardwareExperiences = sortedExperiences.filter(exp => exp.type === 'Hardware'); return (
{/* Software Category */}

/ Software

{softwareExperiences.map(exp => )}
{/* Hardware Category */}

/ Hardware

{hardwareExperiences.map(exp => )}
); ``` **Styling**: - Category headers: Monument Extended, `text-2xl`, with slash accent - Separator: `mb-sp-12` between categories - Cards: Maintain existing styling and animations ### 4. Spacing System Updates **Standardization**: All sections should use consistent spacing tokens from `globals.css`: - Section padding: `py-sp-20 px-sp-16` (desktop), `py-sp-16 px-sp-6` (mobile) - Section margins: `mb-sp-12` between major sections - Card spacing: `space-y-sp-6` for vertical stacks - Grid gaps: `gap-sp-6` for 2-column, `gap-sp-4` for 4-column **Responsive Scaling**: Tailwind responsive utilities handle breakpoints: - Mobile: `px-sp-6 py-sp-16` - Tablet: `px-sp-10 py-sp-18` - Desktop: `px-sp-16 py-sp-20` ## Data Models ### SocialLink ```typescript interface SocialLink { name: string; // Display name (e.g., "GitHub") href: string; // Full URL icon: string; // SVG path or icon component reference ariaLabel: string; // Accessibility label } ``` ### CompanyLogo ```typescript interface CompanyLogo { name: string; // Company name imagePath: string; // Path to logo image (SVG preferred) alt: string; // Alt text for accessibility } ``` ### Experience (existing, with type field) ```typescript interface Experience { id: string; title: string; company: string; type: 'Software' | 'Hardware'; // Used for categorization period: string; location: string; description: string; achievements: string[]; technologies: string[]; featured: boolean; } ``` ## Correctness Properties *A property is a characteristic or behavior that should hold true across all valid executions of a system—essentially, a formal statement about what the system should do. Properties serve as the bridge between human-readable specifications and machine-verifiable correctness guarantees.* ### Property 1: Consistent Spacing System *For any* major section or container element in the site, it should use spacing tokens from the design system (sp-1 through sp-24) with appropriate responsive modifiers for different viewport sizes. **Validates: Requirements 1.1, 1.2, 1.3, 1.4** ### Property 2: Social Links Open in New Tab *For any* social media link in the Footer component, it should have `target="_blank"` and `rel="noopener noreferrer"` attributes to open in a new tab securely. **Validates: Requirements 2.7** ### Property 3: Responsive Component Layout *For any* new component (Footer, CompanyLogos, Experience categories), it should include Tailwind responsive utility classes (sm:, md:, lg:) to adapt layout across viewport sizes. **Validates: Requirements 2.6, 3.7, 4.5** ### Property 4: Reduced Motion Respect *For any* animated component, when `useReducedMotion()` returns true, the component should render a static alternative without motion animations. **Validates: Requirements 3.6, 6.3** ### Property 5: Experience Categorization *For any* experience entry in the Experience section, it should be filtered by its `type` field and rendered within the corresponding Software or Hardware category group. **Validates: Requirements 4.1** ### Property 6: Chronological Ordering Within Categories *For any* category group in the Experience section, the experience entries within that group should be sorted in descending chronological order by year. **Validates: Requirements 4.3** ### Property 7: Monument Extended Typography *For any* heading element (h1, h2, h3) in new components (Footer, CompanyLogos, Experience categories), it should use the `font-display` class which applies Monument Extended font family. **Validates: Requirements 2.4, 4.2, 5.4** ### Property 8: Slash Color Accents *For any* accent element (category separators, hover states, decorative elements) in new components, it should use `var(--slash)` color (#ccff00) via Tailwind classes like `text-[var(--slash)]` or `bg-[var(--slash)]`. **Validates: Requirements 5.1, 5.2** ### Property 9: ARIA Labels for Links *For any* social media link in the Footer component, it should have a descriptive `aria-label` attribute that identifies the platform and action. **Validates: Requirements 6.1** ### Property 10: Alt Text for Images *For any* company logo image in the CompanyLogos component, it should have a non-empty `alt` attribute describing the company. **Validates: Requirements 6.2** ### Property 11: Semantic Heading Hierarchy *For any* sequence of heading elements in the Experience section, the heading levels should follow proper semantic hierarchy (h2 for section title, h3 for categories, no skipped levels). **Validates: Requirements 6.4** ### Property 12: Keyboard Navigation Support *For any* interactive element (links, buttons) in new components, it should be keyboard accessible with proper focus states and no negative tabindex values. **Validates: Requirements 6.5** ## Error Handling ### Footer Component **Missing Social Links Data**: - Gracefully render empty state or hide social links section - Log warning to console in development mode - Ensure layout doesn't break with missing data **Invalid Email Format**: - Display email as-is (validation is not the footer's responsibility) - Ensure mailto: link is properly formatted ### CompanyLogos Component **Missing Logo Images**: - Display company name as fallback text - Log warning for missing images in development - Maintain layout spacing even with missing images **Animation Performance Issues**: - Monitor frame rate using `useAnimationFrame` hook - Fallback to static display if performance drops below threshold - Respect `prefers-reduced-motion` preference ### Experience Component **Missing Type Field**: - Default to "Software" category if type is undefined - Log warning for entries without type field - Ensure all entries are displayed (don't silently drop data) **Empty Categories**: - Hide category header if no entries exist for that type - Maintain spacing consistency when categories are hidden ### General Error Handling **Component Render Errors**: - Wrap components in Error Boundaries - Display user-friendly error message - Log detailed error information for debugging **Responsive Layout Issues**: - Use CSS fallbacks for unsupported features - Test across major browsers and devices - Ensure content remains accessible even if styling fails ## Testing Strategy ### Dual Testing Approach This feature requires both unit tests and property-based tests to ensure comprehensive coverage: **Unit Tests**: Focus on specific examples, edge cases, and integration points - Specific component rendering scenarios - Edge cases (empty data, missing fields) - User interaction flows (clicking links, reduced motion) - Integration between components **Property-Based Tests**: Verify universal properties across all inputs - Spacing consistency across generated component trees - Accessibility attributes across generated link/image sets - Categorization logic across generated experience data - Responsive class application across generated components ### Testing Framework **Framework**: Vitest + React Testing Library + fast-check - Vitest for test runner and assertions - React Testing Library for component testing - fast-check for property-based testing (TypeScript-native) **Property Test Configuration**: - Minimum 100 iterations per property test - Each test tagged with: `Feature: site-improvements-footer-companies, Property {number}: {property_text}` - Use custom generators for component props and data structures ### Unit Test Coverage **Footer Component**: - Renders contact information correctly - Renders all social links with correct attributes - Displays current year in copyright - Opens social links in new tab - Applies correct styling classes - Responsive layout changes at breakpoints **CompanyLogos Component**: - Renders all five company logos - Duplicates logo array for infinite scroll - Applies animation with correct configuration - Displays static grid when reduced motion is enabled - Handles missing logo images gracefully - Maintains responsive layout **Experience Component**: - Filters experiences by Software/Hardware type - Renders category headers with correct styling - Maintains chronological order within categories - Hides empty categories - Applies consistent spacing between categories - Responsive layout on mobile devices ### Property-Based Test Coverage **Property 1: Consistent Spacing System** - Generate random component trees with various nesting levels - Verify all spacing classes use design system tokens - Check responsive modifiers are present **Property 2: Social Links Open in New Tab** - Generate random arrays of social links - Verify each link has target="_blank" and rel="noopener noreferrer" **Property 3: Responsive Component Layout** - Generate random component configurations - Verify presence of responsive utility classes **Property 4: Reduced Motion Respect** - Generate random animation configurations - Verify static rendering when reduced motion is true **Property 5: Experience Categorization** - Generate random experience arrays with mixed types - Verify correct filtering and grouping by type **Property 6: Chronological Ordering Within Categories** - Generate random experience arrays with various dates - Verify descending chronological order within each category **Property 7: Monument Extended Typography** - Generate random heading elements - Verify font-display class is applied **Property 8: Slash Color Accents** - Generate random accent elements - Verify var(--slash) color usage **Property 9: ARIA Labels for Links** - Generate random social link arrays - Verify each has descriptive aria-label **Property 10: Alt Text for Images** - Generate random logo arrays - Verify each image has non-empty alt text **Property 11: Semantic Heading Hierarchy** - Generate random heading sequences - Verify proper h2 → h3 hierarchy without skips **Property 12: Keyboard Navigation Support** - Generate random interactive elements - Verify focusability and proper tabindex values ### Integration Testing **Page Layout Integration**: - Verify CompanyLogos appears after Header - Verify Footer appears at bottom of page - Verify spacing between all sections is consistent - Test full page scroll behavior **Animation Performance**: - Monitor CompanyLogos animation frame rate - Verify smooth scrolling across devices - Test reduced motion fallback behavior **Accessibility Testing**: - Run axe-core automated accessibility tests - Verify keyboard navigation through all components - Test screen reader compatibility - Verify color contrast ratios meet WCAG AA standards ### Visual Regression Testing **Snapshot Tests**: - Footer component in all responsive states - CompanyLogos with animation and static states - Experience section with both categories populated - Experience section with one empty category **Cross-Browser Testing**: - Chrome, Firefox, Safari, Edge - Mobile browsers (iOS Safari, Chrome Mobile) - Verify consistent rendering and animation performance