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)}
/>
)}
Dialog Footer Conditional
// 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
- Keyboard Navigation: All interactive elements are keyboard accessible
- Screen Reader Support: Proper ARIA labels and semantic markup
- Focus Management: Logical tab order within dialog
- State Announcements: Switch changes announced to screen readers
- Role Indicators: Clear visual and textual permission indicators
Error Handling
- Missing Tools: Graceful handling when tool definitions are not found
- Permission Errors: Clear visual feedback for permission restrictions
- Save Failures: Could be extended to handle save operation errors
- State Consistency: Proper reset on cancel to maintain data integrity
Performance Optimizations
- Local State Management: Changes held locally until save confirmation
- Efficient Filtering: Tools filtered once and memoized
- Conditional Rendering: UI elements rendered based on permissions
- Event Optimization: Minimal re-renders on state changes