TOOLS_TOGGLE_SECTION_COMPONENT.md

Overview

The ToolsToggleSection component provides a user interface for viewing and configuring assistant tools. It displays enabled tools in a summary button and opens a detailed dialog for tool management with permission-based editing capabilities.

Purpose

  • Tool Configuration: Enable/disable assistant tools with visual feedback
  • Permission Management: Respect user edit permissions and read-only states
  • Tool Visualization: Display available tools with descriptions and status
  • Session Management: Support temporary tool changes for current session

Key Features

Tool Management

  • Toggle Interface: Switch-based tool enable/disable functionality
  • Visual Status: Clear indicators for active/inactive tools
  • Tool Information: Display tool icons, names, and descriptions
  • Count Display: Show number of enabled tools in summary button

Permission System

  • Read-Only Mode: View-only interface when editing not allowed
  • Edit Permissions: Permission-based tool configuration access
  • Session-Only Changes: Optional temporary tool modifications

Dialog Interface

  • Modal Dialog: Full-screen tool configuration interface
  • Scrollable Content: Handle large numbers of tools efficiently
  • Save/Cancel Workflow: Confirm or discard tool changes

Component Interface

interface ToolsToggleSectionProps {
  enabledTools: string[];               // Array of currently enabled tool IDs
  onToolsChange: (updatedTools: string[]) => void; // Tool change callback
  readOnly?: boolean;                   // Disable all editing (default: false)
  userHasEditPermission?: boolean;      // User can edit tools (default: false)
  sessionOnly?: boolean;                // Changes are session-only (default: true)
}

Core Functionality

1. Tool Display and Status

// Get tool objects with enabled status
const allToolObjects = AVAILABLE_TOOLS
  .filter(tool => enabledTools.includes(tool.id))
  .map(tool => ({
    ...tool,
    enabled: localTools.includes(tool.id)
  }));

// Summary button with tool count
<Button
  variant="outline"
  size="sm"
  className="w-full text-xs justify-between group"
  onClick={() => setToolDialogOpen(true)}
>
  <span className="flex items-center">
    <Settings className="h-3 w-3 mr-2" />
    {activeToolCount} {activeToolCount === 1 ? 'Tool' : 'Tools'} Enabled
  </span>
  {userHasEditPermission && !readOnly ? (
    <span className="text-primary opacity-0 group-hover:opacity-100 transition-opacity">
      Configure
    </span>
  ) : (
    <span>Details</span>
  )}
</Button>

2. Tool Toggle Logic

// Handle individual tool enable/disable
const handleToolToggle = (toolId: string) => {
  if (readOnly) return;
  
  const updatedTools = localTools.includes(toolId)
    ? localTools.filter(id => id !== toolId)
    : [...localTools, toolId];
  
  setLocalTools(updatedTools);
};

// Tool switch component
{!readOnly && userHasEditPermission ? (
  <Switch
    checked={tool.enabled}
    onCheckedChange={() => handleToolToggle(tool.id)}
    className="ml-2 mt-1"
  />
) : tool.enabled ? (
  <Check className="h-4 w-4 text-primary mt-1" />
) : null}

3. State Management

// Local state for temporary changes
const [toolDialogOpen, setToolDialogOpen] = useState(false);
const [localTools, setLocalTools] = useState<string[]>(enabledTools);

// Sync with props changes
useEffect(() => {
  setLocalTools(enabledTools);
}, [enabledTools]);

// Save/Cancel workflow
const handleSaveChanges = () => {
  onToolsChange(localTools);
  setToolDialogOpen(false);
};

const handleCancelChanges = () => {
  setLocalTools(enabledTools); // Reset to original state
  setToolDialogOpen(false);
};

4. Tool Rendering

// Individual tool display with status
{allToolObjects.map(tool => (
  <div 
    key={tool.id} 
    className={`flex items-start justify-between p-3 rounded-lg border ${
      tool.enabled ? 'bg-accent/30 border-accent' : 'bg-card border-border'
    }`}
  >
    <div className="space-y-1 flex-1">
      <div className="flex items-center gap-2">
        <tool.icon className={`h-5 w-5 ${tool.enabled ? 'text-primary' : 'text-muted-foreground'}`} />
        <h4 className="font-medium flex items-center gap-2">
          {tool.name}
          {tool.enabled && (
            <Badge variant="outline" className="ml-1 text-xs py-0">Active</Badge>
          )}
        </h4>
      </div>
      <p className="text-sm text-muted-foreground pl-7">
        {tool.description}
      </p>
    </div>
    
    {/* Toggle switch or status indicator */}
  </div>
))}

Permission-Based UI

Read-Only Mode

// View-only interface
{readOnly || !userHasEditPermission ? (
  tool.enabled ? (
    <Check className="h-4 w-4 text-primary mt-1" />
  ) : null
) : (
  <Switch
    checked={tool.enabled}
    onCheckedChange={() => handleToolToggle(tool.id)}
  />
)}
// Save/Cancel buttons only for editable mode
{!readOnly && userHasEditPermission && (
  <DialogFooter className="flex justify-between gap-2 pt-4 border-t">
    <div className="flex items-center text-sm text-muted-foreground">
      <span>
        {localTools.length} of {AVAILABLE_TOOLS.length} tools selected
      </span>
    </div>
    <div className="flex gap-2">
      <Button variant="outline" size="sm" onClick={handleCancelChanges}>
        Cancel
      </Button>
      <Button variant="default" size="sm" onClick={handleSaveChanges}>
        Save Changes
      </Button>
    </div>
  </DialogFooter>
)}

Integration Examples

Basic Usage

function AssistantConfiguration() {
  const [tools, setTools] = useState(['file-browser', 'document_search']);
  
  return (
    <ToolsToggleSection
      enabledTools={tools}
      onToolsChange={setTools}
      userHasEditPermission={true}
    />
  );
}

Read-Only Display

function AssistantPreview({ assistant }) {
  return (
    <div>
      <h3>{assistant.name}</h3>
      <ToolsToggleSection
        enabledTools={assistant.tools}
        onToolsChange={() => {}} // No-op for read-only
        readOnly={true}
      />
    </div>
  );
}

Permission-Based Access

function SmartToolsSection({ user, assistant }) {
  const canEdit = user.id === assistant.ownerId || user.role === 'admin';
  
  return (
    <ToolsToggleSection
      enabledTools={assistant.tools}
      onToolsChange={(tools) => updateAssistant(assistant.id, { tools })}
      userHasEditPermission={canEdit}
      readOnly={!canEdit}
    />
  );
}

Visual States

Summary Button States

  • Default: Shows tool count with “Details” text
  • Editable: Shows “Configure” on hover when user has permissions
  • Hover Effect: Smooth opacity transition for interactive elements

Tool Item States

  • Active: Accent background, primary text color, “Active” badge
  • Inactive: Default background, muted text color
  • Disabled: Grayed out when in read-only mode

Dialog States

  • Loading: Could be extended to show loading state during tool fetching
  • Empty: Shows message when no tools are available
  • Modified: Footer shows count of selected tools vs total available

Tool Integration

AVAILABLE_TOOLS Structure

// Expected tool object structure
interface Tool {
  id: string;           // Unique tool identifier
  name: string;         // Display name
  description: string;  // Tool description
  icon: LucideIcon;     // Icon component
  // Additional tool metadata...
}

Tool Filtering

// Component only shows tools that are in enabledTools
const allToolObjects = AVAILABLE_TOOLS
  .filter(tool => enabledTools.includes(tool.id))
  .map(tool => ({ ...tool, enabled: localTools.includes(tool.id) }));

Accessibility Features

  1. Keyboard Navigation: All interactive elements are keyboard accessible
  2. Screen Reader Support: Proper ARIA labels and semantic markup
  3. Focus Management: Logical tab order within dialog
  4. State Announcements: Switch changes announced to screen readers
  5. Role Indicators: Clear visual and textual permission indicators

Error Handling

  1. Missing Tools: Graceful handling when tool definitions are not found
  2. Permission Errors: Clear visual feedback for permission restrictions
  3. Save Failures: Could be extended to handle save operation errors
  4. State Consistency: Proper reset on cancel to maintain data integrity

Performance Optimizations

  1. Local State Management: Changes held locally until save confirmation
  2. Efficient Filtering: Tools filtered once and memoized
  3. Conditional Rendering: UI elements rendered based on permissions
  4. Event Optimization: Minimal re-renders on state changes