A responsive React component for displaying paginated project cards with built-in search functionality.
npm install @asafarim/paginated-project-grid
Note: This package requires @asafarim/project-card
as a peer dependency.
import { PaginatedProjectGrid } from '@asafarim/paginated-project-grid';
const projects = [
{
id: '1',
title: 'E-commerce Platform',
description: 'A full-stack e-commerce solution with React and Node.js',
image: '/images/ecommerce.jpg',
techStacks: [
{ name: 'React', color: '#61dafb', icon: '⚛️' },
{ name: 'Node.js', color: '#339933', icon: '🟢' },
{ name: 'MongoDB', color: '#47A248', icon: '🍃' }
],
links: [
{ type: 'demo', url: 'https://demo.example.com' },
{ type: 'repo', url: 'https://github.com/user/repo' }
],
tags: [
{ name: 'Fullstack', onClick: () => alert('Fullstack') },
{ name: 'Ecommerce', onClick: () => alert('Ecommerce') }
],
category: 'web-development',
status: 'active',
featured: true,
priority: 'high',
budget: 15000,
progress: 75,
dateCreated: '2024-01-15',
dueDate: '2024-06-15',
lastUpdated: '2024-01-15',
isPublic: true
},
// ... more projects
];
function ProjectShowcase() {
return (
<PaginatedProjectGrid
projects={projects}
cardsPerPage={6}
currentTheme="dark"
enableSearch={true}
showTechStackIcons={true}
onProjectClick={(project) => {
console.log('Clicked project:', project.title);
}}
/>
);
}
Prop | Type | Default | Description |
---|---|---|---|
projects |
Project[] |
- | Required. Array of project objects |
cardsPerPage |
number |
6 |
Number of cards to display per page |
currentTheme |
'light' \| 'dark' \| 'auto' |
'dark' |
Theme for the grid |
className |
string |
'' |
Additional CSS classes |
onProjectClick |
(project: Project) => void |
- | Click handler for project cards |
showTechStackIcons |
boolean |
false |
Show icons in tech stack tags |
maxDescriptionLength |
number |
150 |
Maximum description length |
enableSearch |
boolean |
true |
Enable search functionality |
searchPlaceholder |
string |
"Search projects..." |
Search input placeholder |
noResultsMessage |
string |
"No projects found..." |
Message when no results |
loadingMessage |
string |
"Loading projects..." |
Loading state message |
isLoading |
boolean |
false |
Show loading state |
searchFields |
Array |
['title', 'description', 'techStacks', 'tags'] |
Fields to search in |
responsive |
object |
{mobile: 1, tablet: 2, desktop: 3, largeDesktop: 4, extraLargeDesktop: 5} |
Responsive breakpoints |
showLoadMore |
boolean |
false |
Use load more instead of pagination |
loadMoreText |
string |
"Load More" |
Load more button text |
animationDuration |
number |
300 |
Animation duration in ms |
interface Project {
id: string;
title: string;
description: string;
image?: string | ProjectImage;
techStacks: TechStackItem[]; // Required - from @asafarim/project-card
links: ProjectLink[]; // Required - from @asafarim/project-card
tags?: ProjectTag[]; // Enhanced tags with navigation and click handlers
category?: string;
status?: 'active' | 'archived' | 'in-progress' | 'completed' | 'draft' | 'coming-soon' | 'planning';
featured?: boolean;
priority?: 'low' | 'medium' | 'high' | 'critical';
budget?: number;
progress?: number; // Progress percentage (0-100)
dateCreated?: string; // ISO date string
dueDate?: string; // ISO date string
lastUpdated?: string; // ISO date string
isPublic?: boolean; // Public/private project flag
currentTheme?: Theme; // Individual project theme override
}
// ProjectTag interface for enhanced tag functionality
interface ProjectTag {
name: string;
navigateTo?: string; // URL to navigate to when tag is clicked
onClick?: () => void; // Function to execute when tag is clicked
}
// Import types from @asafarim/project-card
import type { TechStackItem, ProjectLink, Theme, ProjectImage } from '@asafarim/project-card';
The component now supports interactive tags with navigation and click handlers:
const projects = [
{
// ... other properties
tags: [
{ name: 'React', navigateTo: 'https://reactjs.org' },
{ name: 'TypeScript', navigateTo: 'https://typescriptlang.org' },
{ name: 'Custom Action', onClick: () => alert('Custom action!') }
]
}
];
low
: Low priority projectsmedium
: Medium priority projectshigh
: High priority projectscritical
: Critical priority projectsactive
: Currently active projectsarchived
: Archived projectsin-progress
: Projects in developmentcompleted
: Finished projectsdraft
: Draft projectscoming-soon
: Upcoming projectsplanning
: Projects in planning phaseTrack project completion with a progress percentage (0-100):
{
progress: 75, // 75% complete
// ... other properties
}
The component includes a collapsible search feature that can search across multiple fields:
<PaginatedProjectGrid
projects={projects}
enableSearch={true}
searchFields={['title', 'techStacks', 'tags']}
searchPlaceholder="Search by title, tech, or tags..."
/>
The grid automatically adapts to different screen sizes:
You can customize this behavior:
<PaginatedProjectGrid
projects={projects}
responsive=
/>
The component supports light and dark themes with dark theme as default:
// Dark theme (default)
<PaginatedProjectGrid
projects={projects}
currentTheme="dark"
/>
// Light theme
<PaginatedProjectGrid
projects={projects}
currentTheme="light"
/>
Choose between traditional pagination or load more functionality:
// Traditional pagination (default)
<PaginatedProjectGrid
projects={projects}
cardsPerPage={6}
/>
// Load more functionality
<PaginatedProjectGrid
projects={projects}
cardsPerPage={6}
showLoadMore={true}
loadMoreText="Show More Projects"
/>
The component uses CSS modules for styling. You can override styles by targeting the CSS classes:
/* Custom styles */
.custom-grid {
max-width: 1400px;
}
.custom-grid .projectCard {
border-radius: 16px;
}
The package includes full TypeScript definitions:
import type { PaginatedProjectGridProps, Project } from '@asafarim/paginated-project-grid';
const MyComponent: React.FC<{projects: Project[]}> = ({ projects }) => {
const handleProjectClick = (project: Project) => {
// project is fully typed
console.log(project.title);
console.log(project.priority);
console.log(project.progress);
};
return (
<PaginatedProjectGrid
projects={projects}
onProjectClick={handleProjectClick}
/>
);
};
MIT © Ali Safari