feat: add animated components for enhanced UI/UX

- Introduced DrawLine component for drawing animations.
- Added LazyRevealImage component for lazy loading images with reveal animations.
- Implemented TextDiffuseReveal for animated text reveals with staggered effects.
- Created TopProgressBar for a dynamic loading indicator.
- Added PointCloud mock for testing animations.
- Developed useReducedMotion hook to handle user preferences for reduced motion.
- Centralized animation configurations in config.ts for easier management.
- Defined animation variants in variants.ts for consistent animation effects.
- Established AnimationProvider to supply global animation settings.
- Created tests for AnimationProvider and useReducedMotion hook.
- Added SVG assets for branding and UI elements.
- Documented frontend review plan and hero circuit board animation plan.
This commit is contained in:
Evandro Fonseca Junior committed 2026-03-15 21:06:43 -03:00
1 parent 0ab6930f92
commit 08dd046887
76 files changed
+21682 -1197

No files matched your search

@@ -0,0 +1,501 @@
# 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
<motion.div
animate={{
x: [0, -50%], // Move by half the width (one set of logos)
}}
transition={{
duration: 30, // 30 seconds for full loop
repeat: Infinity,
ease: "linear",
}}
>
{duplicatedLogos.map((logo, index) => (
<img key={`${logo.name}-${index}`} src={logo.imagePath} alt={logo.alt} />
))}
</motion.div>
```
**Reduced Motion Handling**:
```tsx
const shouldReduceMotion = useReducedMotion();
// If reduced motion, display static grid instead of animation
{shouldReduceMotion ? (
<div className="grid grid-cols-5 gap-sp-6">
{companies.map(logo => <img key={logo.name} ... />)}
</div>
) : (
<motion.div animate={...} />
)}
```
**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 (
<Section id="experience" ...>
{/* Software Category */}
<div className="mb-sp-12">
<h3 className="font-display text-2xl font-bold mb-sp-6 flex items-center gap-sp-3">
<span className="text-[var(--slash)]">/</span> Software
</h3>
<motion.div variants={listVariants}>
{softwareExperiences.map(exp => <ExperienceCard key={exp.id} {...exp} />)}
</motion.div>
</div>
{/* Hardware Category */}
<div>
<h3 className="font-display text-2xl font-bold mb-sp-6 flex items-center gap-sp-3">
<span className="text-[var(--slash)]">/</span> Hardware
</h3>
<motion.div variants={listVariants}>
{hardwareExperiences.map(exp => <ExperienceCard key={exp.id} {...exp} />)}
</motion.div>
</div>
</Section>
);
```
**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