TalentSync

Home Projects TalentSync Frontend Application Shared Components

Shared Components

Purpose and Scope

This document covers the reusable UI components and utilities that are shared across multiple features in the TalentSync frontend application. These components provide consistent user experience patterns including navigation, file handling, user feedback, and loading states. For information about feature-specific components (Cold Mail, Hiring Assistant, etc.), see their respective sections under 4.5. For authentication-specific UI components, see 4.2. For the overall navigation architecture, see 4.3.

Component Architecture Overview

The shared components in TalentSync follow a layered architecture where primitive UI components are composed into feature-level reusable components.

Component Hierarchy

Architecture Diagram

Sources: frontend/components/navbar.tsx1-397 frontend/components/mobile-bottom-nav.tsx1-209 frontend/components/floating-action-button.tsx1-109 frontend/components/cold-mail/ResumeSelection.tsx1-697


Navigation Components

Desktop Sidebar Navigation

The Navbar component provides the primary navigation interface for desktop and tablet devices. It implements a collapsible sidebar with role-based menu items and user session management.

Component Structure

Component Part File Location Purpose
Main Container frontend/components/navbar.tsx41-236 Desktop sidebar with collapse functionality
Tablet Navigation frontend/components/navbar.tsx239-391 Top bar navigation for tablet breakpoint
Mobile Navigation Delegated to MobileBottomNav Bottom navigation for mobile devices

Key Features

Collapsible State Management:

const { isCollapsed, setIsCollapsed } = useSidebar();

The sidebar uses a context provider to maintain collapse state across renders. Width transitions between 72px (collapsed) and 288px (expanded).

Navigation Items: Navigation items are imported from frontend/lib/navigation.ts25-46 and include:

  • navItems: Main navigation links (Home, About, Job Seekers, Recruiters)
  • actionItems: Quick action shortcuts with descriptions
  • mobileNavItems: Mobile-specific navigation configuration

Session-Based Rendering:

const { data: session, status } = useSession();

The navigation adapts based on authentication state, showing different options for authenticated vs. unauthenticated users at frontend/components/navbar.tsx146-234

Sources: frontend/components/navbar.tsx28-397 frontend/lib/navigation.ts1-109


Mobile Bottom Navigation

The MobileBottomNav component provides a modern, interactive navigation bar at the bottom of the screen for mobile devices.

Interactive Menu Integration

Architecture Diagram

Component Responsibilities

The mobile navigation system is split into three layers:

  1. MobileBottomNav frontend/components/mobile-bottom-nav.tsx23-64

    • Determines active route based on pathname
    • Handles navigation logic via router.push()
    • Manages visibility (hidden on screens ≥640px)
  2. InteractiveMenuWithNavigation frontend/components/mobile-bottom-nav.tsx100-206

    • Renders navigation buttons with active state
    • Manages textRefs and itemRefs for dynamic styling
    • Splits navigation into left items (0-1) and right items (2-3) with FAB spacer
  3. FloatingActionButton frontend/components/floating-action-button.tsx11-108

    • Expands to show actionItems from navigation config
    • Positioned in center gap between left/right nav items
    • Uses Framer Motion for animation effects

Sources: frontend/components/mobile-bottom-nav.tsx1-209 frontend/components/floating-action-button.tsx1-109 frontend/components/ui/modern-mobile-menu.tsx1-121


Floating Action Button

The FAB provides quick access to major features from any page on mobile devices.

Expansion Behavior

Architecture Diagram

Animation System:

Z-Index Layering:

Layer Z-Index Component
Backdrop 50 Semi-transparent overlay
Main FAB 60 Plus/X button
Sub-actions 70 Expandable action buttons

Sources: frontend/components/floating-action-button.tsx1-109 frontend/lib/navigation.ts71-108


ResumeSelection Component

The ResumeSelection component is a complex, reusable component used in multiple features (Cold Mail Generator, Hiring Assistant) to provide consistent resume selection/upload functionality.

Component Modes and Data Flow

Architecture Diagram

Sources: frontend/components/cold-mail/ResumeSelection.tsx54-696

Mode-Specific Behavior

Existing Resume Mode

When resumeSelectionMode === "existing":

  1. Fetches user resumes from API endpoint on mount at frontend/app/dashboard/cold-mail/page.tsx75-93
  2. Displays dropdown with resume metadata (customName, candidateName, predictedField, uploadDate)
  3. Auto-populates form fields when resume is selected at frontend/components/cold-mail/ResumeSelection.tsx210-227

Dropdown Implementation:

Upload Mode

When resumeSelectionMode === "upload":

  1. Presents file input with drag-and-drop UI at frontend/components/cold-mail/ResumeSelection.tsx290-363
  2. Validates file types: .pdf, .doc, .docx, .txt, .md
  3. For text files, previews first 500 characters at frontend/components/cold-mail/ResumeSelection.tsx88-92
  4. Handles pre-loaded files from localStorage (from analysis page) at frontend/app/dashboard/cold-mail/page.tsx120-159

File Upload UI States:

State Visual Indicator File Location
Empty Upload icon with supported formats ResumeSelection.tsx333-359
File Selected CheckCircle with filename ResumeSelection.tsx308-331
Pre-loaded "Pre-loaded from analysis" message ResumeSelection.tsx322-330

Custom Draft Mode

When resumeSelectionMode === "customDraft" (Cold Mail only):

  1. User can select existing resume OR upload new file (both optional) at frontend/components/cold-mail/ResumeSelection.tsx386-526
  2. Paste email draft in textarea at frontend/components/cold-mail/ResumeSelection.tsx642-647
  3. Provide edit instructions at frontend/components/cold-mail/ResumeSelection.tsx652-658
  4. Click "Edit My Draft" button to enhance draft at frontend/components/cold-mail/ResumeSelection.tsx660-679
  5. Enhanced draft displayed in separate section at frontend/components/cold-mail/ResumeSelection.tsx680-691

Sources: frontend/components/cold-mail/ResumeSelection.tsx1-697 frontend/app/dashboard/cold-mail/page.tsx34-805

Interface Definition

interface ResumeSelectionProps {
  resumeSelectionMode: "existing" | "upload" | "customDraft";
  setResumeSelectionMode: (mode) => void;
  userResumes: UserResume[];
  selectedResumeId: string;
  setSelectedResumeId: (id: string) => void;
  isLoadingResumes: boolean;
  showResumeDropdown: boolean;
  setShowResumeDropdown: (show: boolean) => void;
  resumeFile: File | null;
  setResumeFile: (file: File | null) => void;
  resumeText: string;
  setResumeText: (text: string) => void;
  isPreloaded: boolean;
  setIsPreloaded: (pre: boolean) => void;
  formData: any;
  setFormData: (cb: (prev: any) => any) => void;
  customDraft: string;
  setCustomDraft: (draft: string) => void;
  editInstructions: string;
  setEditInstructions: (instructions: string) => void;
  customDraftEdited: string;
  setCustomDraftEdited: (edited: string) => void;
  isEditing: boolean;
  handleCustomDraftEdit: () => void;
  handleInputChange: (field: string, value: string) => void;
}

Note: The Hiring Assistant version uses a simpler interface without customDraft props, as it only supports existing and upload modes at frontend/app/dashboard/hiring-assistant/page.tsx59-61

Sources: frontend/components/cold-mail/ResumeSelection.tsx26-52


Toast Notification System

The toast system provides user feedback for success, error, and informational messages using Radix UI primitives.

Toast Architecture

Architecture Diagram

Sources: frontend/components/ui/toast.tsx1-131

Toast Variants and Styling

The toast component uses class-variance-authority for variant management:

Variant Background Border Use Case
default from-white/15 to-white/5 border-white/20 Success, info messages
destructive from-red-500/20 to-red-600/10 border-red-400/30 Error messages

Visual Properties:

Usage Pattern

const { toast } = useToast();

// Success notification
toast({
  title: "Email Generated Successfully!",
  description: "Your cold email has been generated and is ready to use.",
});

// Error notification
toast({
  title: "Generation Failed",
  description: error instanceof Error ? error.message : "An error occurred.",
  variant: "destructive",
});

Common Use Cases:

Sources: frontend/components/ui/toast.tsx1-131 frontend/app/dashboard/cold-mail/page.tsx10 frontend/app/dashboard/hiring-assistant/page.tsx10


Loader Components

The application uses multiple loader patterns to indicate processing states.

Loader Variants and Usage

Architecture Diagram

Sources: frontend/app/dashboard/cold-mail/page.tsx9 frontend/app/dashboard/hiring-assistant/page.tsx9 frontend/components/cold-mail/ResumeSelection.tsx16

LoadingOverlay Implementation

Used in Cold Mail and Hiring Assistant pages to prevent interaction during API requests:

Features:

  • Full-screen semi-transparent backdrop
  • Centered spinner with status message
  • Prevents user interaction via z-index layering
  • Different messages for different states:
    • isGenerating: "Generating your email..." or "Generating answers..."
    • isEditing: "Editing..." or "Enhancing your draft..."

Implementation Example:

<LoadingOverlay isGenerating={isGenerating} isEditing={isEditing} />

The component conditionally renders based on boolean flags at frontend/app/dashboard/cold-mail/page.tsx593

PageLoader Implementation

Used for initial page load simulation:

Behavior:

const [isPageLoading, setIsPageLoading] = useState(true);

useEffect(() => {
  const timer = setTimeout(() => setIsPageLoading(false), 100);
  return () => clearTimeout(timer);
}, []);

Sources: frontend/app/dashboard/cold-mail/page.tsx35-36 frontend/app/dashboard/hiring-assistant/page.tsx44

Inline Loader Usage

Inline loaders appear within buttons during form submission:

Button Loading State Example:

<Button disabled={isGenerating}>
  {isGenerating ? (
    <>
      <Loader variant="spinner" size="sm" className="mr-2" />
      Generating...
    </>
  ) : (
    <>
      <Send className="mr-3 h-5 w-5" />
      Generate Cold Email
    </>
  )}
</Button>

Visual Enhancements:

Sources: frontend/app/dashboard/cold-mail/page.tsx701-774 frontend/app/dashboard/hiring-assistant/page.tsx456-512


File Upload Components

UploadResume Component

A standalone file upload component with form validation and progress indication.

Component Interface:

interface UploadResumeProps {
  onSuccess?: (result: any) => void;
  onError?: (error: string) => void;
}

Form Fields:

Field Type Purpose Validation
file File Resume file Required, specific extensions
customName string User-defined name Required, auto-filled from filename
showInCentral boolean Visibility toggle Optional

File Handling Flow:

  1. User selects file via <input type="file"> at frontend/components/upload-resume.tsx88-95
  2. Extension extracted and default name set at frontend/components/upload-resume.tsx22-24
  3. On submit, creates FormData with file and metadata at frontend/components/upload-resume.tsx38-41
  4. Posts to /api/analysis endpoint at frontend/components/upload-resume.tsx43-46
  5. Handles response and triggers callbacks at frontend/components/upload-resume.tsx48-60

Loading State: The component displays a spinner during upload with "Analyzing..." text at frontend/components/upload-resume.tsx142-165

Sources: frontend/components/upload-resume.tsx1-184


Design System Integration

Color Palette

All shared components use the consistent color scheme:

Color Variable Hex Value Usage
Primary Accent #76ABAE Active states, buttons, highlights
Dark Background #222831 Primary background
Secondary Background #31363F Cards, dropdowns
Light Text #EEEEEE Primary text
Muted Text #EEEEEE/70 Secondary text

Component Consistency:

  • All interactive elements use #76ABAE for hover/active states
  • Backdrop blur (backdrop-blur-xl) used consistently for glassmorphism effect
  • Border color border-white/10 or border-white/20 for subtle separation
  • Gradient backgrounds: from-white/5 to-white/10 for cards

Sources: frontend/components/navbar.tsx66 frontend/components/floating-action-button.tsx67 frontend/components/cold-mail/ResumeSelection.tsx112

Animation Patterns

Shared animation library using Framer Motion:

Standard Transitions:

  • Fade in: initial={{ opacity: 0 }}animate={{ opacity: 1 }}
  • Slide in: initial={{ y: 20 }}animate={{ y: 0 }}
  • Scale: whileHover={{ scale: 1.01 }}, whileTap={{ scale: 0.99 }}

Duration Standards:

  • Quick transitions: 200-300ms
  • Standard transitions: 300-500ms
  • Complex animations: 800ms with stagger delays

Example Usage:

<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  transition={{ duration: 0.8, delay: 0.4 }}
>
  {/* Component content */}
</motion.div>

Sources: frontend/app/dashboard/cold-mail/page.tsx597-602 frontend/components/floating-action-button.tsx36-52


Component Reusability Analysis

Cross-Feature Component Usage

Architecture Diagram

Component Adaptation Pattern: The ResumeSelection component demonstrates good reusability through:

  1. Conditional Features: customDraft mode only in Cold Mail
  2. Prop Flexibility: Different prop sets for different use cases
  3. Consistent Interface: Core functionality (existing/upload) works identically
  4. Auto-population: Intelligently fills form fields from resume metadata

Sources: frontend/components/cold-mail/ResumeSelection.tsx26-52 frontend/app/dashboard/cold-mail/page.tsx656-682 frontend/app/dashboard/hiring-assistant/page.tsx434-451

Component Library Structure

Component Category Location Reusability Level
Primitive UI components/ui/* High - Used everywhere
Navigation components/navbar.tsx, components/mobile-bottom-nav.tsx High - Global layout
Feature-Shared components/{feature}/ResumeSelection.tsx Medium - 2-3 features
Feature-Specific components/{feature}/*Panel.tsx Low - Single feature
Layout Wrappers LoadingOverlay, PageLoader Medium - Multiple features

Design Principle: Components become more specialized as they move from ui/ → root components/components/{feature}/. The most reusable primitives (Button, Input, Card) are in ui/, while feature-specific compositions are nested deeper.

Sources: frontend/components/navbar.tsx frontend/components/ui/toast.tsx frontend/components/cold-mail/ResumeSelection.tsx