DOCUMENTS_COMPONENT.md

Overview

The Documents component (DocumentSidebar) is a sidebar component that displays assigned documents for assistants with proper file type icons, image previews, and external link handling. It integrates with the sidebar UI system and provides document access for authenticated users.

Purpose

  • Document Display: Show assigned documents in sidebar with file type icons
  • Image Preview: Special handling for image documents with thumbnail previews
  • External Links: Safe external document access with proper security attributes
  • User State Management: Conditional rendering based on authentication status

Key Features

File Type Detection

  • Icon Mapping: Automatic file type icons via DocumentHandler
  • Image Handling: Special preview for image documents
  • Fallback Support: Error handling for broken images
  • Content Type Detection: Support for MIME type and file extension detection
  • SidebarGroup Structure: Integrates with application sidebar system
  • Responsive Design: Truncated text with tooltips for long filenames
  • Empty States: Graceful handling when no documents are assigned

Component Interface

type DocumentSidebarProps = {
  documents: Document[];  // Array of assigned documents
  userState: UserState;   // User authentication state
};

interface Document {
  name: string;           // Document display name
  url: string;           // Document access URL
  type?: string;         // File type or extension
  contentType?: string;  // MIME content type
}

type UserState = 'not-logged-in' | 'receiver' | 'admin';

Core Functionality

1. Document Item Rendering

const DocumentItem = ({ doc }: { doc: Document }) => {
  const isImage = doc.contentType?.startsWith('image/');
  
  const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
    if (isImage) {
      e.preventDefault();
      window.open(doc.url, '_blank', 'noopener');
    }
  };

  const iconType = DocumentHandler.getFileIcon(doc.type || doc.contentType || '');
  const IconComponent = IconMap[iconType];

  return (
    <SidebarMenuItem>
      <SidebarMenuButton asChild>
        <a 
          href={doc.url} 
          target="_blank" 
          rel="noopener noreferrer"
          onClick={handleClick}
          className="flex items-center gap-2"
        >
          {isImage ? (
            <div className="relative w-4 h-4 overflow-hidden rounded">
              <Image 
                src={doc.url}
                alt={doc.name}
                width={16}
                height={16}
                className="object-cover"
                crossOrigin="anonymous"
                referrerPolicy="no-referrer"
              />
            </div>
          ) : (
            <IconComponent className="w-4 h-4 flex-shrink-0" />
          )}
          <span className="truncate" title={doc.name}>{doc.name}</span>
        </a>
      </SidebarMenuButton>
    </SidebarMenuItem>
  );
};

2. Authentication-Based Rendering

const DocumentSidebar = ({ documents, userState }: DocumentSidebarProps) => {
  if (userState === 'not-logged-in') {
    return <SidebarGroup></SidebarGroup>;
  }

  if (documents.length === 0) {
    return <SidebarGroup></SidebarGroup>;
  }

  return (
    <SidebarGroup>
      <SidebarGroupLabel>
        <span>Assigned Documents</span>
      </SidebarGroupLabel>
      <SidebarGroupContent>
        <SidebarMenu>
          {documents.map((doc, index) => (
            <DocumentItem key={index} doc={doc} />
          ))}
        </SidebarMenu>
      </SidebarGroupContent>
    </SidebarGroup>
  );
};

3. Image Error Handling

// Fallback mechanism for broken images
onError={(e) => {
  const target = e.target as HTMLImageElement;
  target.style.display = 'none';
  const IconFallback = IconMap.Image;
  const iconElement = document.createElement('div');
  iconElement.className = 'w-4 h-4';
  target.parentNode?.appendChild(iconElement);
}}

Integration Examples

Basic Usage

function ChatSidebar({ user, assistant }) {
  return (
    <Sidebar>
      <Documents 
        documents={assistant.documents}
        userState={user ? 'receiver' : 'not-logged-in'}
      />
    </Sidebar>
  );
}

With Assistant Context

function AssistantInterface({ assistant, user }) {
  const getUserState = () => {
    if (!user) return 'not-logged-in';
    if (user.email === assistant.adminEmail) return 'admin';
    return 'receiver';
  };

  return (
    <div className="app-layout">
      <AppSidebar>
        <Documents 
          documents={assistant.initialDocuments || []}
          userState={getUserState()}
        />
      </AppSidebar>
    </div>
  );
}

Document Handler Integration

File Type Detection

// Uses DocumentHandler utility for icon determination
const iconType = DocumentHandler.getFileIcon(doc.type || doc.contentType || '');
const IconComponent = IconMap[iconType];

// Expected icon types from DocumentHandler:
// - 'pdf', 'image', 'document', 'spreadsheet', 'presentation', 'archive', 'code', etc.

Icon Mapping

// IconMap provides React components for each file type
const IconMap = {
  pdf: PdfIcon,
  image: ImageIcon,
  document: FileTextIcon,
  spreadsheet: TableIcon,
  // ... more icon mappings
};

Features

Security

  • Safe External Links: rel="noopener noreferrer" for external document access
  • CORS Handling: Proper cross-origin and referrer policies for images
  • XSS Prevention: Safe handling of document URLs and names

Performance

  • Lazy Rendering: Only renders when documents exist and user is authenticated
  • Optimized Images: Next.js Image component for optimized loading
  • Efficient Updates: Component only re-renders when documents or user state changes

Accessibility

  • Screen Reader Support: Proper semantic markup with sidebar components
  • Keyboard Navigation: Full keyboard accessibility for document links
  • Tooltip Support: Full filenames available via title attributes
  • Focus Management: Logical tab order through document list

Visual Design

  • Consistent Icons: File type-appropriate icons for visual recognition
  • Image Previews: Thumbnail previews for image documents
  • Truncation: Long filenames handled with ellipsis and tooltips
  • Sidebar Integration: Consistent styling with application sidebar theme