Templates Tab Component

The TemplatesTab component (src/components/TemplatesTab.tsx) provides a focused interface for managing saved response templates within chat applications.

Overview

This component offers template management functionality including creating, viewing, applying, and deleting saved templates. It’s designed to be used as a tab content within a larger tabbed interface or as a standalone template management section.

Key Features

Template Management

  • Save current input as a new template with custom title
  • Apply existing templates to input field
  • Delete templates (when not server-synchronized)
  • Template validation and error prevention

User Interface

  • Inline template creation form
  • Scrollable template list
  • Hover effects and visual feedback
  • Keyboard shortcuts (Enter to save)

Content Display

  • Template title and content preview
  • Intelligent content truncation (60 characters)
  • Empty state messaging
  • Delete button with confirmation prevention

Props Interface

interface TemplatesTabProps {
  templates: SavedTemplate[];
  currentInputValue: string;
  canSaveToServer: boolean;
  onApplyTemplate: (template: string) => void;
  onSaveTemplate: (title: string, content: string) => void;
  onDeleteTemplate: (templateId: string) => void;
}

Data Types

interface SavedTemplate {
  id: string;
  title: string;
  content: string;
}

Implementation Example

// Basic usage
<TemplatesTab
  templates={savedTemplates}
  currentInputValue={inputText}
  canSaveToServer={false}
  onApplyTemplate={(template) => setInputValue(template)}
  onSaveTemplate={(title, content) => {
    const newTemplate = { id: generateId(), title, content };
    setSavedTemplates([...savedTemplates, newTemplate]);
  }}
  onDeleteTemplate={(id) => {
    setSavedTemplates(templates.filter(t => t.id !== id));
  }}
/>

// With server synchronization
<TemplatesTab
  templates={serverTemplates}
  currentInputValue={inputText}
  canSaveToServer={true}
  onApplyTemplate={(template) => setInputValue(template)}
  onSaveTemplate={async (title, content) => {
    await saveTemplateToServer(title, content);
    refreshTemplates();
  }}
  onDeleteTemplate={(id) => {
    // Server templates cannot be deleted
    console.log('Server templates are read-only');
  }}
/>

Key Functionality

Template Creation

Provides an inline form for creating new templates:

const handleSaveTemplate = () => {
  if (currentInputValue.trim() && newTemplateTitle.trim()) {
    onSaveTemplate(newTemplateTitle.trim(), currentInputValue.trim());
    setNewTemplateTitle('');
    setShowSaveTemplate(false);
  }
};

Template Application

Click any template to apply its content:

<div 
  className="px-3 py-2 hover:bg-gray-100 cursor-pointer border-b"
  onClick={() => onApplyTemplate(template.content)}
>
  <div className="text-sm font-medium">{template.title}</div>
  <div className="text-xs text-gray-500 mt-1 truncate">
    {template.content.substring(0, 60)}
    {template.content.length > 60 ? '...' : ''}
  </div>
</div>

Auto-focus Management

Automatically focuses the title input when creating templates:

const toggleTemplateInput = () => {
  setShowSaveTemplate(!showSaveTemplate);
  if (!showSaveTemplate) {
    setTimeout(() => {
      const titleInput = document.getElementById('template-title-input');
      if (titleInput) {
        titleInput.focus();
      }
    }, 100);
  }
};

UI Structure

The component consists of three main sections:

Header Section

<div className="py-2 px-3 border-b flex justify-between items-center">
  <h4 className="font-medium">Response Templates</h4>
  <Button 
    variant="ghost" 
    size="sm" 
    onClick={toggleTemplateInput}
    className="h-7 px-2 text-xs"
    disabled={!currentInputValue.trim()}
  >
    {showSaveTemplate ? 'Cancel' : 'Save Current'}
  </Button>
</div>

Template Creation Form (Conditional)

{showSaveTemplate && (
  <div className="p-3 border-b">
    <input
      id="template-title-input"
      type="text"
      className="w-full p-2 text-sm border rounded mb-2"
      placeholder="Template title"
      value={newTemplateTitle}
      onChange={(e) => setNewTemplateTitle(e.target.value)}
      onKeyDown={(e) => {
        if (e.key === 'Enter') {
          handleSaveTemplate();
        }
      }}
    />
    <div className="flex justify-end">
      <Button 
        size="sm" 
        onClick={handleSaveTemplate}
        disabled={!newTemplateTitle.trim() || !currentInputValue.trim()}
      >
        Save Template
      </Button>
    </div>
  </div>
)}

Template List

<ScrollArea className="h-72">
  <div className="py-2">
    {templates.length === 0 ? (
      <div className="px-3 py-4 text-center text-gray-500 text-sm">
        No templates saved yet
      </div>
    ) : (
      templates.map((template) => (
        // Template items with apply and delete functionality
      ))
    )}
  </div>
</ScrollArea>

Dependencies

  • @/components/ui/button - Action buttons
  • @/components/ui/scroll-area - Scrollable content
  • lucide-react - X icon for delete action

State Management

The component manages internal states:

  • showSaveTemplate - Controls template creation form visibility
  • newTemplateTitle - Stores the title for new templates

Validation and Error Prevention

Input Validation

  • Requires both title and content to be non-empty
  • Trims whitespace from inputs
  • Disables save button when validation fails

Keyboard Shortcuts

  • Enter key submits template creation form
  • Focus management for better accessibility

Server Integration Modes

Local Mode (canSaveToServer: false)

  • Shows delete buttons for all templates
  • Templates stored locally
  • Full CRUD operations available

Server Mode (canSaveToServer: true)

  • Hides delete buttons (read-only mode)
  • Templates synchronized with server
  • Only read and apply operations available

Accessibility Features

  • Proper keyboard navigation
  • Auto-focus on template creation
  • Clear visual hierarchy
  • Semantic HTML structure
  • Screen reader friendly labels

Usage Patterns

This component is typically used within:

  • Chat interface sidebars
  • Template management modals
  • Tabbed interfaces (as demonstrated in HistoryTemplatesPopover)
  • Settings or preferences panels

The component provides a self-contained template management experience while remaining flexible enough to integrate with various parent components and data sources.