Skip to content

Commit c26bcd5

Browse files
davila7claude
andcommitted
🔍 Add Intelligent Search Functionality to Components Filter
- Added search button to filter buttons section with toggle functionality - Implemented real-time search across all component categories (except templates) - Search triggers after 3+ characters with 300ms debouncing for performance - Searches through component names, descriptions, categories, tags, and keywords - Added comprehensive search UI with input field, clear button, and results info - Display search results grouped by category with match scoring - Shows "No results" with helpful search suggestions when no matches found - Integrated with existing cart functionality and component installation commands - Added keyboard shortcuts (Escape to close, Enter to focus first result) - Responsive design with mobile-optimized search interface - Search data loaded from main components.json with fallback mechanisms Features: ✅ Search across agents, commands, settings, hooks, and MCPs ✅ Real-time results with intelligent scoring algorithm ✅ Category-based result grouping and filtering ✅ Keyboard navigation support ✅ Mobile-responsive search interface ✅ Integration with existing cart and installation workflows ✅ Performance optimized with debouncing and caching 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 24bea54 commit c26bcd5

File tree

3 files changed

+772
-0
lines changed

3 files changed

+772
-0
lines changed

docs/index.html

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,32 @@ <h3>Start Coding</h3>
201201
<button class="filter-btn" data-filter="templates" onclick="setUnifiedFilter('templates')">
202202
📦 Templates
203203
</button>
204+
<!-- Search Button -->
205+
<button class="filter-btn search-btn" id="searchToggleBtn" onclick="toggleSearch()" title="Search components">
206+
🔍 Search
207+
</button>
208+
</div>
209+
</div>
210+
211+
<!-- Search Bar -->
212+
<div class="search-bar-container" id="searchBarContainer" style="display: none;">
213+
<div class="search-input-wrapper">
214+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" class="search-icon">
215+
<path d="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z"/>
216+
</svg>
217+
<input type="text" id="searchInput" class="search-input" placeholder="Search agents, commands, settings, hooks, or MCPs..." oninput="handleSearchInput(event)" onkeydown="handleSearchKeydown(event)">
218+
<button class="clear-search-btn" id="clearSearchBtn" onclick="clearSearch()" style="display: none;" title="Clear search">
219+
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor">
220+
<path d="M19,6.41L17.59,5L12,10.59L6.41,5L5,6.41L10.59,12L5,17.59L6.41,19L12,13.41L17.59,19L19,17.59L13.41,12L19,6.41Z"/>
221+
</svg>
222+
</button>
223+
</div>
224+
<div class="search-results-info" id="searchResultsInfo" style="display: none;">
225+
<span class="results-count" id="resultsCount">0 results found</span>
226+
<div class="search-filters">
227+
<span class="search-filter-label">Found in:</span>
228+
<span class="search-filter-tags" id="searchFilterTags"></span>
229+
</div>
204230
</div>
205231
</div>
206232
</section>
@@ -543,5 +569,7 @@ <h4>
543569
<script src="js/cart-manager.js"></script>
544570
<script src="js/index-events.js"></script>
545571
<script src="js/modal-helpers.js"></script>
572+
<script src="js/generate-search-data.js"></script>
573+
<script src="js/search-functionality.js"></script>
546574
</body>
547575
</html>

docs/js/generate-search-data.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// Generate search data files from components.json
2+
// This script reads the main components.json and creates separate JSON files for each category
3+
4+
(async function generateSearchData() {
5+
try {
6+
// Read the main components.json file
7+
const response = await fetch('components.json');
8+
const data = await response.json();
9+
10+
console.log('Generating search data files...');
11+
12+
// Create separate files for each category
13+
const categories = ['agents', 'commands', 'settings', 'hooks', 'mcps', 'templates'];
14+
15+
for (const category of categories) {
16+
if (data[category] && Array.isArray(data[category])) {
17+
console.log(`Processing ${category}: ${data[category].length} items`);
18+
19+
// Process each component to ensure search-friendly structure
20+
const processedComponents = data[category].map(component => ({
21+
...component,
22+
// Add search-friendly fields
23+
searchableText: [
24+
component.name || component.title,
25+
component.description,
26+
component.category,
27+
...(component.tags || []),
28+
component.keywords || '',
29+
component.path || ''
30+
].filter(Boolean).join(' ').toLowerCase(),
31+
32+
// Normalize common fields
33+
title: component.name || component.title,
34+
displayName: (component.name || component.title || '').replace(/[-_]/g, ' '),
35+
category: category,
36+
37+
// Add tags if not present
38+
tags: component.tags || [component.category].filter(Boolean)
39+
}));
40+
41+
// Save to individual file (simulate file creation)
42+
// In a real scenario, this would write to the server filesystem
43+
console.log(`Would save ${category}.json with ${processedComponents.length} components`);
44+
45+
// For browser simulation, store in localStorage
46+
if (typeof localStorage !== 'undefined') {
47+
localStorage.setItem(`searchData_${category}`, JSON.stringify(processedComponents));
48+
}
49+
50+
// Also store in a global variable for immediate use
51+
window.searchDataCache = window.searchDataCache || {};
52+
window.searchDataCache[category] = processedComponents;
53+
}
54+
}
55+
56+
console.log('Search data generation complete!');
57+
58+
} catch (error) {
59+
console.error('Error generating search data:', error);
60+
}
61+
})();
62+
63+
// Function to get search data for a category
64+
function getSearchData(category) {
65+
// Try localStorage first
66+
if (typeof localStorage !== 'undefined') {
67+
const data = localStorage.getItem(`searchData_${category}`);
68+
if (data) {
69+
return JSON.parse(data);
70+
}
71+
}
72+
73+
// Try global cache
74+
if (window.searchDataCache && window.searchDataCache[category]) {
75+
return window.searchDataCache[category];
76+
}
77+
78+
return [];
79+
}
80+
81+
// Make function globally available
82+
window.getSearchData = getSearchData;

0 commit comments

Comments
 (0)