Skip to content

Searchable List Example ​

A searchable project list with real-time filtering using ProjectSearch.

Features ​

  • ProjectSearch - Search input with debounced input
  • ProjectList - List layout for projects
  • Real-time filtering - Updates as you type
  • Multi-field search - Searches name, tagline, description, and tags

Code ​

tsx
import { ProjectSearch, ProjectList, ProjectCard, useProjectSearch } from '@manningworks/projex'
import { useState } from 'react'

function SearchableProjects() {
  const [searchQuery, setSearchQuery] = useState('')

  const filteredProjects = useProjectSearch(projects, searchQuery, {
    threshold: 0.3
  })

  return (
    <div>
      <ProjectSearch
        onSearch={setSearchQuery}
        placeholder="Search projects..."
      />

      <ProjectList>
        {filteredProjects.map(project => (
          <ProjectCard key={project.id} project={project} />
        ))}
      </ProjectList>
    </div>
  )
}

HTML Output ​

The components generate semantic HTML:

html
<!-- ProjectSearch -->
<div data-projex-search>
  <input type="search" placeholder="Search projects..." />
</div>

<!-- ProjectList -->
<div data-projex-list>
  <div data-projex-card>
    <div data-projex-card-header>
      <h3>Project Name</h3>
    </div>
    <div data-projex-card-description>Description...</div>
  </div>
  <div data-projex-card>
    <!-- Card content -->
  </div>
</div>

Styling Example ​

CSS for the search input and list layout:

css
/* Search input */
[data-projex-search] input {
  width: 100%;
  padding: 12px 16px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  font-size: 1em;
  margin-bottom: 24px;
}

[data-projex-search] input:focus {
  outline: none;
  border-color: #6366f1;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}

/* List layout */
[data-projex-list] {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

/* List cards */
[data-projex-list] [data-projex-card] {
  display: flex;
  flex-direction: column;
  padding: 16px;
  border: 1px solid #e5e7eb;
  border-radius: 8px;
  background: #fff;
  transition: transform 0.2s, box-shadow 0.2s;
}

[data-projex-list] [data-projex-card]:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}

See the Styling Guide for more CSS examples.

Tips ​

  1. Debounce search input to avoid excessive re-renders (built-in to ProjectSearch)
  2. Search multiple fields for better results
  3. Highlight matches in UI for better UX
  4. Combine with filters for advanced search functionality

Customizing Search Sensitivity ​

The useProjectSearch hook uses Fuse.js fuzzy search with a default threshold of 0.3. You can adjust this for different behaviors:

tsx
import { useProjectSearch } from '@manningworks/projex'

function CustomSearch() {
  const [searchQuery, setSearchQuery] = useState('')

  // More precise matches (fewer results, fewer false positives)
  const strictResults = useProjectSearch(projects, searchQuery, {
    threshold: 0.1
  })

  // More lenient matches (allows more typos, more results)
  const lenientResults = useProjectSearch(projects, searchQuery, {
    threshold: 0.4
  })

  // Default behavior (balanced)
  const defaultResults = useProjectSearch(projects, searchQuery)

  // ...
}

When to Adjust Threshold ​

ThresholdUse CaseExample
0.1Exact/near-exact matchesSearch for specific package names or technical terms
0.3 (default)Balanced searchGeneral project showcase with good precision
0.3More lenientUser-facing search with typos allowed
0.4+Very fuzzyBroad discovery searches

For detailed information on search configuration, see Fuse Search Utilities.